打造Android 最实用的ViewPager 指示器控件

来源:互联网 发布:网络黑白pdf下载 编辑:程序博客网 时间:2024/05/04 15:53

为什么我说它是最实用的 ViewPager 指示器控件呢? 
它有以下几个特点: 
1、通过自定义 View 来实现,代码简单易懂; 
2、使用起来非常方便; 
3、通用性高,大部分涉及到 ViewPager 指示器的地方都能使用此控件; 
4、实现了两种指示器效果,传统版指示器和流行版指示器(具体请看效果图)

一、先来看效果图 
传统版指示器的效果图: 
这里写图片描述

流行版指示器的效果 
这里写图片描述

二、分析 
如果单纯的要实现此功能,相信,大家都能实现,而我也不会拿出来这里讲了,这里我是要把它打造成一个控件,通俗一点讲就是,在以后可以直接拿来用,而不需要修改代码。 
控件,那就离不开自定义 View,我在前面也讲了一篇关于自定义 View 的文章 Android自定义View,你必须知道的几点 ,虽然讲的很浅,但我觉得还是非常有用处的,有兴趣的可以阅读一下,对理解这篇文章很有帮助。额,跑题了! 回顾下那两张效果图,整个 View 需要的资源其实只有两张图片;唯一的难点,就是对图片绘制的位置如何计算;既然是实现通用型易用的控件,那就不能再 ViewPager 的 OnPagerChangerListener 中来改变指示器的状态,所以这个时候,就得把 ViewPager 传入到这个控件中,到这里,分析的差不多了;

三、编码实现功能 
像白饭要一口一口的吃,这里就得先创建一个类,然后让他继承之 View,前期步骤跟我的上一篇 blog 很像,就不累赘了,直接上代码

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">IndicatorView</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">View</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ViewPager</span>.<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">OnPageChangeListener</span>{</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//指示器图标,这里是一个 drawable,包含两种状态,</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//选中和飞选中状态</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Drawable mIndicator;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//指示器图标的大小,根据图标的宽和高来确定,选取较大者</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mIndicatorSize ;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//整个指示器控件的宽度</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mWidth ;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*图标加空格在家 padding 的宽度*/</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mContextWidth ;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//指示器图标的个数,就是当前ViwPager 的 item 个数</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mCount ;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*每个指示器之间的间隔大小*/</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mMargin ;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*当前 view 的 item,主要作用,是用于判断当前指示器的选中情况*/</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mSelectItem ;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*指示器根据ViewPager 滑动的偏移量*/</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> mOffset ;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*指示器是否实时刷新*/</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mSmooth ;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*因为ViewPager 的 pageChangeListener 被占用了,所以需要定义一个    * 以便其他调用    * */</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> ViewPager.OnPageChangeListener mPageChangeListener ;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">IndicatorView</span>(Context context) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>(context, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">IndicatorView</span>(Context context, AttributeSet attrs) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>(context, attrs, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">IndicatorView</span>(Context context, AttributeSet attrs, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> defStyleAttr) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(context, attrs, defStyleAttr);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//通过 TypedArray 获取自定义属性</span>        TypedArray typedArray = getResources().obtainAttributes(attrs, R.styleable.IndicatorView);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取自定义属性的个数</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> N = typedArray.getIndexCount();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < N; i++) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> attr = typedArray.getIndex(i);            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">switch</span> (attr) {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> R.styleable.IndicatorView_indicator_icon:                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//通过自定义属性拿到指示器</span>                    mIndicator = typedArray.getDrawable(attr);                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> R.styleable.IndicatorView_indicator_margin:                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> defaultMargin = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>,getResources().getDisplayMetrics());                    mMargin = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) typedArray.getDimension(attr , defaultMargin);                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span> ;                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> R.styleable.IndicatorView_indicator_smooth:                    mSmooth = typedArray.getBoolean(attr,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>) ;                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;            }        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//使用完成之后记得回收</span>        typedArray.recycle();        initIndicator() ;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">initIndicator</span>() {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取指示器的大小值。一般情况下是正方形的,也是时,你的美工手抖了一下,切出一个长方形来了,</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//不用怕,这里做了处理不会变形的</span>        mIndicatorSize = Math.max(mIndicator.getIntrinsicWidth(),mIndicator.getIntrinsicHeight()) ;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*设置指示器的边框*/</span>        mIndicator.setBounds(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,mIndicator.getIntrinsicWidth(),mIndicator.getIntrinsicWidth());    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li></ul>

这里需要注意一点的就是 Drawable mIndicator这个成员变量,它是在 drawable 文件夹下定义的一个 drawable 文件,包含了选中和为选中两张图片。

接着是测量工作

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * 测量View 的大小,这个方法我前面的 blog 讲了很多了,     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> widthMeasureSpec     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> heightMeasureSpec     */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onMeasure</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> widthMeasureSpec, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> heightMeasureSpec) {        setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));    }    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * 测量宽度,计算当前View 的宽度     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> widthMeasureSpec     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @return</span>     */</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">measureWidth</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> widthMeasureSpec){        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mode = MeasureSpec.getMode(widthMeasureSpec) ;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> size = MeasureSpec.getSize(widthMeasureSpec) ;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> width ;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> desired = getPaddingLeft() + getPaddingRight() + mIndicatorSize*mCount + mMargin*(mCount -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) ;        mContextWidth = desired ;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mode == MeasureSpec.EXACTLY){            width = Math.max(desired, size)  ;        }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mode == MeasureSpec.AT_MOST){                width = Math.min(desired,size) ;            }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                width = desired ;            }        }        mWidth = width ;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> width ;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">measureHeight</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> heightMeasureSpec){        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mode = MeasureSpec.getMode(heightMeasureSpec) ;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> size = MeasureSpec.getSize(heightMeasureSpec) ;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> height ;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mode == MeasureSpec.EXACTLY){            height = size ;        }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> desired = getPaddingTop() + getPaddingBottom() + mIndicatorSize ;            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mode == MeasureSpec.AT_MOST){                height = Math.min(desired,size) ;            }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                height = desired ;            }        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> height ;    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li></ul>

