Android 自定义SeekBar (二) Android 自定义View

一、前言

本文在 上节 的基础上,讲解自定义拖动条的实现思路。

二、思路

先在res/values文件夹下,自定义控件属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MySeekBar">

        <attr name="progress_max" format="float|reference"/> <!-- 进度条最大值 -->
        <attr name="progress_min" format="float|reference"/> <!-- 进度条最小值 -->
        <attr name="progress_default" format="float|reference"/> <!-- 进度条默认值 -->

        <attr name="track_left_height" format="dimension|reference"/> <!-- 进度条左边高度 -->
        <attr name="track_right_height" format="dimension|reference"/> <!-- 进度条右边高度 -->

        <attr name="track_left_color" format="color|reference"/> <!-- 进度条左边颜色 -->
        <attr name="track_right_color" format="color|reference"/> <!-- 进度条右边颜色 -->

        <attr name="thumb_color_default" format="color|reference"/> <!-- 拖动滑块默认颜色 -->
        <attr name="thumb_radius_default" format="dimension|reference"/> <!-- 拖动滑块半径 -->

        <attr name="thumb_color_on_dragging" format="color|reference"/> <!-- 拖动滑块拖动中颜色 -->
        <attr name="thumb_radius_on_dragging" format="dimension|reference"/> <!-- 拖动滑块拖动中半径 -->

    </declare-styleable>
</resources>

由上可知,考虑绘制拖动条必要的几个基本属性,如最大值最小值及其默认值,显示拖动效果或进度的左右高度、颜色,以及滑块的半径和颜色。默认自左往右,故进度条左边高右边稍低,而滑块需要比左边更大一些。

对应SeekBar的构造函数:

public MySeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MySeekBar, defStyleAttr, 0);

        this.progress_max = typedArray.getFloat(R.styleable.MySeekBar_progress_max, 100);
        this.progress_min = typedArray.getFloat(R.styleable.MySeekBar_progress_min, 0);
        this.progress_default = typedArray.getFloat(R.styleable.MySeekBar_progress_default, progress_min);

        this.track_left_height = typedArray.getDimensionPixelSize(R.styleable.MySeekBar_track_left_height, DimensionUtil.dp2px(8));
        this.track_right_height = typedArray.getDimensionPixelSize(R.styleable.MySeekBar_track_right_height, track_left_height - DimensionUtil.dp2px(2));

        this.track_left_color = typedArray.getColor(R.styleable.MySeekBar_track_left_color, Color.BLUE);
        this.track_right_color = typedArray.getColor(R.styleable.MySeekBar_track_right_color, Color.LTGRAY);

        this.thumb_color_default = typedArray.getColor(R.styleable.MySeekBar_thumb_color_default, track_left_color);
        this.thumb_radius_default = typedArray.getDimensionPixelSize(R.styleable.MySeekBar_thumb_radius_default, track_left_height + DimensionUtil.dp2px(2));

        this.thumb_color_on_dragging = typedArray.getColor(R.styleable.MySeekBar_thumb_color_on_dragging, thumb_color_default);
        this.thumb_radius_on_dragging = typedArray.getDimensionPixelSize(R.styleable.MySeekBar_thumb_radius_on_dragging, thumb_radius_default + DimensionUtil.dp2px(2));

        typedArray.recycle();

        thumb_radius = thumb_radius_default;

        initPaint(); // 初始化画笔
    }

由于其他基础知识点已于前面 Android 自定义View 部分讲解,此处不再赘述。着重讲解 onMeasure(测量) 部分。先上代码

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 仅当 android_layout_width = wrap_content 或未指定时生效,若测出来的size大于你所指定的size (譬如这里是180dp),则使用所指定的size
        int width = resolveSize(DimensionUtil.dp2px(180), widthMeasureSpec);
        int height = thumb_radius_on_dragging * 2; // 控件高度按拖动时的滑块直径
        setMeasuredDimension(width, height); // 强制指定控件大小

        xLeft = getPaddingLeft() + thumb_radius_on_dragging; // 实际的绘图区域按距离父布局左边 padding 算起
        xRight = getMeasuredWidth() - getPaddingRight() - thumb_radius_on_dragging; // 到距离父布局右边的的 padding 结束
        yCenter = getPaddingTop() + thumb_radius_on_dragging; // 确定绘制进度条Y轴意义上的中点
    }

此处有个resolveSize() 函数,这个函数继承自view类,

猜你喜欢

转载自www.cnblogs.com/qq1094417747/p/12956138.html
今日推荐