android自定义打对勾的连续签到效果

本文现简单记录下一个签到功能的UI实现,先看效果图,如下:

这是一个很简单的自定义view,原理、逻辑都比较简单,但是要注意的细节部分比较多,距离、位置等的计算要精确

接下来 我们就来实现这个功能:

首先,我们分析下这个view,有三部分构成:圆、直线、对勾,然后一个接一个绘制就行

重写view,实现几个构造方法

public class MyTestView1 extends View {

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

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

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

在第三个构造方法里初始化画笔:

//圆节点及线的画笔
        circlePaint = new Paint();
        circlePaint.setColor(Color.parseColor("#fe9797"));
        //  circlePaint.setStrokeWidth(10);
        circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        circlePaint.setAntiAlias(true);

        //对勾的画笔
        paint1 = new Paint();
        paint1.setColor(Color.parseColor("#ffffff"));
        paint1.setStrokeWidth(6);
        //背景画笔
        outCirclePaint=new Paint();
        outCirclePaint.setColor(Color.parseColor("#eeeeee"));
        //  backgroundPaint.setStrokeWidth(5);
        outCirclePaint.setStyle(Paint.Style.STROKE);
        outCirclePaint.setAntiAlias(true);
        //直线画笔
        linePaint=new Paint();
        linePaint.setColor(Color.parseColor("#eeeeee"));
        //  backgroundPaint.setStrokeWidth(5);
        //文字画笔
        textPaint = new Paint();
        textPaint.setColor(Color.parseColor("#000000"));
        textPaint.setStrokeWidth(6);
        textPaint.setTextSize(40);
        textPaint.setTypeface(Typeface.DEFAULT_BOLD);
        textPaint.setTextAlign(Paint.Align.CENTER);

在onSizeChanged方法里计算节点圆半径以及设置线条宽度:

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

        height=h;
        //圆弧半径
        radius =(w-20) /(count+count-1)/2;

        lineWidth = radius/3;
        outCircleWidth = radius/6;
        outCirclePaint.setStrokeWidth(outCircleWidth);
        linePaint.setStrokeWidth(lineWidth);
        circlePaint.setStrokeWidth(radius/3);

        outR = radius;
        inR  = radius-radius/6;

    }


绘制灰背景+底部数字:

for(int i=0;i<count;i++){
            float centerX = radius+radius*(i*4)+10;
            float centerY = height/2;
            canvas.drawCircle(centerX,centerY,outR,outCirclePaint);
            canvas.drawText(""+(i+1),centerX,centerY+radius*3,textPaint);
            if(i<count-1){//最后一个不用画线
                canvas.drawLine(centerX+radius, height/2, centerX+radius+radius*2, height/2, linePaint);
            }
        }
效果如下:


绘制已签到的节点(浅红色节点):

 canvas.drawCircle(centerX,centerY,inR,circlePaint);
                    drawStaticHook(canvas,centerX,centerY);
                    if(i==postion-2){
                        //签到过的部分直线也用circlePaint
                        canvas.drawLine(centerX+inR, height/2, centerX+radius+radius, height/2, circlePaint);
                    }else{
                        canvas.drawLine(centerX+inR, height/2, centerX+radius*4-inR, height/2, circlePaint);
                    }
 /**
     * 画对勾,无动态效果
     * @param canvas
     * @param centerX
     * @param centerY
     */
    private void drawStaticHook(Canvas canvas,float centerX,float centerY) {

        //画第一根线
        canvas.drawLine(centerX-radius/5-radius/3, centerY, centerX-radius/5 , centerY + radius/3, paint1);

        //画第二根线
        canvas.drawLine(centerX-paint1.getStrokeWidth()/2-radius/5 , centerY + radius/3, centerX + radius*2/3-radius/5, centerY -radius/3, paint1);

    }

绘制签到当天节点(有动态效果)
drawDynamicCircle(canvas,centerX,centerY,circlePaint);
if(radius0>=inR){
	drawHook(canvas,centerX,centerY);
	if(line1_x>=radius/3  && line2_x >= radius*2/3){
	circlePaint.setStrokeWidth(radius/4);
	drawLastLine(canvas,centerX,centerY,circlePaint);
}
                    

/**
     * 绘制节点圆,有动态效果
     * @param canvas
     * @param centerX
     * @param centerY
     * @param paint
     */
    private void drawDynamicCircle(Canvas canvas,float centerX,float centerY,Paint paint){
        //  Log.d("1123","radius0 : "+radius0);
        //  canvas.drawCircle(centerX,centerY,radius+backgroundPaint.getStrokeWidth(),backgroundPaint);
        canvas.drawCircle(centerX,centerY,radius0,paint);
        if(radius0<=inR){
            radius0 += radius/3/step;
            invalidate();
        }
    }

ok,这样基本功能就完成了,接下来要做的就是暴露一些属性以便动态设置如 节点总数以及当前签到的天数等等

 public void setPostion(int postion) {
        this.postion = postion;
        invalidate();
    }
    public void setCount(int count){
        this.count= count;
        invalidate();
    }

如有需要,可自行提取其他属性,这里不再一一赘述。






  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值