测量完了,就到了绘制 View 的阶段了。这里重点看看 onDraw()方法,先说一下,大致流程, 
首先,绘制所有为选中的指示器,这里是绘制 Drawable,所以需要用到 Canvas中的某些方法来平移画布,让其顺序的绘制所有的 Drawable,这里特别注意的一点就是 Canvas.restore() 方法,这个方法是在绘制完成之后,想要回到原来的位置和状态调用,但它必须配合Canvas.save()来配套使用。Canvas.save()就是记录当前画布的状态,所以这里,我觉得这个方法的名字应该换成 record()是不是更符合我们的理解呢?这里纯属个人见解,理解了就好,如何命名不妨碍我们的工作,下面是 onDraw()的代码,注释很详细

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * 绘制指示器     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> canvas     */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onDraw</span>(Canvas canvas) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*        * 首先得保存画布的当前状态,如果位置行这个方法        * 等一下的 restore()将会失效,canvas 不知道恢复到什么状态        * 所以这个 save、restore 都是成对出现的,这样就很好理解了。        * */</span>        canvas.save() ;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*        * 这里开始就是计算需要绘制的位置,        * 如果不好理解,请按照我说的做,拿起        * 附近的纸和笔,在纸上绘制一下,然后        * 你就一目了然了,        *        * */</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> left = mWidth/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> - mContextWidth/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> +getPaddingLeft() ;        canvas.translate(left,getPaddingTop());        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> ; i < mCount ; i++){            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*            * 这里也需要解释一下,            * 因为我们额 drawable 是一个selector 文件            * 所以我们需要设置他的状态,也就是 state            * 来获取相应的图片。            * 这里是获取未选中的图片            * */</span>            mIndicator.setState(EMPTY_STATE_SET) ;            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*绘制 drawable*/</span>            mIndicator.draw(canvas);            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*每绘制一个指示器,向右移动一次*/</span>            canvas.translate(mIndicatorSize+mMargin,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*        * 恢复画布的所有设置,也不是所有的啦,        * 根据 google 说法,就是matrix/clip        * 只能恢复到最后调用 save 方法的位置。        * */</span>        canvas.restore();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*这里又开始计算绘制的位置了*/</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> leftDraw = (mIndicatorSize+mMargin)*(mSelectItem + mOffset);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*        * 计算完了,又来了,平移,为什么要平移两次呢?        * 也是为了好理解。        * */</span>        canvas.translate(left,getPaddingTop());        canvas.translate(leftDraw,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*        * 把Drawable 的状态设为已选中状态        * 这样获取到的Drawable 就是已选中        * 的那张图片。        * */</span>        mIndicator.setState(SELECTED_STATE_SET) ;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*这里又开始绘图了*/</span>        mIndicator.draw(canvas);    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li></ul>

现在我们的控件其实就差一步没有实现了,就是在何时何地更新 View,一开始就分析了,这个 View 是需要传入 ViewPager 的,传入 ViewPager 的目的是什么,其实有三个, 
1、获取 ViewPager 的 item 的个数,从而来确定指示器的个数; 
2、获取当前 ViewPager 选中的 item,也是确定指示器选中的 item; 
3、获取 OnPagerChangeListener,来控制 View 什么时候需要刷新;

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * 此ViewPager 一定是先设置了Adapter,     * 并且Adapter 需要所有数据,后续还不能     * 修改数据     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> viewPager     */</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setViewPager</span>(ViewPager viewPager){        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(viewPager == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;        }        PagerAdapter pagerAdapter = viewPager.getAdapter() ;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(pagerAdapter == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> RuntimeException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"请看使用说明"</span>);        }        mCount = pagerAdapter.getCount() ;        viewPager.setOnPageChangeListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);        mSelectItem = viewPager.getCurrentItem() ;        invalidate();    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setOnPageChangeListener</span>(ViewPager.OnPageChangeListener mPageChangeListener) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mPageChangeListener = mPageChangeListener;    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onPageScrolled</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> positionOffset, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> positionOffsetPixels) {        Log.v(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"zgy"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"========"</span>+position+<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">",===offset"</span> + positionOffset) ;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mSmooth){            mSelectItem = position ;            mOffset = positionOffset ;            invalidate();        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mPageChangeListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){            mPageChangeListener.onPageScrolled(position,positionOffset,positionOffsetPixels);        }    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onPageSelected</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position) {        mSelectItem = position ;        invalidate();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mPageChangeListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){            mPageChangeListener.onPageSelected(position);        }    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onPageScrollStateChanged</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> state) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mPageChangeListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){            mPageChangeListener.onPageScrollStateChanged(state);        }    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li></ul>

这个位置也有个点需要提一下,就是当 mSmooth 为 true 的时候,这个时候是需要实时刷新的,所以需要在onPageScrolled(int position, float positionOffset, int positionOffsetPixels)调用 invalidate(),并把偏移量保存起来,用于计算绘制指示器的位置。

好了,以上就是指示器控件的实现全过程;

既然是一个控件,接下来看看在 xml 是如何引用的

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.gyzhong</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.viewpagerindicator</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.IndicatorView</span>        android:id=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"@+id/id_indicator"</span>        android:layout_centerHorizontal=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"true"</span>        android:layout_alignParentBottom=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"true"</span>        android:layout_marginBottom=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"20dp"</span>        android:layout_width=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"match_parent"</span>        android:layout_height=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"wrap_content"</span>        android:padding=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"5dp"</span>        zgy:indicator_icon=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"@drawable/indicator_selector"</span>        zgy:indicator_margin=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"5dp"</span>/></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

再来看看代码中的引用

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">        mIndicatorView = (IndicatorView) findViewById(R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.id</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.id</span>_indicator) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        mIndicatorView<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setViewPager</span>(mViewPager)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

代码简洁明了。

四、总结 
整体来说,不是很难,代码量很少,主要用到的知识点,1、自定义属性,2、如何测量 View,2、Cavans 中一些方法的使用;最后,看了如果觉得有用,请顶一下,谢谢!

源码下载地址:戳我

0 0
原创粉丝点击