Android - 自定义View(圆点指示器)——支持“纵向视

2017-08-18  本文已影响0人  DJN_

圆点指示器支持“纵向视图”啦

关于圆点指示器的实现请参看上一篇博文:自定义View和属性动画ValueAnimator实现圆点指示器
该篇文章将对支持纵向视图过程的关键代码和使用方法进行介绍。

小圆点 指示点 线段
椭圆 矩形

控件元素的构成

小圆点 指示点 线段
椭圆 矩形
一 效果图
这里写图片描述
二 如何使用

使用时只需在你的xml布局文件中指定indicatorOrientation属性为vertical即可。

 <com.duan.indicatorviewdemo.IndicatorView
 
             app:indicatorOrientation="vertical"
             
            android:layout_marginLeft="30dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:dotNum="5"
            app:dotSize="20dp"
            app:indicatorSize="20dp"
            app:dotColor="#a5b7b3"
            app:indicatorColor="#52ffda"
            app:lineColor="#cacaca"
            app:lineLength="90dp"
            app:lineWidth="4dp" />
三 关键代码
3.1 attr 中添加方向属性定义

本项目在attr.xml文件中添加如下属性定义,并将该属性添加到declare-styleable中:

  <attr name="indicatorOrientation" format="integer"> <!--控件方向-->
        <enum name="vertical" value="0"/> <!--纵向-->
        <enum name="horizontal" value="1"/> <!--水平-->
    </attr>

  <declare-styleable name="IndicatorView">  
    ...
       <attr name="indicatorOrientation"/>
    ...
  </declare-styleable>
3.2 修改 IndicatorView.java
//默认为 水平
        mIndicatorOrientation = array.getInteger(R.styleable.IndicatorView_indicatorOrientation, INDICATOR_ORIENTATION_HORIZONTAL);
...
if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {//xml中宽度设为warp_content
            if (mIndicatorOrientation == INDICATOR_ORIENTATION_VERTICAL) //纵向
                width = getPaddingLeft() + getPaddingRight() + mIndicatorSize;
            else
                width = getPaddingLeft() + ((mDotCount - 1) * mLineLength + mIndicatorSize) + getPaddingRight();
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            if (mIndicatorOrientation == INDICATOR_ORIENTATION_VERTICAL) //纵向
                height = ((mDotCount - 1) * mLineLength + mIndicatorSize) + getPaddingBottom() + getPaddingTop();
            else
                height = getPaddingTop() + mIndicatorSize + getPaddingBottom();
        }
        ...
 if (mIndicatorOrientation == INDICATOR_ORIENTATION_VERTICAL) { //纵向
                indicatorHolder.setCenterX(getWidth() / 2);
                indicatorHolder.setCenterY(mIndicatorPos * mLineLength + getPaddingBottom() + mIndicatorSize / 2);
            } else {
                indicatorHolder.setCenterX(mIndicatorPos * mLineLength + getPaddingLeft() + mIndicatorSize / 2);
                indicatorHolder.setCenterY(getHeight() / 2);
            }
     ...
        if (mIndicatorOrientation == INDICATOR_ORIENTATION_VERTICAL) { //纵向
            for (int i = 0; i < mDotCount - 1; i++) {
                int top = getHeight() - (getPaddingBottom() + mIndicatorSize / 2 + mLineLength * (i + 1));
                int bottom = getHeight() - (getPaddingBottom() + mIndicatorSize / 2 + mLineLength * i);
                int left = (getWidth() - mLineWidth) / 2;
                int right = (getWidth() + mLineWidth) / 2;

                canvas.drawRect(left, top, right, bottom, mPaint);
                }
    ...
...
if (mIndicatorOrientation == INDICATOR_ORIENTATION_VERTICAL) { //纵向
            for (int i = 0; i < clickableAreas.length; i++) {
                int cx = getWidth() / 2;
                int cy = i * mLineLength + getPaddingBottom() + mIndicatorSize / 2;

                if (switchTo != -1 && i == switchTo)
                    mPaint.setColor(mIndicatorColor);
                else
                    mPaint.setColor(mDotColor);

                canvas.drawCircle(cx, cy, mDotSize, mPaint);
                clickableAreas[i][0] = cx;
                clickableAreas[i][1] = cy;
            }
            ...
...
 int ey = (int) event.getY();
 ...
 //纵向
   for (; switchTo < mDotCount; switchTo++) {
                int[] xy = clickableAreas[switchTo];
                //只对y坐标位置进行判断,这样即使用户手指在控件外面(先在控件内触摸后不抬起而是滑到控件外面)滑动也能判断
                if (ey <= xy[1] + temp && ey >= xy[1] - temp) {
                    break;
                }
            }
...
if (mIndicatorOrientation == INDICATOR_ORIENTATION_VERTICAL) { //纵向
                    indicatorHolder.setCenterY(ey);
                } 
                ...
...
 if (mIndicatorOrientation == INDICATOR_ORIENTATION_VERTICAL) { //纵向
            int start = indicatorHolder.getCenterY();
            end = switchTo * mLineLength + getPaddingBottom() + mIndicatorSize / 2;
            trainsAnim = ObjectAnimator.ofInt(indicatorHolder, "centerY", start, end);
        }
...

挤压动画:为“纵向视图”时挤压动画改变indicatorHolder的宽度(centerW)因为线段的宽度,高度(centerH)为指示点当前所在位置和目标点间的距离。

...
if (mIndicatorOrientation == INDICATOR_ORIENTATION_VERTICAL) { //纵向
                        centerH = Math.abs(indicatorHolder.getCenterY() - clickableAreas[switchTo][1]);
                        centerW = mLineWidth;
                    } 
...

不使用动画:此时判断为“纵向视图”时应修改indicatorHolder的中心的纵坐标。

...
if (mIndicatorOrientation == INDICATOR_ORIENTATION_VERTICAL) //纵向
                        indicatorHolder.setCenterY(end);
...

<center>代码修改已同步到Github,你可以在这里下载到源代码:</center>
<center>DuanJiaNing/IndicatorView</center>


上一篇下一篇

猜你喜欢

热点阅读