Android自定义按周签到打卡功能实例代码

前言

之前实现过《Android可签到的日历控件》的功能,跟这篇一样都是实现签到打卡功能,这篇实现的是按月进行打卡做标识,本篇内容实现的按周进行签到打卡。

实现签到规则如下:

1、连续签到7天,即可获得额外积分奖励。

2、连续签到记录在第8天开始时将清零重新计算。

3、如果中断签到,连续签到记录也将清零。

实现步骤:

1.效果图

2.自定义签到打卡View

3.主程序逻辑处理

4.主界面

5.签到bean

6.总结

实现过程:

1.效果图

2.自定义签到打卡View

/**
 * description: 自定义签到View.
 */
public class StepsView extends View {

 /**
 * 动画执行的时间 230毫秒
 */
 private final static int ANIMATION_TIME = 230;
 /**
 * 动画执行的间隔次数
 */
 private final static int ANIMATION_INTERVAL = 10;

 /**
 * 线段的高度
 */
 private float mCompletedLineHeight = CalcUtils.dp2px(getContext(), 2f);

 /**
 * 图标宽度
 */
 private float mIconWidth = CalcUtils.dp2px(getContext(), 21.5f);
 /**
 * 图标的高度
 */
 private float mIconHeight = CalcUtils.dp2px(getContext(), 24f);
 /**
 * UP宽度
 */
 private float mUpWidth = CalcUtils.dp2px(getContext(), 20.5f);
 /**
 * up的高度
 */
 private float mUpHeight = CalcUtils.dp2px(getContext(), 12f);

 /**
 * 线段长度
 */
 private float mLineWidth = CalcUtils.dp2px(getContext(), 25f);

 /**
 * 已经完成的图标
 */
 private Drawable mCompleteIcon;
 /**
 * 正在进行的图标
 */
 private Drawable mAttentionIcon;
 /**
 * 默认的图标
 */
 private Drawable mDefaultIcon;
 /**
 * UP图标
 */
 private Drawable mUpIcon;
 /**
 * 图标中心点Y
 */
 private float mCenterY;
 /**
 * 线段的左上方的Y
 */
 private float mLeftY;
 /**
 * 线段的右下方的Y
 */
 private float mRightY;

 /**
 * 数据源
 */
 private List<StepBean> mStepBeanList;
 private int mStepNum = 0;

 /**
 * 图标中心点位置
 */
 private List<Float> mCircleCenterPointPositionList;
 /**
 * 未完成的线段Paint
 */
 private Paint mUnCompletedPaint;
 /**
 * 完成的线段paint
 */
 private Paint mCompletedPaint;
 /**
 * 未完成颜色
 */
 private int mUnCompletedLineColor = ContextCompat.getColor(getContext(), R.color.c_d5a872);
 /**
 * 积分颜色
 */
 private int mUnCompletedTextColor = ContextCompat.getColor(getContext(), R.color.c_cccccc);

 /**
 * 天数颜色
 */
 private int mUnCompletedDayTextColor = ContextCompat.getColor(getContext(), R.color.c_736657);

 /**
 * up魅力值颜色
 */
 private int mCurrentTextColor = ContextCompat.getColor(getContext(), R.color.c_white);
 /**
 * 完成的颜色
 */
 private int mCompletedLineColor = ContextCompat.getColor(getContext(), R.color.c_d5a872);

 private Paint mTextNumberPaint;

 private Paint mTextDayPaint;

 /**
 * 是否执行动画
 */
 private boolean isAnimation = false;

 /**
 * 记录重绘次数
 */
 private int mCount = 0;

 /**
 * 执行动画线段每次绘制的长度,线段的总长度除以总共执行的时间乘以每次执行的间隔时间
 */
 private float mAnimationWidth = (mLineWidth / ANIMATION_TIME) * ANIMATION_INTERVAL;

 /**
 * 执行动画的位置
 */
 private int mPosition;
 private int[] mMax;

 public StepsView(Context context) {
 this(context, null);
 }

 public StepsView(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
 }

