自定义标尺控件

原文地址:https://blog.csdn.net/qq_31433525/article/details/79107871


示例

示例

功能描述

通过输入的list节点表示标尺刻度,不规定每一个相同,当长度相同,取得的值只能是节点上的值,没有中间值。支持左滑右滑,滑动有动画,并且划过一般自动滑到节点,未满一半返回原节点。

代码

public class RulerView extends View {
    /**屏幕宽度*/
    private int screenWidth;
    /**控件高度*/
    private int viewHeight;
    /**view宽度*/
    private int viewWidth;
    /**m每一小格的长度*/
    private int oneItemValue;
    /**端点节点*/
    private List<String> list =new ArrayList<>();
    /**滑动监听器*/
    private OnRulerChangeListener rulerListener;
    /**滚动计算类*/
    private Scroller              scroller;
    /**手势监听*/
    private GestureDetector       gestureDetector;
    /**偏移量*/
    private int                   offset;
    /**绘制的开始位置*/
    private int                   location;
    /**显示哪个list值*/
    private int                   distanceInteger;
    /**游标颜色*/
    private int                   cursorColor;
    /**刻度颜色*/
    private int                   scaleColor;
    /**刻度字体颜色*/
    private int                   scaleTextColor;
    /**刻度字体大小*/
    private int                   scaleTextSize;
    /**手指抬起时的偏移量*/
    private int                   upOffset;
    /**是否标尺往回走*/
    private boolean               isBack;
    /**字体所处高度比例*/
    private float                 scaleTextHeight;
    /**游标长度比例*/
    private float cursorHeight;

    public void setList(List<String> list) {
        this.list = list;
        invalidate();
    }

    public void setRulerListener(OnRulerChangeListener rulerListener) {
        this.rulerListener = rulerListener;
    }

