Android 自定义可选择范围的控件

 刚研究自定义控件不久,见别人问怎么写一个可选择范围的控件。就自己简单的写了一个。

要实现的效果如图:

代码:

package com.elink.tianyu.cardslistview.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.elink.tianyu.cardslistview.R;

/**
 * 选择范围控件
 * Created by zty on 2016/5/12.
 */
public class RangeSelectionView extends View {

    private Paint paintBackground;//背景线的画笔
    private Paint paintCircle;//起始点圆环的画笔
    private Paint paintWhileCircle;//起始点内圈白色区域的画笔
    private Paint paintText;//起始点数值的画笔
    private Paint paintConnectLine;//起始点连接线的画笔

    private int height = 0;//控件的高度
    private int width = 0;//控件的宽度

    private float centerVertical = 0;//y轴的中间位置

    private float backlineWidth = 5;//底线的宽度

    private float marginhorizontal = 35;//横向边距

    private float marginTop = 50;//文字距顶部的距离

    private float pointStart = 0;//起点的X轴位置

    private float pointEnd = 0;//始点的Y轴位置

    private float circleRadius = 30;//起始点圆环的半径

    private float numStart = 0;//数值的开始值

    private float numEnd = 0;//数值的结束值

    private int textSize = 30;//文字的大小

    private String strUnit = "¥";//刻度的单位

    private boolean isRunning = false;//是否可以滑动

    private boolean isStart = true;//起点还是终点 true:起点;false:终点。


    public RangeSelectionView(Context context) {
        super(context);
        init();
    }

    public RangeSelectionView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RangeSelectionView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //获取控件的宽高、中线位置、起始点、起始数值
        height = MeasureSpec.getSize(heightMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec);
        centerVertical = height / 2;

        pointStart = marginhorizontal;
        pointEnd = width - marginhorizontal;

        numStart = getProgressNum(pointStart);

        numEnd = getProgressNum(pointEnd);

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //如果点击的点在第一个圆内就是起点,并且可以滑动
                if (event.getX() >= (pointStart - circleRadius) && event.getX() <= (pointStart + circleRadius)) {
                    isRunning = true;
                    isStart = true;

                    pointStart = event.getX();
                    //如果点击的点在第二个圆内就是终点,并且可以滑动
                } else if (event.getX() <= (pointEnd + circleRadius) && event.getX() >= (pointEnd - circleRadius)) {
                    isRunning = true;
                    isStart = false;

                    pointEnd = event.getX();
                } else {
                    //如果触控点不在圆环内,则不能滑动
                    isRunning = false;
                }

                break;
            case MotionEvent.ACTION_MOVE:
                if (isRunning) {
                    if (isStart) {
                        //起点滑动时,重置起点的位置和进度值
                        pointStart = event.getX();
                        numStart = getProgressNum(pointStart);
                    } else {
                        //始点滑动时,重置始点的位置和进度值
                        pointEnd = event.getX();
                        numEnd = getProgressNum(pointEnd);
                    }

                    flushState();//刷新状态
                }

                break;
            case MotionEvent.ACTION_UP:

                flushState();
                break;
        }

        return true;
    }

    /**
     * 刷新状态和屏蔽非法值
     */
    private void flushState() {

        //起点非法值
        if (pointStart < marginhorizontal) {
            pointStart = marginhorizontal;
        }
        //终点非法值
        if (pointEnd > width - marginhorizontal) {
            pointEnd = width - marginhorizontal;
        }

        //防止起点位置大于终点位置(规定:如果起点位置大于终点位置,则将起点位置放在终点位置前面,即:终点可以推着起点走,而起点不能推着终点走)
        if (pointStart + circleRadius > pointEnd - circleRadius) {

            pointStart = pointEnd - 2 * circleRadius;

        }

        //防止终点把起点推到线性范围之外
        if (pointEnd < marginhorizontal + 2 * circleRadius) {
            pointEnd = marginhorizontal + 2 * circleRadius;
            pointStart = marginhorizontal;
        }

        invalidate();//这个方法会导致onDraw方法重新绘制

    }

    //进度范围
    float beginNum = 0;
    float endNum = 1000;

    //计算进度数值
    private float getProgressNum(float progress) {

        return (int) progress / (width - 2 * marginhorizontal) * (endNum - beginNum);

    }

    //初始化画笔
    private void init() {

        paintBackground = new Paint();
        paintBackground.setColor(getResources().getColor(R.color.colorBackline));
        paintBackground.setStrokeWidth(backlineWidth);
        paintBackground.setAntiAlias(true);

        paintCircle = new Paint();
        paintCircle.setColor(getResources().getColor(R.color.colorTipCircle));
        paintCircle.setStrokeWidth(backlineWidth);
        paintCircle.setStyle(Paint.Style.STROKE);
        paintCircle.setAntiAlias(true);

        paintWhileCircle = new Paint();
        paintWhileCircle.setColor(getResources().getColor(R.color.white));
        paintCircle.setStyle(Paint.Style.FILL);
        paintWhileCircle.setAntiAlias(true);

        paintText = new Paint();
        paintText.setColor(getResources().getColor(R.color.colorTipText));
        paintText.setTextSize(textSize);
        paintText.setAntiAlias(true);

        paintConnectLine = new Paint();
        paintConnectLine.setColor(getResources().getColor(R.color.colorTipCircle));
        paintConnectLine.setStrokeWidth(backlineWidth + 5);
        paintConnectLine.setAntiAlias(true);

    }

    @Override
    protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);

        //背景线
        canvas.drawLine(marginhorizontal, centerVertical, width - marginhorizontal, centerVertical, paintBackground);
        //起点位置的外圈圆
        canvas.drawCircle(pointStart, centerVertical, circleRadius, paintCircle);
       //起点位置的内圈圆
        canvas.drawCircle(pointStart, centerVertical, circleRadius - backlineWidth, paintWhileCircle);
       //终点位置的外圈圆
        canvas.drawCircle(pointEnd, centerVertical, circleRadius, paintCircle);
       //终点位置的内圈圆
        canvas.drawCircle(pointEnd, centerVertical, circleRadius - backlineWidth, paintWhileCircle);
        //起始点连接线
        canvas.drawLine(pointStart + circleRadius, centerVertical, pointEnd - circleRadius, centerVertical, paintConnectLine);
       //起点数值
        canvas.drawText(numStart + strUnit, pointStart, marginTop, paintText);
        //终点数值
        canvas.drawText(numEnd + strUnit, pointEnd, marginTop, paintText);

    }
}
布局文件:
<com.elink.tianyu.cardslistview.view.RangeSelectionView
        android:layout_width="match_parent"
        android:background="@android:color/white"
        android:layout_height="100dp" />
效果图:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值