Android自定义View之高仿QQ健康

作者: _SOLID | 来源:发表于2016-04-11 22:14 被阅读9724次

    源码有更新:加入动画,动画由简书网友xsfelvis提供

    我们都知道自定义View一般有三种直接继承View继承原有的控件对控件的进行修改重新拼装组合,最后一种主要针对于ViewGroup。具体的怎么做不是本文的所涉及的内容(本文是基于第一种方式实现的),还不太了解的请自行查询相关资料。这次这篇文章主要给大家带来一个高仿QQ健康的自定义View的实现,在介绍的过程中会对涉及到的自定义View相关知识点进行简单的说明,着重点还是在怎么是实现这个自定义View上。

    好了,话不多说。我们来看看QQ健康页面的这个View吧。下面就是给大家讲解这个View怎么去实现。


    QQ健康

    来分析下这个View,最上面有一个圆弧,圆弧里面包含了一些文字,在圆弧的下面有几根竖条,很容易会想到这些竖条的长度是根据每天的步数来计算的。左下方是自己的头像,右下方可以点击查看。
    我是使用的第一种方式,了解自定义View的同学肯定知道,第一种方式一般就是重写OnDraw方法利用Paint在Canvas中一笔一笔的画。

    这个View的宽和高是有一定比例的。如果我们随意的给宽高,然后又没有一定的比例最后渲染出来的View肯定是很混乱的。所以我首先重写了下onMeasure方法

    在初始化方法中有个mRatio是宽高的比例,是我根据截图用像素尺亮出来的,这个因人而异,可能每个人都会有不一样的度量结果,只要记住这个的作用是用来按照一定的比例绘制这个View的就OK了,这样做的好处就是不管这个View多大多小里面的内容都能够自适应,包括后面可能会会出现的一大堆数字,看到可能会有点晕,不用去管他。

    知识点扫盲之MeasureSpec:他代表一个32位的int值,前两位代表SpecMode,后30位代表SpecSize。一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。

    从代码中可以看到如果widthMode 是EXACTLY 或者AT_MOST,我们就将父布局传递过来的测量宽度作为View的宽度。如果不是这两种就将前面定义的默认的宽度来作为View宽度(这个一般不会用到)。宽度测量完了之后,就按照一定的比例计算出高度,然后就将这个高度作为我们View的高度,这样做,View的高度都是按照宽度来计算的,这样做的好处是我们在使用这个View的时候不会导致变形。
    值得注意的是测量完了之后一定要调用 setMeasuredDimension这个方法。

    下面我们再来看看onSizeChanged方法,这里是自适应的关键

    mArcCenterX 和mArcCenterY 是最上面那个圆弧的中心。我们都知道在Android中画一个圆弧需要一个这个圆弧的外接矩形,mArcRect就是这个外接矩形,mArcWidth和mBarWidth是对应画笔的宽度,在这个方法中我们对这些值作了初始化的工作。如果在构造函数里面取调用这个方法,宽和高是未知的。

    到这里我们的初始化工作做得差不多了。下面来看看最重要的onDraw方法中都干了些什么,下面代码都是onDraw方法里面的(代码较长一次性截不完)


    我注释的还是比较详细了,步骤也已经标明了,我相信仔细看肯定能看懂。对于绘制背景那里我多说两句,绘制背景的圆角我用的是贝塞尔曲线画的,当然你也可以直接使用canvas.drawRoundRect去画,但是对于这样一种需求:一个矩形上面两个角是圆角,下面的就是正常的方角,canvas.drawRoundRect显然办不到,然而贝塞尔曲线可以很容易办到,当然贝塞尔曲线的作用不仅仅是这个,它是非常强大的,只要是你能想到的他基本上都是能办到。这里有一篇关于贝塞尔曲线比较好的文章,感兴趣的可以去看看。
    Android 自定义View高级特效,神奇的贝塞尔曲线

    最后我们来看看怎么对右下角的那个查看添加点击事件吧



    其实还是很简单,我们找到右下角对应的一个矩形区域,然后判断当前点击的坐标在不在这个矩形区域内就可以了。

    值得注意的是要记得在初始化方法中加上这句代码
    <code>setLayerType(View.LAYER_TYPE_SOFTWARE, null);</code>
    这句是关闭硬件加速,防止某些4.0的设备虚线显示为实线的问题,可以在AndroidManifest.xml时的Application标签加上android:hardwareAccelerated=”false”,这样整件应用都关闭了硬件加速,虚线可以正常显示,但是关闭硬件加速对性能有些影响,所以这里我们只对当前这个View关闭硬件加速就行了。

    我们来看看最后我们实现的效果吧。


    是不是还是挺不错的,并且还能自适应大小,和QQ的基本上一模一样。

    由于代码量还是比较大,完整的贴出来比较 ,就不贴到这篇文章中了,需要完整版代码的请点击:
    完整代码

    相关文章

      网友评论

      • RamboPan:强。
      • 釒彡尨:hatsu
      • 109cafc9f596:那些比例值是怎么来的,是怎么测量的?
        109cafc9f596:@_SOLID 我今天用了PS的像素尺来测量,和你的测量结果不一致啊,我想请问楼主的手机分辨率是多少?(只因楼主的代码写的好,所以想好好学习一下)
        _SOLID:@109cafc9f596 可以用像素尺
      • 无为不争静:写的很棒,学习了
      • suxm:请问onSizeChange方法什么时候回调,具体什么意思
        suxm:@_SOLID 谢谢
        _SOLID:@suxm 顾名思义,就是在View的大小发生改变的时候就会被调用。比如屏幕旋转的时候就会被调用,建议你去看看android的自定义View
      • RicoX2016:好棒,学习了
      • coolzpw:好!!! 楼主有个问题,这个drawArc方法,圆弧的外接矩形到底是什么,还是有点不懂- - 数学不太好 求解答。。
        _SOLID:@coolzpw 设置了这个的,mTextPaint.setTextALign(Paint.Align.CENTER)以圆弧的中心点作为文字的中心
        coolzpw:@_SOLID O(∩_∩)O谢谢,清楚了些,楼主我看你drawtext是以屏幕一半为起点画的,照理应该效果不会这么正啊- -
        _SOLID:@coolzpw 你应该知道画一个圆可以先画一个正方形,然后以这个正方形画一个内接圆。这里画圆弧原理和这个是一样的
      • hony_:非常不错
      • andyMe:写的好棒!请问在onSizeChanged方法中 计算圆形的圆心这些浮点数是计算出来的还是怎样的?
        _SOLID:@andy_leebo 根据QQ直接测量的
      • 找个森林:太赞了!!!
      • jasonkxs:高仿的不错
        _SOLID:@jasonkxs 不然怎么能叫高仿呢 :blush:
      • Aracys:和原控件比,少了动画,不过还是不错的
        _SOLID: @xsfelvis👍 明天我再去看看
        xsfelvis:已经帮你加了动画了,谢谢分享~ https://github.com/xsfelvis/CusTomView_Animator/blob/master/customView/app/src/main/java/xsf/customView/views/qq_health.java
        _SOLID:@Aracys 有了这个加动画还是很简单的,后面有时间了,我就把动画给加上
      • Amanda皮卡丘:很棒!赞!继续加油哦支持你~
        _SOLID:@Amanda皮卡丘 谢谢支持~
      • a46aa4d1b3f8:效果不错😀
      • 蛋蛋不哭:写的不错

      本文标题:Android自定义View之高仿QQ健康

      本文链接:https://www.haomeiwen.com/subject/jcablttx.html