Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 自定義進度條控件

自定義進度條控件

編輯:關於Android編程

最近在慕課網,學習了關於進度條的自定義,有直線型和圓形進度條兩種:

需要的文件value目錄下的attrs.xml:




    
    
    
    
    
    
    


    
        
        
        
        
        
        
        
    

    
    
    
    
    
    
    
    
    
    
    

1 直線型進度條:

public class MyProgressBar 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


    protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
    protected int mTextColor = DEFAULT_TEXT_COLOR;
    protected int mUnReachColor = DEFAULT_COLOR_UNREACH;
    protected int mUnReachHeight = dp2px(DEFAULT_HEIGHT_UNREACH);
    protected int mReachHeight = dp2px(DEFAULT_HEIGHT_REACH);
    protected int mReachColor = DEFAULT_COLOR_REACH;
    protected int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);


    //
    protected Paint mPaint = new Paint();

    protected int mRealWidth;//控件的寬度

    public MyProgressBar(Context context) {
        this(context,null);
        // TODO Auto-generated constructor stub
    }

    public MyProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs,0);
        // TODO Auto-generated constructor stub
    }

    public MyProgressBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub

          obtainStyleAttrs(attrs);
    }

    /**
     * 獲取自定義屬性
     * @param attrs
     */
    private void obtainStyleAttrs(AttributeSet attrs) {
        // TODO Auto-generated method stub

        TypedArray typedArray = getContext()
                .obtainStyledAttributes(attrs, R.styleable.MyProgressBar);

        //獲取各個屬性
        mTextSize = (int) typedArray.getDimension(R.styleable.MyProgressBar_propgress_text_size, 
                mTextSize);

        mTextColor = (int)typedArray.getColor(R.styleable.MyProgressBar_propgress_text_color,
                mTextColor);

        mUnReachColor = (int)typedArray.getColor(R.styleable.MyProgressBar_propgress_unreach_color,
                mUnReachColor);

        mUnReachHeight = (int)typedArray.getDimension(R.styleable.MyProgressBar_propgress_unreach_height,
                mUnReachHeight);

        mReachColor = (int)typedArray.getColor(R.styleable.MyProgressBar_propgress_reach_color,
                mReachColor);
        mReachHeight  = (int)typedArray.getDimension(R.styleable.MyProgressBar_propgress_reach_height,
                mReachHeight);

        mTextOffset = (int)typedArray.getDimension(R.styleable.MyProgressBar_propgress_text_offset,
                mTextOffset);


        typedArray.recycle();

        //設置mpaint要測量的值
        //如果忘記的話,字體就設置不了了
        mPaint.setTextSize(mTextSize);
    }

    /**
     * 測量
     */
    @Override
    protected synchronized void onMeasure(int widthMeasureSpec,
            int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //寬度測量,有點特殊,由於這裡的寬度不確定,所以
        //int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int withValue = MeasureSpec.getSize(widthMeasureSpec);

        int height = measureHeight(heightMeasureSpec);

        //這裡設定寬度和高度
        setMeasuredDimension(withValue, height);

        //繪制的實際的寬度
        mRealWidth = getMeasuredWidth()-getPaddingLeft()-getPaddingRight();

    }

    @Override
    protected synchronized void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);

        canvas.save();
        canvas.translate(getPaddingLeft(), getHeight()/2);

        boolean noNeedUnReach = false;


//      繪制ReachBar
        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);//繪制一條線
        }

        //繪制文本Text

        mPaint.setColor(mTextColor);
        int y = (int) (-(mPaint.descent()+mPaint.ascent())/2);//設置文本顯示居中
        canvas.drawText(text, progressX, y, mPaint);

        //繪制UnReachBar
        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 measureHeight(int heightMeasureSpec) {
        // TODO Auto-generated method stub
        int result =0;

        int Mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);

        //如果mode為一精確值
        if(Mode==MeasureSpec.EXACTLY){

            result = size;
        }else{
            //獲取組件中最大高度
            int textHeight = (int) (mPaint.descent()-mPaint.ascent());

            result = getPaddingTop()
                    +getPaddingBottom()
                    +Math.max(Math.max(mUnReachHeight, mReachHeight), Math.abs(textHeight));
            //不能超過最大值
            if(Mode==MeasureSpec.AT_MOST){

                result = Math.min(size,result);
            }

        }
        return result;
    }

    //dp轉化
    protected int dp2px(int dpValue){
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, dpValue, getResources().getDisplayMetrics());
    }


    //sp轉化
    protected int sp2px(int spValue){
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spValue, getResources().getDisplayMetrics());
    }

}

2 圓形進度條:

