打造炫酷进度条

来源:互联网 发布:java xbootclasspath 编辑:程序博客网 时间:2024/04/27 11:55

如何自定义控件

1.自定义属性的声明与获取

2.测量onMeasure

3.布局onLayout(ViewGroup)

4.绘制onDraw

5.onTouchEvent

6.onInterceptTouchEvent(ViewGroup)

7.状态的恢复与保存


自定义属性的声明与获取

1.分析需要的自定义属性

2.在res/values/attrs.xml定义声明

3.在layout文件中进行使用

4.在View的构造方法中进行获取


条形进度条


attrs.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <attr name="progress_unreach_color" format="color"></attr>    <attr name="progress_unreach_height" format="dimension"></attr>    <attr name="progress_reach_color" format="color"></attr>    <attr name="progress_reach_height" format="dimension"></attr>    <attr name="progress_text_color" format="color"></attr>    <attr name="progress_text_size" format="dimension"></attr>    <attr name="progress_text_offset" format="dimension"></attr>    <declare-styleable name="HorizontalProgressBarWithProgress">        <attr name="progress_unreach_color"></attr>        <attr name="progress_unreach_height"></attr>        <attr name="progress_reach_color"></attr>        <attr name="progress_reach_height"></attr>        <attr name="progress_text_color"></attr>        <attr name="progress_text_size"></attr>        <attr name="progress_text_offset"></attr>    </declare-styleable></resources>


HorizontalProgressBarWithProgress.java


public class HorizontalProgressBarWithProgress extends ProgressBar {    private static final int DEFAULT_TEXT_SIZE = 10; // sp    private static final int DEFAULT_TEXT_COLOR = 0xFFFC00D1;    private static final int DEFAULT_COLOR_UNREACH = 0xFFD3D6DA;    private static final int DEFAULT_HEIGHT_UNREACH = 2; // dp    private static final int DEFAULT_COLOR_REACH = DEFAULT_TEXT_COLOR;    private static final int DEFAULT_HEIGHT_REACH = 2; // dp    private static final int DEFAULT_TEXT_OFFSET = 10; // dp    private int mTextSize = sp2px(DEFAULT_TEXT_SIZE);    private int mTextColor = DEFAULT_TEXT_COLOR;    private int mUnReachColor = DEFAULT_COLOR_UNREACH;    private int mUnReachHeight = dp2px(DEFAULT_HEIGHT_UNREACH);    private int mReachColor = DEFAULT_COLOR_REACH;    private int mReachHeight = dp2px(DEFAULT_HEIGHT_REACH);    private int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);    private Paint mPaint = new Paint();    /**     * 在onMeasure中初始化     * 在onDraw中使用     */    private int mRealWidth;    public HorizontalProgressBarWithProgress(Context context) {        this(context, null);    }    public HorizontalProgressBarWithProgress(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public HorizontalProgressBarWithProgress(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        //获取自定义属性        obtainStyledAttrs(attrs);    }    /**     * 获取自定义属性     *     * @param attrs     */    private void obtainStyledAttrs(AttributeSet attrs) {        TypedArray ta = getContext().obtainStyledAttributes(attrs,                R.styleable.HorizontalProgressBarWithProgress);        mTextSize = (int) ta.getDimension(                R.styleable.HorizontalProgressBarWithProgress_progress_text_size, mTextSize);        mTextColor = ta.getColor(                R.styleable.HorizontalProgressBarWithProgress_progress_text_color, mTextColor);        mTextOffset = (int) ta.getDimension(                R.styleable.HorizontalProgressBarWithProgress_progress_text_offset, mTextOffset);        mUnReachColor = ta.getColor(                R.styleable.HorizontalProgressBarWithProgress_progress_unreach_color, mUnReachColor);        mUnReachHeight = (int) ta.getDimension(                R.styleable.HorizontalProgressBarWithProgress_progress_unreach_height, mUnReachHeight);        mReachColor = ta.getColor(                R.styleable.HorizontalProgressBarWithProgress_progress_reach_color, mReachColor);        mReachHeight = (int) ta.getDimension(                R.styleable.HorizontalProgressBarWithProgress_progress_reach_height, mReachHeight);        ta.recycle();        mPaint.setTextSize(mTextSize);    }    @Override    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthVal = MeasureSpec.getSize(widthMeasureSpec);        int height = measureHeight(heightMeasureSpec);        //确定view的宽和高        setMeasuredDimension(widthVal, height);        mRealWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();    }    private int measureHeight(int heightMeasureSpec) {        int result = 0;        int mode = MeasureSpec.getMode(heightMeasureSpec);        int size = MeasureSpec.getSize(heightMeasureSpec);        //精确值(如match_parent、200dp一类)        if (mode == MeasureSpec.EXACTLY) {            result = size;        } else {            //当前绘制底线(descent) 当前绘制顶线(ascent) ascent为负值            //结果为文字的高度            int textHeight = (int) (mPaint.descent() - mPaint.ascent());            result = getPaddingTop() + getPaddingBottom() +                    Math.max(Math.max(mReachHeight, mUnReachHeight), Math.abs(textHeight));            //测量值不能超过给定的size值            if (mode == MeasureSpec.AT_MOST) {                return Math.min(result, size);            }        }        return result;    }    @Override    protected synchronized void onDraw(Canvas canvas) {        canvas.save();        canvas.translate(getPaddingLeft(), getHeight() / 2);        boolean noNeedUnReach = false;        //draw reach bar        String text = getProgress() + "%";        int textWidth = (int) mPaint.measureText(text);        float radio = getProgress() * 1.0f / getMax();        float progressX = radio * mRealWidth;        if (progressX + textWidth > mRealWidth) {            progressX = mRealWidth - textWidth;            noNeedUnReach = true;        }        float endX = progressX - mTextOffset / 2;        if (endX > 0) {            mPaint.setColor(mReachColor);            mPaint.setStrokeWidth(mReachHeight);            canvas.drawLine(0, 0, endX, 0, mPaint);        }        //draw text        mPaint.setColor(mTextColor);        int y = (int) (-(mPaint.descent() + mPaint.ascent()) / 2);        canvas.drawText(text, progressX, y, mPaint);        //draw unreach bar        if (!noNeedUnReach) {            float start = progressX + mTextOffset / 2 + textWidth;            mPaint.setColor(mUnReachColor);            mPaint.setStrokeWidth(mUnReachHeight);            canvas.drawLine(start, 0, mRealWidth, 0, mPaint);        }        canvas.restore();    }    private int dp2px(int dpVal) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,                getResources().getDisplayMetrics());    }    private int sp2px(int spVal) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,                getResources().getDisplayMetrics());    }}



activity_main.xml

<?xml version="1.0" encoding="utf-8"?><ScrollView xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:liu="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical">        <com.example.view.HorizontalProgressBarWithProgress            android:id="@+id/id_progress01"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginTop="30dp"            android:padding="15dp"            android:progress="0"            liu:progress_reach_color="#ffff0000"            liu:progress_text_color="#ffff0000"            liu:progress_unreach_color="#44ff0000" />        <com.example.view.HorizontalProgressBarWithProgress            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginTop="30dp"            android:padding="15dp"            android:progress="100"            liu:progress_text_color="#44ff0000"            liu:progress_unreach_color="#ffff0000" />        <com.example.view.HorizontalProgressBarWithProgress            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginTop="30dp"            android:padding="15dp"            android:progress="30"            liu:progress_text_color="#44ff0000"            liu:progress_unreach_color="#ffff0000" />    </LinearLayout></ScrollView>



MainActivity.java


public class MainActivity extends AppCompatActivity {    private final int MSG_UPDATE = 0x110;    private Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            int progress = mHProgress.getProgress();            mHProgress.setProgress(++progress);            if (progress >= 100) {                mHandler.removeMessages(MSG_UPDATE);            }            mHandler.sendEmptyMessageDelayed(MSG_UPDATE, 100);        }    };    private HorizontalProgressBarWithProgress mHProgress;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mHProgress = (HorizontalProgressBarWithProgress) findViewById(R.id.id_progress01);        mHandler.sendEmptyMessage(MSG_UPDATE);    }}


