自定义滑动条

使用贝塞尔曲线绘制的自定义滑动条,不多说,先看效果图

关键代码分析:

1.定义变量

    //假设 控件高度为115,可以求得弧度的:开始点、结束点的坐标和控制点的坐标
    private int bgColor = Color.WHITE;//控件背景色
    private int viewHight = 200;//控件的高度
    private int rSliderBlock = 40;//圆形滑块半径
    private float drawX = 0;//滑块滑动时x坐标
    private int index = 6;//滑块停止滑动后,当前选中的位置 1-9
    private int preIndexPx = 150;//每个位置的间距(18个分隔)
    private int lineWidth = 5;//线背景的宽度
    private int dengSize = 30;//等号字体大小
    private int gaoDiSize = 30;//“高低”字体大小
    private int zhiShuSize = 40;//“风险指数”字体大小
    private boolean isMoving = false;//是否正在滑动
    private int tmpIndex = 0;//用来保存滑块滑动超过index的preIndexPx的距离范围时,index值在tmpIndex中不变

2.绘制凸起的弧度

        //将高阶贝塞尔曲线降阶到二阶:分成4段进行绘制
        if (isMoving) {//移动中,使用滑动的X坐标进行计算
            path.moveTo(drawX - preIndexPx * 2, viewHight * 0.5f);
            path.quadTo(drawX - preIndexPx * 2 + preIndexPx * 0.5f, viewHight * 0.5f, drawX - preIndexPx * 2 + preIndexPx, viewHight * 0.5f - preIndexPx * 0.5f);
            path.quadTo(drawX - preIndexPx * 0.5f, viewHight * 0.5f - preIndexPx, drawX, viewHight * 0.5f - preIndexPx);//viewHight * 0.5f-preIndexPx表示:弧度的顶点为一个preIndexPx的高度
            path.quadTo(drawX + preIndexPx * 0.5f, viewHight * 0.5f - preIndexPx, drawX + preIndexPx, viewHight * 0.5f - preIndexPx * 0.5f);//viewHight * 0.5f-preIndexPx表示:弧度的顶点为一个preIndexPx的高度
            path.quadTo(drawX + preIndexPx * 2 - preIndexPx * 0.5f, viewHight * 0.5f, drawX + preIndexPx * 2, viewHight * 0.5f);
        } else {
            path.moveTo(preIndexPx * (changeValue(index - 1)), viewHight * 0.5f);
            path.quadTo(preIndexPx * (changeValue(index - 1)) + preIndexPx * 0.5f, viewHight * 0.5f, preIndexPx * (changeValue(index - 1)) + preIndexPx, viewHight * 0.5f - preIndexPx * 0.5f); path.quadTo(preIndexPx * (changeValue(index)) - preIndexPx * 0.5f, viewHight * 0.5f - preIndexPx, preIndexPx * (changeValue(index)), viewHight * 0.5f - preIndexPx);//viewHight * 0.5f-preIndexPx表示:弧度的顶点为一个preIndexPx的高度 path.quadTo(preIndexPx * (changeValue(index)) + preIndexPx * 0.5f, viewHight * 0.5f - preIndexPx, preIndexPx * (changeValue(index)) + preIndexPx, viewHight * 0.5f - preIndexPx * 0.5f);//viewHight * 0.5f-preIndexPx表示:弧度的顶点为一个preIndexPx的高度 path.quadTo(preIndexPx * (changeValue(index + 1)) - preIndexPx * 0.5f, viewHight * 0.5f, preIndexPx * (changeValue(index + 1)), viewHight * 0.5f); }

3.数字随曲线位置变化而上下浮动

    /**
     * 用偏移量比例计算刻度的高度
     * 将滑块的X的坐标值drawX,从index的位置增大到index+1的位置时的距离值的变化范围,
     * 映射成刻度线和数字的Y坐标,从viewHight * 0.5f到viewHight * 0.5f-preIndexPx 的变化
     * 具体描述:
     * 滑动到index右一个2*preIndexPx距离侧时,
     * drawX变大,index位置的高度值变小,index+1位置的值变大。
     * drawX变小,index位置的高度值变大,index+1位置的值变小
     * 滑动在index左侧一个2*preIndexPx距离时
     * drawX变小,index位置的高度值变小,index-1位置的值变大
     * drawX变大,index位置的高度值变大,index-1位置的值变小。
     *
     * @return float[] 0:index位置的高度变化(偏离index位置的绝对值变大则高度变小),1:index+1 或者index-1位置的高度变化(偏离index位置的绝对值变大则高度变大)
     */
    private float[] getDistance() {
        float[] retValue = new float[]{viewHight * 0.5f, viewHight * 0.5f};
        if (tmpIndex == 0) {//首次计算时
            tmpIndex = index;
        }
        if (drawX == 0) {
            drawX = changeValue(tmpIndex) * preIndexPx;
        }
        if ((changeValue(tmpIndex) * preIndexPx - 2 * preIndexPx) >= drawX || drawX >= (changeValue(tmpIndex) * preIndexPx + 2 * preIndexPx)) {
            tmpIndex = index;//滑块滑动距离超过2*preIndexPx时对tmpIndex更新
        }
        float b = Math.abs(drawX - changeValue(tmpIndex) * preIndexPx) / (preIndexPx * 2);//计算百分比
        retValue[0] = viewHight * 0.5f - preIndexPx + preIndexPx * b;//index位置的距离变化值
        retValue[1] = viewHight * 0.5f - preIndexPx * b;//index+1或者index-1位置的距离变化值
//        Log.d(TAG, tmpIndex + "移动的结果:" + retValue[0] + ";" + retValue[1] + ";drawX:" + drawX + ";index和drawx的差值:" + Math.abs(drawX - changeValue(tmpIndex) * preIndexPx) + ";2格值:" + preIndexPx * 2 + ";百分比" + b + ";控件位置:" + viewHight * 0.5f);
        return retValue;
    }

4.具体代码参见我的gitHub seekBar 项目

猜你喜欢

转载自www.cnblogs.com/androiddream/p/9213929.html