 public StepsView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 init();
 }

 /**
 * init
 */
 private void init() {
 mStepBeanList = new ArrayList<>();

 mCircleCenterPointPositionList = new ArrayList<>();

 //未完成文字画笔
 mUnCompletedPaint = new Paint();
 mUnCompletedPaint.setAntiAlias(true);
 mUnCompletedPaint.setColor(mUnCompletedLineColor);
 mUnCompletedPaint.setStrokeWidth(2);
 mUnCompletedPaint.setStyle(Paint.Style.FILL);

 //已完成画笔文字
 mCompletedPaint = new Paint();
 mCompletedPaint.setAntiAlias(true);
 mCompletedPaint.setColor(mCompletedLineColor);
 mCompletedPaint.setStrokeWidth(2);
 mCompletedPaint.setStyle(Paint.Style.FILL);

 //number paint
 mTextNumberPaint = new Paint();
 mTextNumberPaint.setAntiAlias(true);
 mTextNumberPaint.setColor(mUnCompletedTextColor);
 mTextNumberPaint.setStyle(Paint.Style.FILL);
 mTextNumberPaint.setTextSize(CalcUtils.sp2px(getContext(), 10f));

 //number paint
 mTextDayPaint = new Paint();
 mTextDayPaint.setAntiAlias(true);
 mTextDayPaint.setColor(mUnCompletedDayTextColor);
 mTextDayPaint.setStyle(Paint.Style.FILL);
 mTextDayPaint.setTextSize(CalcUtils.sp2px(getContext(), 12f));

 //已经完成的icon
 mCompleteIcon = ContextCompat.getDrawable(getContext(), R.drawable.sign);
 //正在进行的icon
 mAttentionIcon = ContextCompat.getDrawable(getContext(), R.drawable.unsign);
 //未完成的icon
 mDefaultIcon = ContextCompat.getDrawable(getContext(), R.drawable.unsign);
 //UP的icon
 mUpIcon = ContextCompat.getDrawable(getContext(), R.drawable.jifendikuai);
 }

 @Override
 protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
 }

 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
 super.onSizeChanged(w, h, oldw, oldh);
 setChange();
 }

 private void setChange() {
 //图标的中中心Y点
 mCenterY = CalcUtils.dp2px(getContext(), 28f) + mIconHeight / 2;
 //获取左上方Y的位置,获取该点的意义是为了方便画矩形左上的Y位置
 mLeftY = mCenterY - (mCompletedLineHeight / 2);
 //获取右下方Y的位置,获取该点的意义是为了方便画矩形右下的Y位置
 mRightY = mCenterY + mCompletedLineHeight / 2;

 //计算图标中心点
 mCircleCenterPointPositionList.clear();
 //第一个点距离父控件左边14.5dp
 float size = mIconWidth / 2 + CalcUtils.dp2px(getContext(), 23f);
 mCircleCenterPointPositionList.add(size);

 for (int i = 1; i < mStepNum; i++) {
  //从第二个点开始,每个点距离上一个点为图标的宽度加上线段的23dp的长度
  size = size + mIconWidth + mLineWidth;
  mCircleCenterPointPositionList.add(size);
 }
 }

 @SuppressLint("DrawAllocation")
 @Override
 protected synchronized void onDraw(Canvas canvas) {
 super.onDraw(canvas);

 if (mStepBeanList.size() != 0) {
  if (isAnimation) {
  drawSign(canvas);
  } else {
  drawUnSign(canvas);
  }
 }
 }

 /**
 * 绘制签到(伴随签到动画)
 */
 @SuppressLint("DrawAllocation")
 private void drawSign(Canvas canvas) {
 for (int i = 0; i < mCircleCenterPointPositionList.size(); i++) {
  //绘制线段
  float preComplectedXPosition = mCircleCenterPointPositionList.get(i) + mIconWidth / 2;
  if (i != mCircleCenterPointPositionList.size() - 1) {
  //最后一条不需要绘制
  if (mStepBeanList.get(i + 1).getState() == StepBean.STEP_COMPLETED) {
   //下一个是已完成,当前才需要绘制
   canvas.drawRect(preComplectedXPosition, mLeftY, preComplectedXPosition + mLineWidth,
    mRightY, mCompletedPaint);
  } else {
   //其余绘制灰色

   //当前位置执行动画
   if (i == mPosition - 1) {
   //绿色开始绘制的地方,
   float endX = preComplectedXPosition + mAnimationWidth * (mCount / ANIMATION_INTERVAL);
   //绘制
   canvas.drawRect(preComplectedXPosition, mLeftY, endX, mRightY, mCompletedPaint);
   //绘制
   canvas.drawRect(endX, mLeftY, preComplectedXPosition + mLineWidth,
    mRightY, mUnCompletedPaint);
   } else {
   canvas.drawRect(preComplectedXPosition, mLeftY, preComplectedXPosition + mLineWidth,
    mRightY, mUnCompletedPaint);
   }
  }
  }

  //绘制图标
  float currentComplectedXPosition = mCircleCenterPointPositionList.get(i);
  Rect rect = new Rect((int) (currentComplectedXPosition - mIconWidth / 2),
   (int) (mCenterY - mIconHeight / 2),
   (int) (currentComplectedXPosition + mIconWidth / 2),
   (int) (mCenterY + mIconHeight / 2));

  StepBean stepsBean = mStepBeanList.get(i);

  if (i == mPosition && mCount == ANIMATION_TIME) {
  //当前需要绘制
  mCompleteIcon.setBounds(rect);
  mCompleteIcon.draw(canvas);
  } else {
  if (stepsBean.getState() == StepBean.STEP_UNDO) {
   mDefaultIcon.setBounds(rect);
   mDefaultIcon.draw(canvas);
  } else if (stepsBean.getState() == StepBean.STEP_CURRENT) {
   mAttentionIcon.setBounds(rect);
   mAttentionIcon.draw(canvas);
  } else if (stepsBean.getState() == StepBean.STEP_COMPLETED) {
   mCompleteIcon.setBounds(rect);
   mCompleteIcon.draw(canvas);
  }
  }

  //绘制图标
  if (stepsBean.getState() == StepBean.STEP_COMPLETED || (i == mPosition
   && mCount == ANIMATION_TIME)) {
  //已经完成了或者是当前动画完成并且需要当前位置需要改变
  if (stepsBean.getNumber() != 0) {
   //是up的需要橙色
   mTextNumberPaint.setColor(mCurrentTextColor);
  } else {
   //普通完成的颜色
   mTextNumberPaint.setColor(mCompletedLineColor);
  }
  } else {
  //还没签到的,颜色均为灰色
  mTextNumberPaint.setColor(mUnCompletedLineColor);
  }

  //绘制UP
  if (stepsBean.getNumber() != 0) {
  //需要UP才进行绘制
  Rect rectUp =
   new Rect((int) (currentComplectedXPosition - mUpWidth / 2),
    (int) (mCenterY - mIconHeight / 2 - CalcUtils.dp2px(getContext(), 8f) - mUpHeight),
    (int) (currentComplectedXPosition + mUpWidth / 2),
    (int) (mCenterY - mIconHeight / 2 - CalcUtils.dp2px(getContext(), 1f)));
  mUpIcon.setBounds(rectUp);
  mUpIcon.draw(canvas);
  }

  //0表示不需要显示积分,非0表示需要消失积分
  if (stepsBean.getNumber() != 0) {
  canvas.drawText("+" + stepsBean.getNumber(),
   currentComplectedXPosition - CalcUtils.dp2px(getContext(), 8f),
   mCenterY / 2 - CalcUtils.dp2px(getContext(), 0.5f),
   mTextNumberPaint);
  }
  //天数文字
  canvas.drawText(stepsBean.getDay(),
   currentComplectedXPosition - CalcUtils.dp2px(getContext(), 12f),
   mCenterY + CalcUtils.dp2px(getContext(), 30f),
   mTextDayPaint);
 }

 //记录重绘次数
 mCount = mCount + ANIMATION_INTERVAL;
 if (mCount <= ANIMATION_TIME) {
  //引起重绘
  postInvalidate();
 } else {
  //重绘完成
  isAnimation = false;
  mCount = 0;
 }
 }

 /**
 * 绘制初始状态的view
 */
 @SuppressLint("DrawAllocation")
 private void drawUnSign(Canvas canvas) {

 for (int i = 0; i < mCircleCenterPointPositionList.size(); i++) {
  //绘制线段
  float preComplectedXPosition = mCircleCenterPointPositionList.get(i) + mIconWidth / 2;
  if (i != mCircleCenterPointPositionList.size() - 1) {
  //最后一条不需要绘制
  if (mStepBeanList.get(i + 1).getState() == StepBean.STEP_COMPLETED) {
   //下一个是已完成,当前才需要绘制
   canvas.drawRect(preComplectedXPosition, mLeftY, preComplectedXPosition + mLineWidth,
    mRightY, mCompletedPaint);
  } else {
   //其余绘制灰色
   canvas.drawRect(preComplectedXPosition, mLeftY, preComplectedXPosition + mLineWidth,
    mRightY, mUnCompletedPaint);
  }
  }

  //绘制图标
  float currentComplectedXPosition = mCircleCenterPointPositionList.get(i);
  Rect rect = new Rect((int) (currentComplectedXPosition - mIconWidth / 2),
   (int) (mCenterY - mIconHeight / 2),
   (int) (currentComplectedXPosition + mIconWidth / 2),
   (int) (mCenterY + mIconHeight / 2));

  StepBean stepsBean = mStepBeanList.get(i);

  if (stepsBean.getState() == StepBean.STEP_UNDO) {
  mDefaultIcon.setBounds(rect);
  mDefaultIcon.draw(canvas);
  } else if (stepsBean.getState() == StepBean.STEP_CURRENT) {
  mAttentionIcon.setBounds(rect);
  mAttentionIcon.draw(canvas);
  } else if (stepsBean.getState() == StepBean.STEP_COMPLETED) {
  mCompleteIcon.setBounds(rect);
  mCompleteIcon.draw(canvas);
  }

  //绘制增加的分数数目
  if (stepsBean.getState() == StepBean.STEP_COMPLETED) {
  //已经完成了
  if (stepsBean.getNumber() != 0) {
   //是up的需要橙色
   mTextNumberPaint.setColor(mCurrentTextColor);
  } else {
   //普通完成的颜色
   mTextNumberPaint.setColor(mCompletedLineColor);
  }
  } else {
  //还没签到的,颜色均为灰色
  mTextNumberPaint.setColor(mUnCompletedLineColor);
  }

  //绘制UP
  if (stepsBean.getNumber() != 0) {
  //需要UP才进行绘制
  Rect rectUp =
   new Rect((int) (currentComplectedXPosition - mUpWidth / 2),
    (int) (mCenterY - mIconHeight / 2 - CalcUtils.dp2px(getContext(), 8f) - mUpHeight),
    (int) (currentComplectedXPosition + mUpWidth / 2),
    (int) (mCenterY - mIconHeight / 2 - CalcUtils.dp2px(getContext(), 1f)));
  mUpIcon.setBounds(rectUp);
  mUpIcon.draw(canvas);
  }

  //0表示不需要显示积分,非0表示需要消失积分
  if (stepsBean.getNumber() != 0) {
  //积分文字
  canvas.drawText("+" + stepsBean.getNumber(),
   currentComplectedXPosition - CalcUtils.dp2px(getContext(), 8f),
   mCenterY / 2 - CalcUtils.dp2px(getContext(), 0.5f),
   mTextNumberPaint);
  }

  //天数文字
  canvas.drawText(stepsBean.getDay(),
   currentComplectedXPosition - CalcUtils.dp2px(getContext(), 12f),
   mCenterY + CalcUtils.dp2px(getContext(), 30f),
   mTextDayPaint);
 }
 }

 /**
 * 设置流程步数
 *
 * @param stepsBeanList 流程步数
 */
 public void setStepNum(List<StepBean> stepsBeanList) {

 if (stepsBeanList == null && stepsBeanList.size() == 0) {
  return;
 }
 mStepBeanList = stepsBeanList;
 mStepNum = mStepBeanList.size();
 setChange();//重新绘制

 //引起重绘
 postInvalidate();
 }

 /**
 * 执行签到动画
 *
 * @param position 执行的位置
 */
 public void startSignAnimation(int position) {
 //线条从灰色变为绿色
 isAnimation = true;
 mPosition = position;
 //引起重绘
 postInvalidate();
 }
}

