自定义View学习之12/1

感谢AigeStudio提供的自定义view讲解(地址http://blog.csdn.net/aigestudio)下面是我看了Aige的讲解之后自己的理解以及demo,有说错的地方欢迎大家指出。

在这里自定义一个圆形等级条的view来加强自己对自定义的理解。

思路:
1、需要画一个背景圆,再需要一个覆盖在背景圆上面的进度圆。
2、使用线程让进度圆产生动画。
3、在进度圆达到圆满的时候回到原点,给个回调。

现在我们先画出一个空心圆。

代码块

    /** 背景圆的画笔 */
    private Paint paint;
    /** 进度条圆的画笔 */
    private Paint paint1;
    /** 设置矩阵的坐标点 */
    private RectF rectF;

    /** 屏幕的高度 */
    private int width = 0;
    /** 园的半径 */
    private int circleRadius = 0;
    /** 园的y轴起始坐标 */
    private int circleStartY = 20;
    /** 园的y轴终点坐标 起始坐标加上园的半径*2 */
    private int circleEndy = 0;

    /**我一般喜欢直接写3个构造方法,方便引用*/
    public CircleView(Context context) {
        super(context);
        init(context);
    }
    public CircleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    /**初始化画笔*/
    private void init(Context context){
        paint = new Paint();// 布局xml里面引用
        paint1 = new Paint();// 布局xml里面引用

        paint.setAntiAlias(true);// 设置抗锯齿
            paint.setColor(getResources().getColor(R.color.char_circlebackground));
        paint.setStyle(Style.STROKE);// 设置圆心掏空
        paint.setStrokeWidth(dip2px(context, 10));
        // 设置画笔形状 圆形,需要先设置画笔样式 SYROKE 或者 FILL_AND_STROKE
        paint.setStrokeCap(Paint.Cap.ROUND);

        paint1.setAntiAlias(true);// 设置抗锯齿
        paint1.setColor(getResources().getColor(R.color.char_circleplan));
        paint1.setStyle(Style.STROKE);
        paint1.setStrokeWidth(dip2px(context, 10));
        paint1.setStrokeCap(Paint.Cap.ROUND);

        width = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
        circleRadius = width / 4;
        circleEndy = circleStartY + circleRadius * 2;

        rectF = new RectF(width / 2 - circleRadius, circleStartY, width / 2 + circleRadius, circleEndy);// 弧形
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 第一个参数是圆的大小,根据矩阵来控制。第二个参数是在哪个点起始,已顺时针方向走,所以说90为正下方。0为最右边。第三个参数是圆的度数360为一圈
        canvas.drawArc(rectF, 90, 360, false, paint);
        //这里等级为4/1等级,所以是90
        canvas.drawArc(rectF, 90, 90, false, paint1);

    }
        /**传入dp,返回px*/
    public float dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (float) (dpValue * scale + 0.5f);
    }

效果如下:这里写图片描述

