当前位置:   article > 正文

▲ Android 自定义日历签到效果_android 日历签到

android 日历签到

如果需要更多的定制化需求请直接看我这篇,Android 使用RecycleView自定义日历签到效果
,自定义日历2.0的功能远远大于我这个篇1.0的效果。

效果展示
在这里插入图片描述

自定义1.0的效果,适用于需求差不多,拿过来直接使用的。毕竟大家时间宝贵.
在这里插入图片描述
这里的这个图标是可以根据自己的需求更换的,比如连续签到有礼包的这种,还有忘记签到状态之类的。

代码实现

通过自定义View,把带有日历的Adapter加载到这个View中,然后通过这个View实现 OnTodayClickListener完成签到。

核心代码

public class SignView extends View {
    private static final String[] WEEK_MARK = {"一", "二", "三", "四", "五", "六", "日"};

    private static final int MAX_COLUMN = 7;
    /**
     * 周内
     */
    private static final int COLOR_MARKER_WEEKDAY = 0xFF999999;
    private static final int COLOR_MARKER_WEEKEND = 0xFF1B89CD;
    /**
     * 已签到背景色
     */
    private static final int COLOR_BACKGROUND_HIGHLIGHT = 0xFF1B89CD;
    /**
     * 未签到背景色
     */
    private static final int COLOR_BACKGROUND_NORMAL = 0xFFFFFFFF;
    /**
     * 等待签到背景色
     */
    private static final int COLOR_BACKGROUND_WAIT = 0xFFFE7471;
    /**
     * 已签到文字颜色
     */
    private static final int COLOR_TEXT_HIGHLIGHT = 0xFFFFFFFF;
    /**
     * 未签到文字颜色
     */
    private static final int COLOR_TEXT_NORMAL = 0xFF606060;
//    /**
//     * 不可用文字颜色
//     */
//    private static final int COLOR_TEXT_DISABLED = 0xFFD4D4D4;

    private static final int MARKER_TEXT_SIZE = 40;
    private static final int CELL_TEXT_SIZE = 40;

    private static final int VERTICAL_SPACE = 51;
    private static final int VERTICAL_MARGIN = 62;
    private static final int HORIZONTAL_MARGIN = 39;
    private static final int CELL_SIZE = 80;
    private static final int WAIT_LINE_SIZE = 14;

    private int dayOfMonthToday;
    private int markerTextY;
    private int verticalCellTop;
    private int sumDayOfMonth;
    private int daysOfFirstWeek;
    private int horizontalSpace;
    private int deltaTextCellY;
    private int deltaTextMarkerY;

    private int verticalSpace;
    private int verticalMargin;
    private int horizontalMargin;
    private int cellSize;
    private int waitLineSize;

    private Path waitPath;
    private Rect waitRect;
    private Paint paintWeekday;
    private Paint paintWeekend;
    private Paint paintTextNormal;
    private Paint paintTextHighlight;
    private Paint paintBackgroundWait;
    private Paint paintBackgroundNormal;
    private Paint paintBackgroundHighlight;
    private CalendarAdapter adapter;
    private ResolutionUtil resolutionUtil;
    private Paint paintReward;
    private Paint paintRewardX;
    public SignView(Context context) {
        this(context, null);
    }

