(Android Studio)自定义 ProgressBar(一)

1 说明

据说现在很多人都开始使用Android Studio,我也开始用用吧,现在还在慢慢摸索中。。。。今天在慕课上学啦制作进度条,现在就来总结一下吧。
对了Android Studio的单词大写快捷键: Ctrl + Shift + U ;

2 效果图

这是As预览中截取的图片

3 实现步骤总结

1 建一个继承ProgressBar的类

这里暂时只需要把构造方法添加进去即可(一个参数,两个参数的和三个参数的)。
这里写图片描述
这里写图片描述

2 创建资源文件

这里主要是定义自己的控件的属性名称。如图:
这里写图片描述

3 到继承了ProgressBar的类中实现onMeasure和OnDraw

onMeasure(int widthMeasureSpec, int heightMeasureSpec):对尺寸进行测量;
onDraw(Canvas canvas):绘制图形;
以上两个方法只需要复写就可以了,View中会自动调用的。

4 具体代码

4.1 首先values中创建 atts.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>

<!--      这里是类名  HorizontalProgressBarView   -->
    <declare-styleable name="HorizontalProgressBarView">
        <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>

4.2 其次就是HorizontalProgressBarView类

package com.example.hyf.appforprogress.views;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ProgressBar;

import com.example.hyf.appforprogress.R;

/**
 * Created by Administrator on 2016/5/18.
 */
public class HorizontalProgressBarView extends ProgressBar {


    private String Tag = "houyafei" ;

    //定义默认值
    private  static final int DEFAULT_TEXT_SIZE = 10 ; // sp
    private  static final int DEFAULT_TEXT_COLOR = 0xFFFc00d1 ;
    private  static final int DEFAULT_UNREACH_COLOR = 0xffd3d6da ;
    private  static final int DEFAULT_UNREACH_HEIGHT = 2 ; // dp
    private  static final int DEFAULT_REACH_COLOR = DEFAULT_TEXT_COLOR ;
    private  static final int DEFAULT_REACH_HEIGHT= 3 ; // dp
    private  static final int DEFAULT_TEXT_OFFSET = 10 ; // dp


