MyException - 我的异常网
当前位置:我的异常网» 移动开发 » 自定义View学习之12/一

自定义View学习之12/一

www.MyException.Cn  网友分享于:2015-02-11  浏览:0次
自定义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学习就到这里,欢迎大家指正错误。互相学习。第一次专注的写博客,希望各位大大多多支持。提前祝福兄弟姐妹们新年快乐。。

未完待续、、、

文章评论

为什么程序员都是夜猫子
为什么程序员都是夜猫子
总结2014中国互联网十大段子
总结2014中国互联网十大段子
程序员必看的十大电影
程序员必看的十大电影
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
程序员都该阅读的书
程序员都该阅读的书
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
 程序员的样子
程序员的样子
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员和编码员之间的区别
程序员和编码员之间的区别
编程语言是女人
编程语言是女人
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
10个调试和排错的小建议
10个调试和排错的小建议
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
中美印日四国程序员比较
中美印日四国程序员比较
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
Java程序员必看电影
Java程序员必看电影
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
程序员的鄙视链
程序员的鄙视链
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
鲜为人知的编程真相
鲜为人知的编程真相
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
旅行,写作,编程
旅行,写作,编程
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
一个程序员的时间管理
一个程序员的时间管理
如何成为一名黑客
如何成为一名黑客
程序员应该关注的一些事儿
程序员应该关注的一些事儿
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
每天工作4小时的程序员
每天工作4小时的程序员
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
代码女神横空出世
代码女神横空出世
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有