效果已经画出来了。但是缺少点东西,现在view里面东西全是死的,得让他活起来,并且具有动画,满级之后自动反0操作。所以我加了以下代码


    /** 背景圆的画笔 */
    private Paint paint;
    /** 进度条圆的画笔 */
    private Paint paint1;
    /** 设置矩阵的坐标点 */
    private RectF rectF;

    /** 屏幕的高度 */
    private int width = 0;
    /** 园的半径 */
    private int circleRadius = 0;
    /** 园的y轴起始坐标 */
    private int circleStartY = 20;
    /** 园的y轴终点坐标 起始坐标加上园的半径*2 */
    private int circleEndy = 0;

    /** 初始进度 */
    private float currentPorcent = 0;
    /** 进度是多少 */
    private float maxPorcent = 0;

    /**满级回调*/
    public RestoreCirclr rc;
    /** 是否还原 */
    public boolean isRestore = false;

    /**我一般喜欢直接写3个构造方法,方便引用*/
    public CircleView(Context context) {
        super(context);
        init(context);
    }
    public CircleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    /**初始化画笔*/
    private void init(Context context){
        paint = new Paint();// 布局xml里面引用
        paint1 = new Paint();// 布局xml里面引用

        paint.setAntiAlias(true);// 设置抗锯齿
        paint.setColor(getResources().getColor(R.color.char_circlebackground));
        paint.setStyle(Style.STROKE);// 设置圆心掏空
        paint.setStrokeWidth(dip2px(context, 10));
        // 设置画笔形状 圆形,需要先设置画笔样式 SYROKE 或者 FILL_AND_STROKE
        paint.setStrokeCap(Paint.Cap.ROUND);

        paint1.setAntiAlias(true);// 设置抗锯齿
        paint1.setColor(getResources().getColor(R.color.char_circleplan));
        paint1.setStyle(Style.STROKE);
        paint1.setStrokeWidth(dip2px(context, 10));
        paint1.setStrokeCap(Paint.Cap.ROUND);

        width = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
        circleRadius = width / 4;
        circleEndy = circleStartY + circleRadius * 2;

        rectF = new RectF(width / 2 - circleRadius, circleStartY, width / 2 + circleRadius, circleEndy);// 弧形
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 第一个参数是圆的大小,根据矩阵来控制。第二个参数是在哪个点起始,已顺时针方向走,所以说90为正下方。0为最右边。第三个参数是圆的度数360为一圈
        canvas.drawArc(rectF, 90, 360, false, paint);
        //这里等级为4/1等级,所以是90
        canvas.drawArc(rectF, 90, currentPorcent, false, paint1);

        if (currentPorcent == 0) {
            handler.postDelayed(drawRunnable, 0);
        }
    }
    /**启动动画刷新界面*/
    public void invalidateView(){
        handler.postDelayed(drawRunnable, 0);
    }

    private Handler handler = new Handler();

    Runnable drawRunnable = new Runnable() {

        @Override
        public void run() {
            if (!isRestore) {//有经验时动画
                if (currentPorcent >= maxPorcent) {
                    currentPorcent = maxPorcent;
                    invalidate();
                    //移除当前Runnable
                    handler.removeCallbacks(drawRunnable);
                } else {
                    currentPorcent += 5;//这里是动画速度,当前为5。可自己去调试经验值增长速度
                    handler.postDelayed(drawRunnable, (long) (1300 / maxPorcent));
                    invalidate();
                }
                if (currentPorcent == 360) {
                    if (rc != null) {
                        isRestore = rc.OnRestoreCirclr();
                        handler.postDelayed(drawRunnable, 0);
                    }
                }
            } else {//满级之后经验条动画返回0进度
                if (currentPorcent <= 0) {
                    currentPorcent = 0;
                    invalidate();

                    handler.removeCallbacks(drawRunnable);
                } else {
                    currentPorcent -= 3;//这里是动画速度,当前为3。可自己去调试经验值反0速度
                    handler.postDelayed(drawRunnable, (long) (1300 / maxPorcent));
                    invalidate();
                }
            }
        }
    };



    public boolean isRestore() {
        return isRestore;
    }
    public void setRestore(boolean isRestore) {
        this.isRestore = isRestore;
    }
    /** 设置等级进度,传入升级经验,以及当前经验  maxPorcent就是当前经验在升级经验占的百分比*/
    public void setCirclePlan(int max, int current) {
        maxPorcent = (int) (((float)360 / (float)max) * current);
    }

    /**传入dp,返回px*/
    public float dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (float) (dpValue * scale + 0.5f);
    }   

    /** 设置园线的颜色 */
    public void setCircleColor(int color) {
        paint.setColor(color);
    }

    /** 设置进度线的颜色 */
    public void setCirclePlanColor(int color) {
        paint1.setColor(color);
    }

    public void setRc(RestoreCirclr rc) {
        this.rc = rc;
    }

    public interface RestoreCirclr {
        public boolean OnRestoreCirclr();
    }

在mainActivity里面调用代码如下:

    private CircleView circleView;
    /** 升级经验为100 */
    private int max ;
    /** 目前经验值为10 */
    private int current ;
    /** 经验加10 */
    private Button button_1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        circleView = (CircleView) findViewById(R.id.circleView);
        button_1 = (Button) findViewById(R.id.button_1);
        button_1.setOnClickListener(this);

        max = 100;
        current = 10;

        circleView.setCirclePlan(max, current);// 进度条已满 升级数是100,当前经验数是10

        circleView.setRc(new RestoreCirclr() {// 满级之后的回调

            @Override
            public boolean OnRestoreCirclr() {
                //满级之后的操作   返回true就回到原点
                current=0;
                return true;
            }
        });

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.button_1:
            current += 10;
            circleView.setRestore(false); //false经验值增加
            circleView.setCirclePlan(max, current);
            circleView.invalidateView();//刷新view
            break;
        }
    }

效果图:这里写图片描述
由于本人第一次写博客,不会制作那种可动的gif图片,所以导致动画效果看不见。如果各位有兴趣的看看动画效果可去(http://download.csdn.net/detail/u013895206/8431395)这个地址下载源码。
本篇自定义view学习就到这里,欢迎大家指正错误。互相学习。第一次专注的写博客,希望各位大大多多支持。提前祝福兄弟姐妹们新年快乐。。

未完待续、、、

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值