    //使用默认值
    private  float mTextSize = (float)sp2px(DEFAULT_TEXT_SIZE) ;
    private int mTextColor = DEFAULT_TEXT_COLOR ;
    private int mUnreachColor = DEFAULT_UNREACH_COLOR;
    private int mUnreachHeight = dp2px(DEFAULT_UNREACH_HEIGHT);
    private int mReachColor = DEFAULT_REACH_COLOR ;
    private int mReachHeight = dp2px(DEFAULT_REACH_HEIGHT);
    private int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET) ;



    private Paint mPaint = new Paint();

    private  int mRealWidth ;

    public HorizontalProgressBarView(Context context) {
        this(context,null);
    }

    public HorizontalProgressBarView(Context context, AttributeSet attrs) {
        this(context, attrs,0);

    }

    public HorizontalProgressBarView(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.HorizontalProgressBarView);

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//注意,这里的属性名称前都加了类名和下划线,与atts.xml文件中的名称做下对比
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        mTextSize = ta.getDimension(R.styleable.HorizontalProgressBarView_progress_text_size,
                mTextSize);
        mTextColor =  ta.getColor(R.styleable.HorizontalProgressBarView_progress_text_color,
                mTextColor) ;
        mUnreachColor = ta.getColor(R.styleable.HorizontalProgressBarView_progress_unreach_color,
                mUnreachColor);
        mUnreachHeight = (int) ta.getDimension(R.styleable.HorizontalProgressBarView_progress_unreach_height,
                mUnreachHeight);
        mReachColor =  ta.getColor(R.styleable.HorizontalProgressBarView_progress_reach_color,
                mReachColor);
        mReachHeight = (int) ta.getDimension(R.styleable.HorizontalProgressBarView_progress_reach_height,
                mReachHeight);
        mTextOffset = (int) ta.getDimension(R.styleable.HorizontalProgressBarView_progress_text_offset,
                mTextOffset);

        ta.recycle();

        //设置字体大小 ,用于后面计算控件的高度
        mPaint.setTextSize(mTextSize);
    }

    /**
     *
     * @param dpVal
     * @return
     */
    private int dp2px(int dpVal){
       return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
               dpVal,getResources().getDisplayMetrics());
    }


    /**
     *
     * @param spVal
     * @return
     */
    private int sp2px(int spVal){
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spVal,getResources().getDisplayMetrics());
    }

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

        //获取宽度的模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);


        //获取宽度的值,通过宽度的模式来获取 宽度的值
        int widthVal = MeasureSpec.getSize(widthMeasureSpec);
        //获取控件高度的值
        int height = getHeightMeasure(heightMeasureSpec);

        //设置控件的尺寸
        setMeasuredDimension(widthVal,height);

        //设置控件的实际宽度
        mRealWidth = getMeasuredWidth()-getPaddingLeft()-getPaddingRight();

    }

    /**
     *
     * @param heightMeasureSpec
     * @return
     */
    private int getHeightMeasure(int heightMeasureSpec) {

        int result = 0 ;

        //获得测量模式
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        //获取测量结果--高度
        int size = MeasureSpec.getSize(heightMeasureSpec);
        //用户的提供的是精确的数值模式
        if(mode==MeasureSpec.EXACTLY){

            result = size ;
        }else{
            //下部分的之减去上部分的值
            int textHeight = (int) (mPaint.descent() - mPaint.ascent());
            //
            result = getPaddingTop()+getPaddingBottom()+
                    Math.max(Math.abs(textHeight),Math.max(mReachHeight,mUnreachHeight));

            if(mode==MeasureSpec.AT_MOST){
                result = Math.min(result,size);
            }
        }
        return result ;
    }


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

        //绘制其实坐标
        canvas.translate(getPaddingLeft(),getHeight()/2);

        // 代表是否需要绘制onReachbar
        boolean isNeedUnReach = false ;
        float radio =  getProgress()*1.0f/getMax() ;
        //测量文本宽度
        String text = getProgress()+"%" ;
        int  textWidth = (int) mPaint.measureText(text);

        //
        float progressX = radio*mRealWidth ;
        //保证数字被显示
        if(progressX+textWidth>mRealWidth){

            progressX = mRealWidth - textWidth ;
            isNeedUnReach = true ;
        }

        //绘制进度条的进度长度

        float endX = progressX - mTextOffset/2 ;

        if(endX>0){
            mPaint.setColor(mReachColor);
            mPaint.setStrokeWidth(mReachHeight);

            canvas.drawLine(0,0,endX, 0, mPaint);
        }

        //绘制文本
        mPaint.setColor(mTextColor);
        mPaint.setAntiAlias(true);
        int y = (int) (-(mPaint.descent()+mPaint.ascent())/2);
        canvas.drawText(text,progressX,y,mPaint);

        //绘制unReachbar
        if (!isNeedUnReach){
            float  start = progressX + mTextOffset/2 + textWidth ;
            mPaint.setColor(mUnreachColor);
            mPaint.setStrokeWidth(mUnreachHeight);
            canvas.drawLine(start,0,mRealWidth,0,mPaint);
        }
        canvas.restore();

    }
}

4.3 在布局文件中引用自定义的进度条

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:padding="20dp">

    <com.example.hyf.appforprogress.views.HorizontalProgressBarView
        android:id="@+id/id_pro_01"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:progress="43"
        android:max="100"
        app:progress_unreach_height="2dp"
        app:progress_text_size="13sp"
        app:progress_reach_color="#ff009900"
        app:progress_unreach_color="#66009900"
        app:progress_text_color="#2caf2c"
        />
</LinearLayout>

这里写图片描述

5 测量模式

        /**
         * Measure specification mode: The parent has not imposed any constraint
         * on the child. It can be whatever size it wants.
         */
        public static final int UNSPECIFIED = 0 << MODE_SHIFT;

        /**
         * Measure specification mode: The parent has determined an exact size
         * for the child. The child is going to be given those bounds regardless
         * of how big it wants to be.
         */
        public static final int EXACTLY     = 1 << MODE_SHIFT;

        /**
         * Measure specification mode: The child can be as large as it wants up
         * to the specified size.
         */
        public static final int AT_MOST     = 2 << MODE_SHIFT;
MeasureSpec.UNSPECIFIED :
是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。

MeasureSpec.EXACTLY:
精确的测量模式

MeasureSpec.AT_MOST:
是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。

6 还有圆形可以设置

参考我的第二篇文章:
自定义环形进度显示之
《(Android Studio)自定义 ProgressBar(二)》

发布了53 篇原创文章 · 获赞 51 · 访问量 14万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览