圆形进度条


attrs.xml

    <declare-styleable name="RoundProgressBarWithProgress">        <attr name="radius" format="dimension"></attr>    </declare-styleable>

activity_main.xml

        <com.example.view.RoundProgressBarWithProgress            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginTop="30dp"            android:padding="15dp"            android:progress="30"            liu:radius="20dp"            liu:progress_text_color="#ff000000"            liu:progress_unreach_color="#ffff0000" />        <com.example.view.RoundProgressBarWithProgress            android:id="@+id/id_progress02"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginTop="30dp"            android:padding="15dp"            android:progress="0"            liu:radius="60dp"            liu:progress_text_color="#ff000000"            liu:progress_text_size="30sp"            liu:progress_unreach_color="#44ff0000" />



RoundProgressBarWithProgress.java

public class RoundProgressBarWithProgress extends HorizontalProgressBarWithProgress {    private int mRadius = dp2px(30);    private int mMaxPaintWidth;    public RoundProgressBarWithProgress(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public RoundProgressBarWithProgress(Context context) {        this(context, null);    }    public RoundProgressBarWithProgress(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mReachHeight = (int) (mUnReachHeight * 2.5f);        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBarWithProgress);        mRadius = (int) ta.getDimension(R.styleable.RoundProgressBarWithProgress_radius, mRadius);        ta.recycle();        //设置画笔为空心        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setAntiAlias(true);        //防抖动        mPaint.setDither(true);        //设置画笔的笔触风格        //ROUND 圆角的笔触        mPaint.setStrokeCap(Paint.Cap.ROUND);    }    @Override    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        mMaxPaintWidth = Math.max(mReachHeight, mUnReachHeight);        //默认四个padding一致        int expect = mRadius * 2 + mMaxPaintWidth + getPaddingLeft() + getPaddingRight();        int width = resolveSize(expect, widthMeasureSpec);        int height = resolveSize(expect, heightMeasureSpec);        int realWidth = Math.min(width, height);        mRadius = (realWidth - getPaddingLeft() - getPaddingRight() - mMaxPaintWidth) / 2;        setMeasuredDimension(realWidth, realWidth);    }    @Override    protected synchronized void onDraw(Canvas canvas) {        String text = getProgress() + "%";        float textWidth = mPaint.measureText(text);        float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;        canvas.save();        canvas.translate(getPaddingLeft() + mMaxPaintWidth / 2, getPaddingTop() + mMaxPaintWidth / 2);        mPaint.setStyle(Paint.Style.STROKE);        //draw unreach bar        mPaint.setColor(mUnReachColor);        mPaint.setStrokeWidth(mUnReachHeight);        canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);        //draw reach bar        mPaint.setColor(mReachColor);        mPaint.setStrokeWidth(mReachHeight);        //弧度        float sweepAngle = getProgress() * 1.0f / getMax() * 360;        canvas.drawArc(new RectF(0, 0, mRadius * 2, mRadius * 2), 0, sweepAngle, false, mPaint);        //draw text        mPaint.setColor(mTextColor);        mPaint.setStyle(Paint.Style.FILL);        canvas.drawText(text, mRadius - textWidth / 2, mRadius - textHeight, mPaint);        canvas.restore();    }}


https://github.com/LiuchangDuan/demo






0 0
原创粉丝点击