public class RoundProgressBar 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

    protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
    protected int mTextColor = DEFAULT_TEXT_COLOR;
    protected int mUnReachColor = DEFAULT_COLOR_UNREACH;
    protected int mUnReachHeight = dp2px(DEFAULT_HEIGHT_UNREACH);
    protected int mReachHeight = dp2px(DEFAULT_HEIGHT_REACH);
    protected int mReachColor = DEFAULT_COLOR_REACH;
    protected int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);

    private Paint mPaint = new Paint();

    private int mRdius = dp2px(30);
    private int mMaxPaintWith;

    // dp轉化
    protected int dp2px(int dpValue) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpValue, getResources().getDisplayMetrics());
    }

    // sp轉化
    protected int sp2px(int spValue) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spValue, getResources().getDisplayMetrics());
    }

    public RoundProgressBar(Context context) {
        this(context, null);
        // TODO Auto-generated constructor stub
    }

    public RoundProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        // TODO Auto-generated constructor stub
    }

    public RoundProgressBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub

        //Reach進度條加粗,為unReach進度條的2.0f倍
        mReachHeight = (int) (mUnReachHeight * 2.0f);

        TypedArray ta = context.obtainStyledAttributes(attrs,
                R.styleable.RoundProgressBar);
        // 獲取各個屬性
        mTextSize = (int) ta.getDimension(
                R.styleable.RoundProgressBar_progress_text_size, mTextSize);

        mTextColor = (int) ta.getColor(
                R.styleable.RoundProgressBar_progress_text_color, mTextColor);

        mUnReachColor = (int) ta.getColor(
                R.styleable.RoundProgressBar_progress_unreach_color,
                mUnReachColor);

        mUnReachHeight = (int) ta.getDimension(
                R.styleable.RoundProgressBar_progress_unreach_height,
                mUnReachHeight);

        mReachColor = (int) ta.getColor(
                R.styleable.RoundProgressBar_progress_reach_color, mReachColor);
        mReachHeight = (int) ta.getDimension(
                R.styleable.RoundProgressBar_progress_reach_height,
                mReachHeight);

        mTextOffset = (int) ta.getDimension(
                R.styleable.RoundProgressBar_progress_text_offset, mTextOffset);
        mRdius = (int) ta.getDimension(R.styleable.RoundProgressBar_radius,
                mRdius);

        mPaint.setStyle(Style.STROKE);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStrokeCap(Cap.ROUND);

        ta.recycle();

        //忘記這個字體就無法設置了
        mPaint.setTextSize(mTextSize);
    }

    /**
     * 測量
     */
    @Override
    protected synchronized void onMeasure(int widthMeasureSpec,
            int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mMaxPaintWith = Math.max(mUnReachHeight, mReachHeight);
        // 默認四個panding一致
        int expected = mRdius * 2 + mMaxPaintWith + getPaddingLeft()
                + getPaddingRight();

        // 圓形進度條提供了測量的方法
        int width = resolveSize(expected, widthMeasureSpec);
        int height = resolveSize(expected, heightMeasureSpec);

        int realWidth = Math.min(width, height);

        mRdius = (realWidth - getPaddingLeft() - getPaddingRight() - mMaxPaintWith) / 2;

        setMeasuredDimension(realWidth, realWidth);

    }

    @Override
    protected synchronized void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);

        String text = getProgress() + "%";
        float textWidth = mPaint.measureText(text);

        float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;

        canvas.save();
        // 坐標
        canvas.translate(getPaddingLeft() + mMaxPaintWith / 2, getPaddingTop()
                + mMaxPaintWith / 2);

        mPaint.setStyle(Style.STROKE);

        // unReachBar
        mPaint.setColor(mUnReachColor);
        mPaint.setStrokeWidth(mUnReachHeight);
        canvas.drawCircle(mRdius, mRdius, mRdius, mPaint);

        // reachBar
        mPaint.setColor(mReachColor);
        mPaint.setStrokeWidth(mReachHeight);
        // 弧度
        float sweepAngle = getProgress() * 1.0f / getMax() * 360;

        // 畫弧
        canvas.drawArc(new RectF(0, 0, mRdius * 2, mRdius * 2), 0, sweepAngle,
                false, mPaint);

        // text
        mPaint.setColor(mTextColor);
        mPaint.setStyle(Style.FILL);
        canvas.drawText(text, mRdius - textWidth / 2, mRdius - textHeight,
                mPaint);

        // 別忘
        canvas.restore();

    }

}

然後我們在MainActivity中實現效果:

public class MainActivity extends Activity {

    private MyProgressBar myProgressBar;
    private RoundProgressBar myRoundProgressBar;

    private static final int MSG_UPDATE = 0X01;

    private Handler handler = new Handler(){

        public void handleMessage(Message msg) {

            //直線進度條
            int progress = myProgressBar.getProgress();
            myProgressBar.setProgress(++progress);

            //圓形進度條
            int roundProgress = myRoundProgressBar.getProgress();
            myRoundProgressBar.setProgress(++roundProgress);

            if(progress>=100 ){
                handler.removeMessages(MSG_UPDATE);
            }

            if(roundProgress>=100){
                handler.removeMessages(MSG_UPDATE);
            }
            handler.sendEmptyMessageDelayed(MSG_UPDATE, 200);

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       myProgressBar = (MyProgressBar)findViewById(R.id.myprogressBar1);

       myRoundProgressBar = (RoundProgressBar) findViewById(R.id.roundProgressBar);

       handler.sendEmptyMessage(MSG_UPDATE);

    }

}

應用:
定義控件成功之後,直接在.xml文件中引入並設置,如在activity_main.xml中



    

        

        
        

         


          


           


    

    


在這裡需要注意的是:必須添加這個指定xmlns,否則用不了
xmlns:hyman="http://schemas.android.com/apk/res/com.example.progressbar"

最後的效果顯示如下:
這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved