Android自定义view实现日历打卡签到

本文实例为大家分享了Android自定义view实现日历打卡签到的具体代码,供大家参考,具体内容如下

1.说明

自己写一个view实现每天签到的功能,设置背景图片

源码下载

2.效果图

3.主界面

package com.example.myapplication30;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

import java.util.ArrayList;

import java.util.Calendar;

import java.util.List;

public class MainActivity extends AppCompatActivity {

//参考网址:https://blog.csdn.net/MacaoPark/article/details/102069775

private TextView mTvDaySum;

private TextView mTvMonth;

private SignView mCvCalendar;

private List<SignEntity> data;

private Calendar calendar;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTvDaySum = findViewById(R.id.punch_tv_day_sum);

mTvMonth = findViewById(R.id.punch_tv_month);

mCvCalendar = findViewById(R.id.punch_cv_calendar);

}

@Override

protected void onStart() {

super.onStart();

onReady();

}

@SuppressLint("SetTextI18n")

private void onReady() {

calendar = Calendar.getInstance();

int year = calendar.get(Calendar.YEAR);

int month = calendar.get(Calendar.MONTH);

//int date = calendar.get(Calendar.DATE);

int dayOfMonthToday = calendar.get(Calendar.DAY_OF_MONTH);

List<SignDate> signDates = new ArrayList<>();

signDates.add(new SignDate(2021, 5, 1, true));

signDates.add(new SignDate(2021, 5, 2, true));

signDates.add(new SignDate(2021, 5, 3, true));

signDates.add(new SignDate(2021, 5, 4, true));

signDates.add(new SignDate(2021, 5, 5, true));

mTvDaySum.setText("本期连续登录\t"+signDates.size()+"\t天");

mTvMonth.setText(year+"年"+getResources().getStringArray(R.array.month_array)[month]+"\t"+dayOfMonthToday+"日");

data = new ArrayList<>();

for (int i = 1; i <= dayOfMonthToday; i++) {

SignEntity signEntity = new SignEntity();

if (i == dayOfMonthToday) {

signEntity.setDayType(2);

} else {

signEntity.setDayType(1);

}

for (int j = 0; j < signDates.size(); j++) {

if (signDates.get(j).getDay() == i) {

signEntity.setDayType(0);

break;

} else if (dayOfMonthToday == i) {

signEntity.setDayType(2);

} else {

signEntity.setDayType(1);

}

}

data.add(signEntity);

}

SignAdapter signAdapter = new SignAdapter(data);

mCvCalendar.setAdapter(signAdapter);

}

}

4.适配器

package com.example.myapplication30;

import java.util.List;

/**

* SignAdapter

* Created by E.M on 2016/4/21.

*/

public class SignAdapter extends CalendarAdapter {

private List<SignEntity> data;

public SignAdapter(List<SignEntity> data) {

this.data = data;

}

@Override

public SignView.DayType getType(int dayOfMonth) {

return SignView.DayType.valueOf(data.get(dayOfMonth - 1).getDayType());

}

}

5.自定义view

package com.example.myapplication30;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.BitmapShader;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.ComposeShader;

import android.graphics.LinearGradient;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.PorterDuff;

import android.graphics.RadialGradient;

import android.graphics.Rect;

import android.graphics.Shader;

import android.graphics.SweepGradient;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import java.util.Calendar;

/**

* 签到日历控件

* Created by E.M on 2016/4/20.

*/

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 = 0xFFFF0000;

/**

* 未签到背景色

*/

private static final int COLOR_BACKGROUND_NORMAL = 0xFF9C9C9C;

/**

* 等待签到背景色

*/

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;

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);

verticalSpace = VERTICAL_SPACE;

verticalMargin = VERTICAL_MARGIN;

horizontalMargin = HORIZONTAL_MARGIN;

cellSize = CELL_SIZE;

waitLineSize = WAIT_LINE_SIZE;

}

private void initPaint() {

// int markerTextSize = resolutionUtil.formatVertical(MARKER_TEXT_SIZE);

// int cellTextSize = resolutionUtil.formatVertical(CELL_TEXT_SIZE);

int markerTextSize = MARKER_TEXT_SIZE;

int cellTextSize = 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.setColor(COLOR_TEXT_HIGHLIGHT);

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.STROKE);

paintBackgroundHighlight = new Paint();

paintBackgroundHighlight.setAntiAlias(true);

paintBackgroundHighlight.setStrokeWidth(2);

paintBackgroundHighlight.setStyle(Paint.Style.FILL);

//颜色

//paintBackgroundHighlight.setColor(COLOR_BACKGROUND_HIGHLIGHT);

//多种颜色数组

//int[] colors = {Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW,Color.MAGENTA};

//float[] position = {0f, 0.2f, 0.4f, 0.6f, 1.0f};

//Shader shader1 = new LinearGradient(100,850,600,850,colors,position,Shader.TileMode.CLAMP);

//paintBackgroundHighlight.setShader(shader1);

//设置背景图片

/* Bitmap placeholder = BitmapFactory.decodeResource(getResources(), R.mipmap.small);

Shader shader1 = new BitmapShader(placeholder, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

paintBackgroundHighlight.setShader(shader1);*/

}

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.drawCircle(x, y, cellSize/2, paintBackgroundHighlight);

// canvas.drawRect(x - 60, y - 60, x + 60, y + 60, paintBackgroundHighlight);// 正方形

// Bitmap placeholder = BitmapFactory.decodeResource(getResources(), R.mipmap.purtest);

// canvas.drawBitmap(placeholder,);wCircle(x, y, cellSize/2, paintBackgroundHighlight);

canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.small3),x-40, y-40 , paintBackgroundHighlight);

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;

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(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 DISABLED;

default:

return DISABLED;

}

}

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 Android自定义view实现日历打卡签到 的全部内容, 来源链接: utcz.com/p/243520.html

回到顶部