Android仿今日头条极速版签到功能

阅读: 评论:0

Android仿今日头条极速版签到功能

Android仿今日头条极速版签到功能

 

前言:这个签到功能一开始想找找有没有现成的轮子,后来国内国外找了一圈也没发现类似的。只能自己动手撸一个。

 

注意:这个自定义view我并没有适配warp_content,也就是说,你只能给它固定的高度,比如200dp。否则它会默认填满你的整个屏幕。

另外  像dip2px这种代码,每位开发者自己应该都有,我就不补充了,像图片文件,我这边也不好补充。

 

这篇文章不会教你如何直接使用这个自定义view,因为每个人的需求都不一样,你肯定是要在我的基础上修修改改,所以你最好能够看懂这些代码。

 

对于自定义view基础比较薄弱的人,看懂其实也不难,我所认为对你最大的难点是:

Q:线条如何转折?

A: 使用Path

Q:线条如何变成矩形?

A:给画笔添加setStrokeCap和setStrokeJoin(具体去源码里搜索一下就看到了)

Q:进度条的动画效果如何实现?

A:使用属性动画。需要用到三个动画,并且监听动画进度,第一个动画播放完毕后  开始启动第二个动画。(后来我发现使用animatorSet更方便,你如果感兴趣可以试试)

 

我只是告诉你大致的思路,具体实现从源码中参考。

 

思路:  1.先画出最底层的线,再画出红色的线盖住它,我们只需要控制红色线的长度变化即可。

 

使用(只讲述API):

signInView.setSignInDay(int);//取值:1-10  ,分别让红线停留在对应1-10个小圆点所在的地方
SignInDay();//返回当前传入的天数

代码:

/*** Created by Fushize on 2019/8/19.*/
public class SignInView extends View {private int startWidth = 20;private int endWidth;private Paint paint;private Paint pointPaint;private Paint imgPaint;private Paint textPaint;private int signInDay;private float progress = 0;private float progress2 = 0;private float progress3 = 0;private int maxLine = 800;   //最大的长度private final int offSetY = 200;    //偏移的Yprivate int offSetX = 0;    //偏移的Xprivate final int maxHeigh = 340;   //最大高度private final int circleRadius = 7; //小圆点的半径private int duration = 2000;    //动画时长public String[] strMoney = {"10", "20", "30", "40", "50", "60"};public String[] strMoney2 = {"880", "500", "300", "150"};private String[] strDay = {"1天", "2天", "3天", "4天", "5天", "6天"};private String[] strDay2 = {"30天", "21天", "14天", "7天"};private ObjectAnimator animator;private ObjectAnimator animator2;private ObjectAnimator animator3;private @SuppressLint("DrawAllocation")Bitmap sign_in_150;private @SuppressLint("DrawAllocation")Bitmap sign_in_300;private @SuppressLint("DrawAllocation")Bitmap sign_in_500;private @SuppressLint("DrawAllocation")Bitmap sign_in_880;public SignInView(Context context) {super(context, null);init();}// 创建 getter 方法public float getProgress() {return progress;}// 创建 setter 方法public void setProgress(float progress) {this.progress = progress;invalidate();}public SignInView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SignInView);signInDay = ta.getInt(R.styleable.SignInView_signInDay, 0);ta.recycle();init();}public SignInView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}@SuppressLint("ObjectAnimatorBinding")private void init() {maxLine = getContext().getResources().getDisplayMetrics().widthPixels - CommonUtil.dip2px(74);startWidth = CommonUtil.dip2px(20);offSetX = startWidth;endWidth = maxLine - startWidth;paint = new Paint();pointPaint = new Paint();imgPaint = new Paint();imgPaint.setStyle(STROKE);imgPaint.setAntiAlias(true);textPaint = new Paint();textPaint.setStyle(Paint.Style.FILL);textPaint.setAntiAlias(true);//最底层的线//上层的线paint.setStrokeWidth(36);paint.setStyle(STROKE);paint.setAntiAlias(true);paint.setDither(true);paint.setStrokeJoin(Paint.Join.ROUND);paint.setStrokeCap(Paint.Cap.ROUND);//画小圆点pointPaint.setStrokeWidth(5);pointPaint.setStyle(FILL);pointPaint.setStrokeJoin(Paint.Join.ROUND);pointPaint.setStrokeCap(Paint.Cap.ROUND);pointPaint.setColor(getResources().lor.white));sign_in_150 = BitmapFactory.decodeResource(getResources(), R.mipmap.sign_in_50, null);sign_in_300 = BitmapFactory.decodeResource(getResources(), R.mipmap.sign_in_100, null);sign_in_500 = BitmapFactory.decodeResource(getResources(), R.mipmap.sign_in_200, null);sign_in_880 = BitmapFactory.decodeResource(getResources(), R.mipmap.sign_in_300, null);animator = ObjectAnimator.ofFloat(this, "progress", 0.05f, 1);animator.setDuration(duration);// 执行动画animator.start();animator2 = ObjectAnimator.ofFloat(this, "progress2", 0, 1);animator2.setDuration(duration);animator3 = ObjectAnimator.ofFloat(this, "progress3", 0, 1);animator3.setDuration(duration);animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationStart(Animator animation, boolean isReverse) {}@Overridepublic void onAnimationEnd(Animator animation, boolean isReverse) {if (signInDay >= 6) {animator2.start();}}});animator2.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationStart(Animator animation, boolean isReverse) {}@Overridepublic void onAnimationEnd(Animator animation, boolean isReverse) {if (signInDay >= 6) {animator3.start();}}});animator2.addUpdateListener(valueAnimator -> {progress2 = (Float) AnimatedValue();invalidate();});animator3.addUpdateListener(valueAnimator -> {progress3 = (Float) AnimatedValue();invalidate();});}public void setSignInDay(int signInDay) {this.signInDay = signInDay;invalidate();}public int getSignInDay() {return signInDay;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {Measure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onDraw(Canvas canvas) {Draw(canvas);paint.setColor(getResources()._signin));Path path = new Path();veTo(offSetX, offSetY);path.lineTo(endWidth, offSetY);path.rLineTo(0, maxHeigh);int line = maxLine - offSetX * 2;path.rLineTo(-line, 0);canvas.drawPath(path, paint);paint.setColor(getResources().lor.main_color));Path path1 = new Path();veTo(offSetX, offSetY);int yuliuWidth = (maxLine - startWidth * 2) / 7;   //预留的宽度if (signInDay == 1) {//第一天path1.lineTo(yuliuWidth * progress + startWidth, offSetY);} else if (signInDay <= 6) {//2-6天float x = (yuliuWidth) * (signInDay);x = x + 20;if (x > maxLine) {x = maxLine;}path1.lineTo(x * progress + startWidth, offSetY);} else {//六天以后path1.lineTo(endWidth * progress, offSetY);path1.rLineTo(0, maxHeigh * progress2);float v = 0;switch (signInDay) {case 10:v = yuliuWidth * 7;break;case 9:v = yuliuWidth * 4.5f;break;case 8:v = yuliuWidth * 2.8f;break;case 7:v = yuliuWidth * 1.5f;break;}path1.rLineTo(-v * progress3, 0);}canvas.drawPath(path1, paint);//画圆点for (int i = 0; i < 6; i++) {canvas.drawCircle(yuliuWidth * (i + 1) + startWidth, offSetY, circleRadius, pointPaint);}canvas.drawCircle(yuliuWidth + startWidth, offSetY + maxHeigh, circleRadius, pointPaint);canvas.drawCircle(yuliuWidth * 2.8f + startWidth, offSetY + maxHeigh, circleRadius, pointPaint);canvas.drawCircle(yuliuWidth * 4.5f + startWidth, offSetY + maxHeigh, circleRadius, pointPaint);canvas.drawCircle(yuliuWidth * 6 + startWidth, offSetY + maxHeigh, circleRadius, pointPaint);//画金币图片@SuppressLint("DrawAllocation") Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.sign_in_10, null);for (int i = 0; i < strMoney.length; i++) {canvas.drawBitmap(bitmap, (yuliuWidth * (i + 1) + startWidth) - (Width() / 2), 40, imgPaint);}textPaint.setTextSize(CommonUtil.dip2px(12));for (int i = 0; i < strMoney.length; i++) {textPaint.setColor(getResources().getColor(signInDay > i ? R.color.main_color : lor_aaa));//画奖励金额的文字canvas.drawText(strMoney[i], yuliuWidth * (i + 1) + startWidth - (asureText(strMoney[i]) / 2), Height() + 90, textPaint);//画已签到天数的文字canvas.drawText(signInDay > i ? "已签" : strDay[i], yuliuWidth * (i + 1) + startWidth - (asureText(strDay[i]) / 2), Height() + 200, textPaint);}//底部四张图片与文字textPaint.setColor(getResources().lor_aaa));for (int i = 0; i < strMoney2.length; i++) {switch (i) {case 0://第30天 奖励880if (signInDay >= 10) {textPaint.setColor(getResources().lor.main_color));canvas.drawText("已签", yuliuWidth + startWidth - (asureText(strDay[i]) / 2), sign_Height() + maxHeigh + 200, textPaint);} else {//画已签到天数的文字canvas.drawText(strDay2[i], yuliuWidth + startWidth - (asureText(strDay[i]) / 2), sign_Height() + maxHeigh + 200, textPaint);}//画出金币图片canvas.drawBitmap(sign_in_880, (yuliuWidth + startWidth) - (sign_Width() / 2), maxHeigh + 46, imgPaint);//画奖励金额的文字canvas.drawText(strMoney2[i], yuliuWidth + startWidth - (asureText(strMoney2[i]) / 2), maxHeigh + 160, textPaint);break;case 1://第21天 奖励500if (signInDay >= 9) {textPaint.setColor(getResources().lor.main_color));canvas.drawText("已签", (yuliuWidth * 2.8f + startWidth) - (asureText(strDay[i]) / 2), sign_Height() + maxHeigh + 200, textPaint);} else {canvas.drawText(strDay2[i], (yuliuWidth * 2.8f + startWidth) - (asureText(strDay[i]) / 2), sign_Height() + maxHeigh + 200, textPaint);}canvas.drawBitmap(sign_in_500, (yuliuWidth * 2.8f + startWidth) - (sign_Width() / 2), maxHeigh + 46, imgPaint);canvas.drawText(strMoney2[i], (yuliuWidth * 2.8f + startWidth) - (asureText(strMoney2[i]) / 2), maxHeigh + 160, textPaint);break;case 2://第14天 奖励300if (signInDay >= 8) {textPaint.setColor(getResources().lor.main_color));canvas.drawText("已签", (yuliuWidth * 4.5f + startWidth) - (asureText(strDay[i]) / 2), sign_Height() + maxHeigh + 200, textPaint);} else {canvas.drawText(strDay2[i], (yuliuWidth * 4.5f + startWidth) - (asureText(strDay[i]) / 2), sign_Height() + maxHeigh + 200, textPaint);}canvas.drawBitmap(sign_in_300, (yuliuWidth * 4.5f + startWidth) - (sign_Width() / 2), maxHeigh + 46, imgPaint);canvas.drawText(strMoney2[i], (yuliuWidth * 4.5f + startWidth) - (asureText(strMoney2[i]) / 2), maxHeigh + 160, textPaint);break;case 3://第7天 奖励150if (signInDay >= 7) {textPaint.setColor(getResources().lor.main_color));canvas.drawText("已签", (yuliuWidth * 6f + startWidth) - (asureText(strDay[i]) / 2), sign_Height() + maxHeigh + 200, textPaint);} else {canvas.drawText(strDay2[i], (yuliuWidth * 6f + startWidth) - (asureText(strDay[i]) / 2), sign_Height() + maxHeigh + 200, textPaint);}canvas.drawBitmap(sign_in_150, (yuliuWidth * 6 + startWidth) - (sign_Width() / 2), maxHeigh + 46, imgPaint);canvas.drawText(strMoney2[i], (yuliuWidth * 6 + startWidth) - (asureText(strMoney2[i]) / 2), maxHeigh + 160, textPaint);break;}}}
}

 

 

本文发布于:2024-01-28 09:35:06,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17064057106483.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:极速   头条   功能   今日   Android
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23