3.主程序逻辑处理

/**
 * 一周签到规则:
 * 1、连续签到7天,即可额外获得15积分奖励
 * 2、连续签到记录在第8天开始时将清零重新计算
 * 3、如果中断签到,连续签到记录也将清零
 *
 * 注:可以显示签到的动画,这里没有使用动画
 * 需要动画可以调用mStepView.startSignAnimation(int position)
 * position表示需要做动画的位置
 */
public class MainActivity extends AppCompatActivity {

 private StepsView mStepView;
 private RelativeLayout rl_oval;
 private TextView text_sign;
 private TextView text_lianxusign;
 private ArrayList<StepBean> mStepBeans = new ArrayList<>();

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  initView();

  initData();

  initListener();
 }

 private void initListener() {

  rl_oval.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    //点击签到按钮,请求后台接口数据
    //模拟请求接口数据成功
    requestSuccessData();
   }
  });
 }

 /**
  * 模拟请求接口数据成功后更新数据
  */
 private void requestSuccessData() {
  mStepBeans.clear();//清空初始化数据
  String reponse = "{\n" +
    " \"datas\": {\n" +
    "  \"day\": 3,\n" +
    "  \"myPoint\": 10890,\n" +
    "  \"signLog\": {\n" +
    "   \"content\": \"每日签到\",\n" +
    "   \"createTime\": \"2019-05-29 09:42:05\",\n" +
    "   \"familyId\": \"0\",\n" +
    "   \"id\": \"951660\",\n" +
    "   \"integral\": \"4\",\n" +
    "   \"logType\": \"3\",\n" +
    "   \"orderId\": \"0\",\n" +
    "   \"type\": \"1\",\n" +
    "   \"userId\": \"43431\"\n" +
    "  },\n" +
    "  \"signState\": true,\n" +
    "  \"userSingninList\": [\n" +
    "   {\n" +
    "    \"createTime\": \"2019-05-27 18:04:15\",\n" +
    "    \"day\": \"1\",\n" +
    "    \"familyId\": \"0\",\n" +
    "    \"id\": \"278904\",\n" +
    "    \"seriesDay\": \"1\",\n" +
    "    \"type\": \"0\",\n" +
    "    \"userId\": \"43431\"\n" +
    "   },\n" +
    "   {\n" +
    "    \"createTime\": \"2019-05-28 09:31:02\",\n" +
    "    \"day\": \"2\",\n" +
    "    \"familyId\": \"0\",\n" +
    "    \"id\": \"278905\",\n" +
    "    \"seriesDay\": \"2\",\n" +
    "    \"type\": \"0\",\n" +
    "    \"userId\": \"43431\"\n" +
    "   },\n" +
    "   {\n" +
    "    \"createTime\": \"2019-05-29 09:42:05\",\n" +
    "    \"day\": \"3\",\n" +
    "    \"familyId\": \"0\",\n" +
    "    \"id\": \"278907\",\n" +
    "    \"seriesDay\": \"3\",\n" +
    "    \"type\": \"0\",\n" +
    "    \"userId\": \"43431\"\n" +
    "   }\n" +
    "  ]\n" +
    " },\n" +
    " \"msg\": \"success!\",\n" +
    " \"ret\": 0\n" +
    "}";

  //解析后台请求数据
  SignListReq signListReq = new Gson().fromJson(reponse, SignListReq.class);
  if (signListReq.getRet() == 0) {
   rl_oval.setBackgroundResource(R.drawable.lianxusign_bg);
   text_sign.setText("已签到");
   text_lianxusign.setVisibility(View.VISIBLE);
   text_lianxusign.setText("连续" + signListReq.getDatas().getDay() + "天");

   setSignData(signListReq.getDatas());
  }

 }

 private void initView() {
  mStepView = findViewById(R.id.step_view);
  rl_oval = findViewById(R.id.rl_oval);
  text_sign = findViewById(R.id.text_sign);
  text_lianxusign = findViewById(R.id.text_lianxusign);

 }

 private void initData() {

  //初始化模拟请求后台数据
  String reponse = "{\n" +
    " \"datas\": {\n" +
    "  \"day\": 2,\n" +
    "  \"myPoint\": 10886,\n" +
    "  \"signLog\": {\n" +
    "   \"content\": \"每日签到\",\n" +
    "   \"createTime\": \"2019-05-28 09:31:02\",\n" +
    "   \"familyId\": \"0\",\n" +
    "   \"id\": \"951656\",\n" +
    "   \"integral\": \"9\",\n" +
    "   \"logType\": \"3\",\n" +
    "   \"orderId\": \"0\",\n" +
    "   \"type\": \"1\",\n" +
    "   \"userId\": \"43431\"\n" +
    "  },\n" +
    "  \"signState\": true,\n" +
    "  \"userSingninList\": [\n" +
    "   {\n" +
    "    \"createTime\": \"2019-05-27 18:04:15\",\n" +
    "    \"day\": \"1\",\n" +
    "    \"familyId\": \"0\",\n" +
    "    \"id\": \"278904\",\n" +
    "    \"seriesDay\": \"1\",\n" +
    "    \"type\": \"0\",\n" +
    "    \"userId\": \"43431\"\n" +
    "   },\n" +
    "   {\n" +
    "    \"createTime\": \"2019-05-28 09:31:02\",\n" +
    "    \"day\": \"2\",\n" +
    "    \"familyId\": \"0\",\n" +
    "    \"id\": \"278905\",\n" +
    "    \"seriesDay\": \"2\",\n" +
    "    \"type\": \"0\",\n" +
    "    \"userId\": \"43431\"\n" +
    "   }\n" +
    "  ]\n" +
    " },\n" +
    " \"msg\": \"success!\",\n" +
    " \"ret\": 0\n" +
    "}";

  //解析后台请求数据
  SignListReq signListReq = new Gson().fromJson(reponse, SignListReq.class);
  if (signListReq.getRet() == 0) {
   setSignData(signListReq.getDatas());
  }
 }

 /**
  * 数据处理
  *
  * @param datas
  */
 private void setSignData(SignListReq.DatasBean datas) {

  //处理已签到的数据
  //先添加已签到的日期到集合中
  if (datas.getUserSingninList().size() != 0) {
   for (int i = 0; i < datas.getUserSingninList().size(); i++) {
    //时间格式:2019-05-27 18:04:15
    String createTime = datas.getUserSingninList().get(i).getCreateTime();
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date d1 = null;
    try {
     d1 = df.parse(createTime);
    } catch (ParseException e) {
     e.printStackTrace();
    }
    String timeString = df.format(d1);
    //获取日期的月、日
    String[] timeList = timeString.split(" ");
    String[] split = timeList[0].split("-");
    String month = split[1];//月
    String day = split[2];//日

    //判断是否需要显示积分图标,number表示-- 0为不显示积分,非0为显示积分
    if (datas.getSignLog() != null && datas.getUserSingninList().get(i).getCreateTime().equals(datas.getSignLog().getCreateTime())) {
     mStepBeans.add(new StepBean(StepBean.STEP_COMPLETED, Integer.parseInt(datas.getSignLog().getIntegral()), month + "." + day));
    } else {
     mStepBeans.add(new StepBean(StepBean.STEP_COMPLETED, 0, month + "." + day));
    }
   }
  }

  //添加未签到的数据,填充为最近一周数据
  if (mStepBeans.size() < 7) {

   //获取当前时间的月日
   Calendar now = Calendar.getInstance();
   int currentMonth = now.get(Calendar.MONTH) + 1;//当月
   int currentDay = now.get(Calendar.DAY_OF_MONTH);//当天
   String currentTime = setData(currentMonth) + "." + setData(currentDay);

   //后台有签到集合数据
   if (datas.getUserSingninList().size() != 0) {
    String createTime = datas.getUserSingninList().get(datas.getUserSingninList().size() - 1).getCreateTime();
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date d1 = null;
    try {
     d1 = df.parse(createTime);
    } catch (ParseException e) {
     e.printStackTrace();
    }
    String timeString = df.format(d1);
    String[] timeList = timeString.split(" ");
    String[] split = timeList[0].split("-");
    String month = split[1];//月
    String day = split[2];//日

    for (int i = mStepBeans.size(); i < 7; i++) {
     int parseInt = Integer.parseInt(day) + i - 1;
     //判断累积的天数是否超过当月的总天数
     if (parseInt <= getDayOfMonth()) {
      String time = setData(Integer.parseInt(month)) + "." + setData(parseInt);
      if (currentTime.equals(time)) {
       mStepBeans.add(new StepBean(StepBean.STEP_CURRENT, 0, time));
      } else {
       mStepBeans.add(new StepBean(StepBean.STEP_UNDO, 0, time));
      }
     } else {
      String time = setData((Integer.parseInt(month) + 1)) + "." + setData(parseInt - getDayOfMonth());
      if (currentTime.equals(time)) {
       mStepBeans.add(new StepBean(StepBean.STEP_CURRENT, 0, time));
      } else {
       mStepBeans.add(new StepBean(StepBean.STEP_UNDO, 0, time));
      }
     }
    }
   } else {//后台没有签到集合数据,没有的话从当天时间开始添加未来一周的日期数据
    for (int i = 0; i < 7; i++) {
     int parseInt = currentDay + i;
     //判断累积的天数是否超过当月的总天数
     if (parseInt <= getDayOfMonth()) {
      String time = setData(currentMonth) + "." + setData(parseInt);
      if (currentTime.equals(time)) {
       mStepBeans.add(new StepBean(StepBean.STEP_CURRENT, 0, time));
      } else {
       mStepBeans.add(new StepBean(StepBean.STEP_UNDO, 0, time));
      }
     } else {
      String time = setData((currentMonth + 1)) + "." + setData(parseInt - getDayOfMonth());
      if (currentTime.equals(time)) {
       mStepBeans.add(new StepBean(StepBean.STEP_CURRENT, 0, time));
      } else {
       mStepBeans.add(new StepBean(StepBean.STEP_UNDO, 0, time));
      }
     }
    }
   }
  }

  mStepView.setStepNum(mStepBeans);
 }

 /**
  * 获取最大天数
  *
  * @return
  */
 public int getDayOfMonth() {
  Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
  int day = aCalendar.getActualMaximum(Calendar.DATE);
  return day;
 }

 /**
  * 日月份处理
  *
  * @param day
  * @return
  */
 public String setData(int day) {
  String time = "";
  if (day < 10) {
   time = "0" + day;
  } else {
   time = "" + day;
  }

  return time;
 }
}