    public RulerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        WindowManager  windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm            = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(dm);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RulerView);
        cursorColor = typedArray.getColor(R.styleable.RulerView_cursor_color, Color.rgb(255,0,0));
        scaleColor = typedArray.getColor(R.styleable.RulerView_scale_color,Color.argb(255,102,102,102));
        scaleTextColor = typedArray.getColor(R.styleable.RulerView_scale_text_color,Color.argb(255,102,102,102));
        scaleTextSize = typedArray.getDimensionPixelOffset(R.styleable.RulerView_scale_text_size,36);
        scaleTextHeight = typedArray.getFloat(R.styleable.RulerView_scale_text_height,(float)0.25);
        cursorHeight = typedArray.getFloat(R.styleable.RulerView_cursor_height,(float) 0);
        screenWidth = dm.widthPixels;
        oneItemValue = screenWidth/20;
        //滚动计算器
        scroller = new Scroller(context);
        //一定要加,不然只会收到onDown,onShowPress,onLongPress3个事件
        setClickable(true);
        //手势解析
        gestureDetector = new GestureDetector(context, gestureListener);
        //是否允许长点击
        gestureDetector.setIsLongpressEnabled(false);
        location=screenWidth/2;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        viewHeight = MeasureSpec.getSize(heightMeasureSpec);
        if(list.size() == 0){
            list.add("0");
        }
        viewWidth=oneItemValue*(list.size()-1)*5;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        viewWidth=oneItemValue*(list.size()-1)*5;
        drawBottomLine(canvas);
        drawScale(canvas);
        drawCursor(canvas);
    }
    /**绘制刻度*/
    private void drawScale(Canvas canvas) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(3);
        paint.setColor(scaleColor);
        Paint paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintText.setTextSize(scaleTextSize);
        paintText.setColor(scaleTextColor);
        for(int i=0;i <= (list.size()-1)*5;i++){
            int currentLocation=location+i*oneItemValue;
            if(i % 5 == 0){
                String drawStr;
                drawStr = list.get(i/5);
                Rect bounds = new Rect();
                paintText.getTextBounds(drawStr, 0, drawStr.length(), bounds);
                canvas.drawText(drawStr, currentLocation - bounds.width() / 2, viewHeight-viewHeight*scaleTextHeight, paintText);
                canvas.drawLine(currentLocation, viewHeight-viewHeight/5, currentLocation, viewHeight, paint);
            }else{
                canvas.drawLine(currentLocation, viewHeight-viewHeight/8, currentLocation, viewHeight, paint);
            }
        }
    }

    /**绘制游标*/
    private void drawCursor(Canvas canvas) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(3);
        paint.setColor(cursorColor);
        if(scroller.computeScrollOffset()){
            canvas.drawLine(screenWidth/2+scroller.getCurrX(), viewHeight*cursorHeight, screenWidth/2+scroller.getCurrX(), viewHeight, paint);
        }else{
            canvas.drawLine(screenWidth/2+offset, viewHeight*cursorHeight, screenWidth/2+offset, viewHeight, paint);
        }
    }

    /**绘制底部横线*/
    private void drawBottomLine(Canvas canvas) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(3);
        paint.setColor(Color.rgb(102,102,102));
        if(scroller.computeScrollOffset()){
            canvas.drawLine(scroller.getCurrX(),viewHeight,screenWidth+scroller.getCurrX(), viewHeight, paint);
        }else{
            canvas.drawLine(offset, viewHeight, screenWidth+offset, viewHeight, paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        gestureDetector.onTouchEvent(event);
        if(event.getAction() == MotionEvent.ACTION_UP){
            changeValue();
            upOffset = offset;
            offset = distanceInteger *5*oneItemValue;
            if(isBack){
                scroller.startScroll(upOffset,0,-(upOffset-offset),0,1000);
            }else{
                scroller.startScroll(upOffset,0,(offset-upOffset),0,1000);
            }
            invalidate();
        }
        return super.onTouchEvent(event);
    }
    /**改变textView*/
    private void changeValue(){
        distanceInteger= offset/(oneItemValue*5);
        int distanceRemainder = offset % (oneItemValue*5);
        if(distanceRemainder >=oneItemValue*5/2){
            distanceInteger=distanceInteger+1;
            isBack=false;
        }else{
            isBack=true;
        }
        if(rulerListener != null){
            if(distanceInteger >= list.size()){
                distanceInteger = list.size() -1;
            }
            rulerListener.setValue(Integer.valueOf(list.get(distanceInteger)));
        }
    }
    private GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener(){
        /**
         * @param e1 滑动事件的起点(也就是说onDown()的时候)
         * @param e2 当前滑动位置点(手指的位置)
         * @param distanceX 上次滑动(调用onScroll)到这次滑动的X轴的距离px
         * @param distanceY 上次滑动(调用onScroll)到这次滑动的Y轴的距离px
         */
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            if(offset >= viewWidth && distanceX >= 0){
                distanceX =0;
                offset=viewWidth;
            }else if(offset <= 0 && distanceX <= 0){
                distanceX = 0;
                offset =0;
            }
            scroller.forceFinished(true);
            offset=offset+(int)distanceX;
            scrollTo(offset,0);
            return super.onScroll(e1, e2, distanceX, distanceY);
        }

        /***
         * @param e1 拖动动事件的起点(也就是说onDown()的时候)
         * @param e2 onFling()调用时,手指的位置
         * @param velocityX X轴上每秒滑动像素值
         * @param velocityY Y轴上每秒滑动像素值
         * 当拖动速率velocityX或velocityY超过ViewConfiguration.getMinimumFlingVelocity()最小拖动速率时,才会调用onFling(),
         * 也就是如果只拖动一点,或是慢慢的拖动,是不会触发该方法
         */
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            scroller.fling(offset, 0, (int) (-velocityX / 1.5), 0, 0, viewWidth, 0, 0);
            return super.onFling(e1, e2, velocityX, velocityY);

        }
    };
    @Override
    public void computeScroll() {
        super.computeScroll();
        if(scroller.computeScrollOffset()){
            scrollTo(scroller.getCurrX(),0);
            invalidate();
        }else{
            scrollTo(offset,0);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
public interface OnRulerChangeListener {
    /**设置值*/
    void setValue(int value);
}
  • 1
  • 2
  • 3
  • 4
  • 5
<resources>
    <declare-styleable name="RulerView">
        <!--游标的颜色-->
        <attr name="cursor_color" format="color"></attr>
        <!--刻度颜色-->
        <attr name="scale_color" format="color"></attr>
        <!--刻度字体颜色-->
        <attr name="scale_text_color" format="color"></attr>
        <!--刻度字体大小-->
        <attr name="scale_text_size" format="dimension"></attr>
        <!--字体所处高度-->
        <attr name="scale_text_height" format="float"></attr>
        <!--游标长度比例-->
        <attr name="cursor_height" format="float"></attr>
    </declare-styleable>
</resources>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

使用

<com.example.RulerView
        android:id="@+id/rulerview"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:layout_marginTop="10dp"
        app:cursor_color="#ff0000"
        app:scale_color="#333333"
        app:scale_text_color="#333333"
        app:scale_text_size="20sp" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
public class MainActivity extends AppCompatActivity implements OnRulerChangeListener {
    TextView  textView;
    RulerView rulerView;
    int       num;
    private int currLocation = 500;
    private List<String> list=new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        list.add(0,"500");
        list.add(1,"1000");
        list.add(2,"1400");
        rulerView = (RulerView) findViewById(R.id.rulerview);
        rulerView.setRulerListener(this);
        rulerView.setList(list);
        textView = (TextView) findViewById(R.id.tvValue);
        textView.setText(currLocation + "");

    }

    @Override
    public void setValue(int value) {
        textView.setText(value+"");
    }
}

猜你喜欢

转载自blog.csdn.net/chenhuakang/article/details/79793647