    public SignView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public SignView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initResolution();
        initPaint();
        initData();
    }

    private void initResolution() {
        resolutionUtil = ResolutionUtil.getInstance();
        verticalSpace = resolutionUtil.formatVertical(VERTICAL_SPACE);
        verticalMargin = resolutionUtil.formatVertical(VERTICAL_MARGIN);
        horizontalMargin = resolutionUtil.formatHorizontal(HORIZONTAL_MARGIN);
        cellSize = resolutionUtil.formatVertical(CELL_SIZE);
        waitLineSize = resolutionUtil.formatVertical(WAIT_LINE_SIZE);
    }

    private void initPaint() {
        int markerTextSize = resolutionUtil.formatVertical(MARKER_TEXT_SIZE);
        int cellTextSize = resolutionUtil.formatVertical(CELL_TEXT_SIZE);

        paintWeekday = new Paint();
        paintWeekday.setAntiAlias(true);
        paintWeekday.setColor(COLOR_MARKER_WEEKDAY);
        paintWeekday.setTextSize(markerTextSize);
        paintWeekday.setTextAlign(Paint.Align.CENTER);

        paintWeekend = new Paint();
        paintWeekend.setAntiAlias(true);
        paintWeekend.setColor(COLOR_MARKER_WEEKEND);
        paintWeekend.setTextSize(markerTextSize);
        paintWeekend.setTextAlign(Paint.Align.CENTER);

        paintTextNormal = new Paint();
        paintTextNormal.setAntiAlias(true);
        paintTextNormal.setColor(COLOR_TEXT_NORMAL);
        paintTextNormal.setTextSize(cellTextSize);
        paintTextNormal.setTextAlign(Paint.Align.CENTER);

        //签到画笔颜色
        paintTextHighlight = new Paint();
        paintTextHighlight.setAntiAlias(true);
        paintTextHighlight.setAlpha(00);//透明度
        paintTextHighlight.setTextSize(cellTextSize);
        paintTextHighlight.setTextAlign(Paint.Align.CENTER);

        paintBackgroundWait = new Paint();
        paintBackgroundWait.setAntiAlias(true);
        paintBackgroundWait.setColor(COLOR_BACKGROUND_WAIT);
        paintBackgroundWait.setStrokeWidth(2);
        paintBackgroundWait.setStyle(Paint.Style.STROKE);

        //未签到 背景
        paintBackgroundNormal = new Paint();
        paintBackgroundNormal.setAntiAlias(true);
        paintBackgroundNormal.setColor(COLOR_BACKGROUND_NORMAL);
        paintBackgroundNormal.setStrokeWidth(2);
        paintBackgroundNormal.setStyle(Paint.Style.FILL);


        //已签到 背景
        paintBackgroundHighlight = new Paint();
        paintBackgroundHighlight.setAntiAlias(true);
       // paintBackgroundHighlight.setColor(COLOR_BACKGROUND_HIGHLIGHT);
        paintBackgroundHighlight.setStrokeWidth(2);
        paintBackgroundHighlight.setStyle(Paint.Style.FILL);

        //奖项
        paintReward = new Paint();
        paintReward.setAntiAlias(true);
        paintReward.setStrokeWidth(2);
        paintReward.setStyle(Paint.Style.FILL);

        paintRewardX = new Paint();
        paintRewardX.setAntiAlias(true);
        paintRewardX.setAlpha(00);//透明度
        paintRewardX.setTextSize(cellTextSize);
        paintRewardX.setTextAlign(Paint.Align.CENTER);
    }

    private void initData() {
        Paint.FontMetricsInt fmiMarker = paintWeekday.getFontMetricsInt();
        deltaTextMarkerY = -(fmiMarker.bottom - fmiMarker.top) / 2 - fmiMarker.top;
        markerTextY = verticalMargin + cellSize / 2;
        Paint.FontMetricsInt fmiCell = paintTextNormal.getFontMetricsInt();
        deltaTextCellY = -(fmiCell.bottom - fmiCell.top) / 2 - fmiCell.top;
        verticalCellTop = verticalMargin + cellSize;

        Calendar calendarToday = Calendar.getInstance();
        dayOfMonthToday = calendarToday.get(Calendar.DAY_OF_MONTH);
        int dayOfWeek;
        sumDayOfMonth = calendarToday.getActualMaximum(Calendar.DAY_OF_MONTH);

        Calendar calendarFirstDay = Calendar.getInstance();
        calendarFirstDay.set(Calendar.DAY_OF_MONTH, 1);
        dayOfWeek = calendarFirstDay.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek == Calendar.SUNDAY) {
            dayOfWeek = 7;
        } else {
            dayOfWeek = dayOfWeek - 1;
        }
        daysOfFirstWeek = MAX_COLUMN - dayOfWeek + 1;
    }

    private void createWaitBackground(int topX, int topY) {
        waitPath = new Path();
        waitPath.moveTo(topX, topY + waitLineSize);
        waitPath.lineTo(topX, topY);
        waitPath.lineTo(topX + waitLineSize, topY);

        waitPath.moveTo(topX + cellSize - waitLineSize, topY + cellSize);
        waitPath.lineTo(topX + cellSize, topY + cellSize);
        waitPath.lineTo(topX + cellSize, topY + cellSize - waitLineSize);

        waitRect = new Rect(topX, topY, topX + cellSize, topY + cellSize);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        horizontalSpace = (w - MAX_COLUMN * cellSize - horizontalMargin * 2) / (MAX_COLUMN - 1);
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        drawWeekMark(canvas);
        drawCellsBackground(canvas);
        drawCells(canvas);
    }

    private void drawWeekMark(Canvas canvas) {
        int y = markerTextY + deltaTextMarkerY;
        for (int i = 0; i < 7; i++) {
            int x = horizontalMargin + i * (horizontalSpace + cellSize)
                    + cellSize / 2;
            if (i < 5) {
                canvas.drawText(WEEK_MARK[i], x, y, paintWeekday);
            } else {
                canvas.drawText(WEEK_MARK[i], x, y, paintWeekend);
            }
        }
    }

    private void drawCellsBackground(Canvas canvas) {
        for (int i = 1; i <= dayOfMonthToday; i++) {
            drawCellBackground(canvas, i, getColumnIndex(i), getRowIndex(i));
        }
    }

    /**
     * 根据行列序号绘制日期背景
     *
     * @param canvas     画布
     * @param dayOfMonth 日期
     * @param column     列序号
     * @param row        行序号
     */
    private void drawCellBackground(Canvas canvas, int dayOfMonth, int column, int row) {
        int x = horizontalMargin + column * (horizontalSpace + cellSize)
                + cellSize / 2;
        int y = verticalCellTop + verticalSpace * (row + 1) + cellSize * row + cellSize / 2;
        if (adapter != null) {
            DayType dayType = adapter.getType(dayOfMonth);
            switch (dayType) {
                case WAITING:
                    if (waitPath == null) {
                        createWaitBackground(x - cellSize / 2, y - cellSize / 2);
                    }
                    canvas.drawPath(waitPath, paintBackgroundWait);
                    break;
                case SIGNED:
                    canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.icon_m), x-30, y-30, paintBackgroundHighlight);
                    break;
                case REWARD:
                   canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.icon_j), x-30, y-30, paintReward);
                   // canvas.drawCircle(x, y, cellSize / 2, paintBackgroundNormal);
                    break;
                default:
                    canvas.drawCircle(x, y, cellSize / 2, paintBackgroundNormal);
                    break;
            }
        } else {
            canvas.drawCircle(x, y, cellSize / 2, paintBackgroundNormal);
        }
    }

    private void drawCells(Canvas canvas) {
        for (int i = 1; i <= sumDayOfMonth; i++) {
            drawCell(canvas, i, getColumnIndex(i), getRowIndex(i));
        }
    }

    /**
     * 根据行列序号绘制日期
     *
     * @param canvas     画布
     * @param dayOfMonth 日期
     * @param column     列序号
     * @param row        行序号
     */
    private void drawCell(Canvas canvas, int dayOfMonth, int column, int row) {
        int x = horizontalMargin + column * (horizontalSpace + cellSize)
                + cellSize / 2;
        int y = verticalCellTop + verticalSpace * (row + 1) + cellSize * row + cellSize / 2
                + deltaTextCellY;
        if (adapter != null && dayOfMonth <= dayOfMonthToday) {
            DayType dayType = adapter.getType(dayOfMonth);
            Paint paint;
            switch (dayType) {
                case SIGNED:
                    paint = paintTextHighlight;
                    break;
                case REWARD:
                    paint = paintRewardX;
                    break;
                default:
                    paint = paintTextNormal;
                    break;
            }
            canvas.drawText(String.valueOf(dayOfMonth), x, y, paint);
        } else {
            canvas.drawText(String.valueOf(dayOfMonth), x, y, paintTextNormal);
        }
    }

    /**
     * 获取列序号
     *
     * @param dayOfMonth 日期
     * @return 列序号
     */
    private int getColumnIndex(int dayOfMonth) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek == Calendar.SUNDAY) {
            dayOfWeek = 6;
        } else {
            dayOfWeek = dayOfWeek - 2;
        }
        return dayOfWeek;
    }

    /**
     * 获取行序号
     *
     * @param dayOfMonth 日期
     * @return 行序号
     */
    private int getRowIndex(int dayOfMonth) {
        float weight = (dayOfMonth - daysOfFirstWeek) / (MAX_COLUMN * 1f);
        double rowIndexDouble = Math.abs(Math.ceil(weight));
        return (int) rowIndexDouble;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            float x = event.getX();
            float y = event.getY();
            if (waitPath != null) {
                if (adapter.getType(dayOfMonthToday).equals(DayType.WAITING)) {
                    if (x >= waitRect.left && y >= waitRect.top && x <= waitRect.right && y <= waitRect.bottom) {
                        if (onTodayClickListener != null) {
                            onTodayClickListener.onTodayClick();
                        }
                    }
                }
            }
        }
        return true;
    }

    public void setAdapter(CalendarAdapter adapter) {
        this.adapter = adapter;
        this.invalidate();
    }

    public int getDayOfMonthToday() {
        return dayOfMonthToday;
    }

    public void notifyDataSetChanged() {
        invalidate();
    }

    private OnTodayClickListener onTodayClickListener;

    public void setOnTodayClickListener(OnTodayClickListener onTodayClickListener) {
        this.onTodayClickListener = onTodayClickListener;
    }

    public interface OnTodayClickListener {
        void onTodayClick();
    }

    public enum DayType {
        /**
         * 已签到状态,时间已过
         */
        SIGNED(0),
        /**
         * 未签到状态,时间已过
         */
        UNSIGNED(1),
        /**
         * 等待状态,即当日还未签到
         */
        WAITING(2),
        /**
         * 不可达到状态,未到时间
         */
        UNREACHABLE(3),
        /**
         * 不可用状态,非当前月份
         */
        DISABLED(5),

        /**
         * 奖赏
         */
        REWARD(4);

        private int value;

        DayType(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public static DayType valueOf(int value) {
            switch (value) {
                case 0:
                    return SIGNED;
                case 1:
                    return UNSIGNED;
                case 2:
                    return WAITING;
                case 3:
                    return UNREACHABLE;
                case 4:
                    return REWARD;
                case 5:
                    return DISABLED;
                default:
                    return DISABLED;
            }
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433

【源码地址】

[希望这篇文章可以帮到你]

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/930186
推荐阅读
相关标签
  

闽ICP备14008679号