4.主界面布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".ui.activity.MainActivity">

 <RelativeLayout
  android:id="@+id/rl_oval"
  android:layout_width="70dp"
  android:layout_height="70dp"
  android:layout_marginTop="150dp"
  android:layout_centerHorizontal="true"
  android:background="@drawable/sign_bg">

  <LinearLayout
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_centerInParent="true"
   android:orientation="vertical">

   <TextView
    android:id="@+id/text_sign"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="签到"
    android:textColor="#fff"
    android:layout_gravity="center_horizontal"
    android:textSize="16sp" />

   <TextView
    android:id="@+id/text_lianxusign"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="连续3天"
    android:textColor="#fff"
    android:visibility="gone"
    android:layout_gravity="center_horizontal"
    android:textSize="12sp" />
  </LinearLayout>
 </RelativeLayout>

 <com.sorgs.stepview.ui.widget.StepsView
  android:id="@+id/step_view"
  android:layout_below="@id/rl_oval"
  android:layout_marginTop="20dp"
  android:layout_marginLeft="15dp"
  android:layout_width="match_parent"
  android:layout_height="77dp" />
</RelativeLayout>

5.签到bean

package com.sorgs.stepview.bean;

/**
 * description: 签到bean.
 */
public class StepBean {
 /**
  * 未完成
  */
 public static final int STEP_UNDO = -1;
 /**
  * 正在进行
  */
 public static final int STEP_CURRENT = 0;
 /**
  * 已完成
  */
 public static final int STEP_COMPLETED = 1;

 private int state;
 private int number;//0为不显示积分,非0为显示积分
 private String day;

 public StepBean(int state, int number, String day) {
  this.state = state;
  this.number = number;
  this.day = day;
 }

 public int getNumber() {
  return number;
 }

 public void setNumber(int number) {
  this.number = number;
 }

 public int getState() {
  return state;
 }

 public void setState(int state) {
  this.state = state;
 }

 public String getDay() {
  return day;
 }

 public void setDay(String day) {
  this.day = day;
 }
}

6.总结

该篇的功能是根据需求进行功能的处理,自定义View是实现了签到时的动画效果的,不过我们的需求不需要动画,所以这里就没调用演示,需要的可以自行调用

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • Android积分签到上移消失动画效果

    还记得以前在某云的时候,有次需求是一个积分签到,要求点击签到按钮然后有一个动画效果,比如+30积分然后慢慢往上移动在消失.那会不会做就想着改下需求,直接去掉了动画效果,而今时隔很久又遇到同样的问题,比较蛋疼的是我清楚记得当时做过这个功能,但是自己没有做出来,当然现在做还是不会.自己当年省写的代码含泪也要补上.这次吸取教训,实现这个效果. 大致思路:动画部分,由一个垂直的平移和一个透明度变化的两个动画组成.然后通过AnimationSet将两个动画添加到集合,然后开始播放动画. 更新UI部分,用的

  • Android简单实现app每月签到功能

    本文实例为大家分享了Android实现app每月签到功能的具体代码,供大家参考,具体内容如下 先上一张效果图: 其中这些签到的效果图是在网上找的,然后重要用到的控件就是 GridvVew 了, 代码很简单,只有3个代码文件: MainActivity.class 文件 package zhanghuan.cn.checkdesign; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import

  • Android基于AccessibilityService制作的钉钉自动签到程序代码

    前两天公司开始宣布要使用阿里钉钉来签到啦!!!~~这就意味着,我必须老老实实每天按时签到上班下班了,这真是一个悲伤的消息,可是!!!!那么机智(lan)的我,怎么可能就这么屈服!!!阿里钉钉签到,说到底不就是手机软件签到吗?我就是干移动开发的,做一个小应用每天自动签到不就行了:) 说干就干,首先分析一下,阿里钉钉的签到流程: 打开阿里钉钉->广告页停留2S左右->进入主页->点击"工作"tab->点击"签到"模块->进入签到页面(可能会

  • Android可签到日历控件的实现方法

    最近在公司的功能需求中,需要实现可以签到的日历,签到后在签到过的日期做标志.本功能参考了网上一些大神的日历控件,在此基础上进行修改,已满足本公司的需求,现已完成,记录一下. 布局文件: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_wi

  • Android实现带签到赢积分功能的日历

    Android实现点击签到按钮直接签到,弹出dialog,先上效果图 demo是利用gridview实现的,现附上布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent&qu

  • Android自定义按周签到打卡功能实例代码

    前言 之前实现过<Android可签到的日历控件>的功能,跟这篇一样都是实现签到打卡功能,这篇实现的是按月进行打卡做标识,本篇内容实现的按周进行签到打卡. 实现签到规则如下: 1.连续签到7天,即可获得额外积分奖励. 2.连续签到记录在第8天开始时将清零重新计算. 3.如果中断签到,连续签到记录也将清零. 实现步骤: 1.效果图 2.自定义签到打卡View 3.主程序逻辑处理 4.主界面 5.签到bean 6.总结 实现过程: 1.效果图 2.自定义签到打卡View /** * descrip

  • Android 自定义弹出菜单和对话框功能实例代码

    Android 开发当中,可能会存在许多自定义布局的需求,比如自定义弹出菜单(popupWindow),以及自定义对话框(Dialog). 话不多说,直接上图片. 先讲第一种,自定义PopUpWindow 1.popupWindow protected void showPopWindow(View view, final int pos){ WindowManager wm= (WindowManager) myContext.getSystemService(Context.WINDOW_S

  • Android自定义View实现箭头沿圆转动实例代码

    具体代码如下所示: //MyCircleView类 public class MyCircleView extends View{ //当前画笔画圆的颜色 private int CurrenCircleBoundColor; private Paint paint; ////从xml中获取的颜色 private int circleBundColor; private float circleBoundWidth; private float pivotX; private float piv

  • Android 自定义输入支付密码的软键盘实例代码

    Android 自定义输入支付密码的软键盘 有项目需求需要做一个密码锁功能,还有自己的软键盘,类似与支付宝那种,这里是整理的资料,大家可以看下,如有错误,欢迎留言指正 需求:要实现类似支付宝的输入支付密码的功能,效果图如下: 软键盘效果图 使用 android.inputmethodservice.KeyboardView 这个类自定义软键盘 软键盘的实现 1. 自定义只输入数字的软键盘 PasswordKeyboardView 类,继承自 android.inputmethodservice.

  • Android调用系统自带的分享功能实例代码

    实现分享功能的几个办法 1.调用系统的分享功能 2.通过第三方SDK,如ShareSDK,友盟等 3.自行使用各自平台的SDK,比如QQ,微信,微博各自的SDK 这里就记录下第一种办法. 分享文本信息 Intent textIntent = new Intent(Intent.ACTION_SEND); textIntent.setType("text/plain"); textIntent.putExtra(Intent.EXTRA_TEXT, "这是一段分享的文字&quo

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

  • Android 百度地图定位实现仿钉钉签到打卡功能的完整代码

    导语 本章根据百度地图API,实现仿钉钉打卡功能.用到了基础地图.覆盖物.定位图层.陀螺仪方法.悬浮信息弹框. 百度地图API地址  :Android 地图SDK 请先注册注册百度账号和获取密钥,并实现地图显示出来.(注意:密钥.权限要设置) 另外,我得说明本章所下载官方Demo 和 导入的jar包和so文件.自定义下载即可,如下图: 接下来,一起看实现效果. 源码Git地址:BaiduMapApp 效果图 实现代码·三步骤 第一步:基础地图和方向传感器 类先实现方向传感器 implements

  • Android 实现钉钉自动打卡功能

    提前准备 首先我们需要一直不用的Android手机,插上公司的电源.下载安装钉钉并设置为极速打卡. 自动打开 我们只需要启动一个服务,定时打开钉钉应用后再返回即可. 防止熄屏 这华为手机并没有永不息屏的选项,所以我们需要设置一下防止自动息屏. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 设置不自动息屏 getWindow().setFla

  • Android自定义View之绘制圆形头像功能

    前言 做APP应用开发的时候,用户头像肯定是必不可少的,但是90%以上的需求头像都是圆形的.那么,如何通过自定义View的方式实现圆形头像呢,那么,本片博文会告诉你不仅仅是实现过程.一定会有意想不到的收获哦! 最终效果 国际惯例,我们先来看最终实现的效果图 自定义RoundImageView继承自ImageView public class RoundImageView extends ImageView { public RoundImageView(Context context) { su

  • Android 百度地图POI搜索功能实例代码

    在没介绍正文之前先给大家说下poi是什么意思. 由于工作的关系,经常在文件中会看到POI这三个字母的缩写,但是一直对POI的概念和含义没有很详细的去研究其背后代表的意思.今天下班之前,又看到了POI这三个字母,决定认认真真的搜索一些POI具体的含义. POI是英文的缩写,原来的单词是point of interest, 直译成中文就是兴趣点的意思.兴趣点这个词最早来自于导航地图厂商.地图厂商为了提供尽可能多的位置信息,花费了很大的精力去寻找诸如加油站,餐馆,酒店,景点等目的地,这些目的地其实都可

随机推荐