美文网首页
自定义进度条之进阶篇

自定义进度条之进阶篇

作者: 冬絮 | 来源:发表于2018-05-18 13:03 被阅读57次

    带自定义属性的进度条

    image.png
    前三个进度条基本是系统原生的,详情见我的上一篇文章自定义进度条之样式篇
    今天我们讲一下下边的2个带文字的自定义进度条,如果对paint,canvas,bitmap.onDraw,onMeasure不太了解的同学,可以先看看自定义控件三部曲中的绘图篇
    1. 自定义属性
      在res/values下新建文件attr_progress_bar.xml

       <declare-styleable name="HorizontalProgressBarWithNumber">  // 声名属性集的名称,即这些属性是属于哪个控件的。
           <attr name="progress_unreached_color" format="color" /> //进度未达到颜色
           <attr name="progress_reached_color" format="color" />   //进度已经达到的颜色
           <attr name="progress_reached_bar_height" format="dimension" />  //进度条已经达到的高
           <attr name="progress_unreached_bar_height" format="dimension" />//进度条未达到的高
           <attr name="progress_text_size" format="dimension" />   //进度条文字的大小(SP)
           <attr name="progress_text_color" format="color" />      //进度条文字的颜色
           <attr name="progress_text_offset" format="dimension" /> //进度条文字的偏移量
           <attr name="progress_text_visibility" format="enum">    //进度条文字是否可见
               <enum name="visible" value="0" />                   //枚举值可见
               <enum name="invisible" value="1" />                 //枚举值不可见
           </attr>
       </declare-styleable>
      

    .简单说一下上边所使用的 <attr name="progress_unreached_color" format="color" />

    • 其中name是我们给这个自定义属性所起的名称,
    • format是自定义属性的类型,
      Android一共给我们提供了八种自定义属性的类型,分别是:
    Num format 类型
    1 reference 引用
    2 color 颜色
    3 boolean 布尔值
    4 dimension 尺寸值
    5 float 浮点值
    6 integer 整型值
    7 string 字符串
    8 enum 枚举值

    2.创建自定义进度条的HorizontalProgressBarWithNumber类继承与ProgressBar

      package com.xvdong.custom.view;
        
        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.xvdong.custom.R;
        
        /**
         * Created by xvDong on 2018/5/16.
         */
        
        public class HorizontalProgressBarWithNumber extends ProgressBar {
            private static final int DEFAULT_TEXT_SIZE = 10;
            private static final int DEFAULT_TEXT_COLOR = 0XFFFC00D1;
            private static final int DEFAULT_COLOR_UNREACHED_COLOR = 0xFFd3d6da;
            private static final int DEFAULT_HEIGHT_REACHED_PROGRESS_BAR = 2;
            private static final int DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR = 2;
            private static final int DEFAULT_SIZE_TEXT_OFFSET = 10;
        
            /**
             * painter of all drawing things
             */
            protected Paint mPaint = new Paint();
            /**
             * color of progress number
             */
            protected int mTextColor = DEFAULT_TEXT_COLOR;
            /**
             * size of text (sp)
             */
            protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
        
            /**
             * offset of draw progress
             */
            protected int mTextOffset = dp2px(DEFAULT_SIZE_TEXT_OFFSET);
        
            /**
             * height of reached progress bar
             */
            protected int mReachedProgressBarHeight = dp2px(DEFAULT_HEIGHT_REACHED_PROGRESS_BAR);
        
            /**
             * color of reached bar
             */
            protected int mReachedBarColor = DEFAULT_TEXT_COLOR;
            /**
             * color of unreached bar
             */
            protected int mUnReachedBarColor = DEFAULT_COLOR_UNREACHED_COLOR;
            /**
             * height of unreached progress bar
             */
            protected int mUnReachedProgressBarHeight = dp2px(DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR);
            /**
             * view width except padding
             */
            protected int mRealWidth;
        
            protected boolean mIfDrawText = true;
        
            protected static final int VISIBLE = 0;
        
            public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs) {
                this(context, attrs, 0);
            }
        
            public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs,
                                                   int defStyle) {
                super(context, attrs, defStyle);
        
                setHorizontalScrollBarEnabled(true);
        
                obtainStyledAttributes(attrs);
        
                mPaint.setTextSize(mTextSize);
                mPaint.setColor(mTextColor);
        
            }
        
            /**
             * get the styled attributes
             *
             * @param attrs
             */
            private void obtainStyledAttributes(AttributeSet attrs) {
                // init values from custom attributes
                final TypedArray attributes = getContext().obtainStyledAttributes(
                        attrs, R.styleable.HorizontalProgressBarWithNumber);
        
                mTextColor = attributes
                        .getColor(
                                R.styleable.HorizontalProgressBarWithNumber_progress_text_color,
                                DEFAULT_TEXT_COLOR);
                mTextSize = (int) attributes.getDimension(
                        R.styleable.HorizontalProgressBarWithNumber_progress_text_size,
                        mTextSize);
        
                mReachedBarColor = attributes
                        .getColor(
                                R.styleable.HorizontalProgressBarWithNumber_progress_reached_color,
                                mTextColor);
                mUnReachedBarColor = attributes
                        .getColor(
                                R.styleable.HorizontalProgressBarWithNumber_progress_unreached_color,
                                DEFAULT_COLOR_UNREACHED_COLOR);
                mReachedProgressBarHeight = (int) attributes
                        .getDimension(
                                R.styleable.HorizontalProgressBarWithNumber_progress_reached_bar_height,
                                mReachedProgressBarHeight);
                mUnReachedProgressBarHeight = (int) attributes
                        .getDimension(
                                R.styleable.HorizontalProgressBarWithNumber_progress_unreached_bar_height,
                                mUnReachedProgressBarHeight);
                mTextOffset = (int) attributes
                        .getDimension(
                                R.styleable.HorizontalProgressBarWithNumber_progress_text_offset,
                                mTextOffset);
        
                int textVisible = attributes
                        .getInt(R.styleable.HorizontalProgressBarWithNumber_progress_text_visibility,
                                VISIBLE);
                if (textVisible != VISIBLE) {
                    mIfDrawText = false;
                }
                attributes.recycle();
            }
        
        
            @Override
            protected synchronized void onMeasure(int widthMeasureSpec,
                                                  int heightMeasureSpec) {
                int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        
                if (heightMode != MeasureSpec.EXACTLY) {
        
                    float textHeight = (mPaint.descent() + mPaint.ascent());
                    int exceptHeight = (int) (getPaddingTop() + getPaddingBottom() + Math
                            .max(Math.max(mReachedProgressBarHeight,
                                    mUnReachedProgressBarHeight), Math.abs(textHeight)));
        
                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(exceptHeight,
                            MeasureSpec.EXACTLY);
                }
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        
            }
        
            @Override
            protected synchronized void onDraw(Canvas canvas) {
                canvas.save();
                //画笔平移到指定paddingLeft, getHeight() / 2位置,注意以后坐标都为以此为0,0
                canvas.translate(getPaddingLeft(), getHeight() / 2);
        
                boolean noNeedBg = false;
                //当前进度和总值的比例
                float radio = getProgress() * 1.0f / getMax();
                //已到达的宽度
                float progressPosX = (int) (mRealWidth * radio);
                //绘制的文本
                String text = getProgress() + "%";
        
                //拿到字体的宽度和高度3265
                float textWidth = mPaint.measureText(text);
                float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;
        
                //如果到达最后,则未到达的进度条不需要绘制
                if (progressPosX + textWidth > mRealWidth) {
                    progressPosX = mRealWidth - textWidth;
                    noNeedBg = true;
                }
        
                // 绘制已到达的进度
                float endX = progressPosX - mTextOffset / 2;
                if (endX > 0) {
                    mPaint.setColor(mReachedBarColor);
                    mPaint.setStrokeWidth(mReachedProgressBarHeight);
                    canvas.drawLine(0, 0, endX, 0, mPaint);
                }
        
                // 绘制文本
                if (mIfDrawText) {
                    mPaint.setColor(mTextColor);
                    canvas.drawText(text, progressPosX, -textHeight, mPaint);
                }
        
                // 绘制未到达的进度条
                if (!noNeedBg) {
                    float start = progressPosX + mTextOffset / 2 + textWidth;
                    mPaint.setColor(mUnReachedBarColor);
                    mPaint.setStrokeWidth(mUnReachedProgressBarHeight);
                    canvas.drawLine(start, 0, mRealWidth, 0, mPaint);
                }
        
                canvas.restore();
        
            }
        
            @Override
            protected void onSizeChanged(int w, int h, int oldw, int oldh) {
                super.onSizeChanged(w, h, oldw, oldh);
                mRealWidth = w - getPaddingRight() - getPaddingLeft();
        
            }
        
            /**
             * dp 2 px
             *
             * @param dpVal
             */
            protected int dp2px(int dpVal) {
                return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        dpVal, getResources().getDisplayMetrics());
            }
        
            /**
             * sp 2 px
             *
             * @param spVal
             * @return
             */
            protected int sp2px(int spVal) {
                return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                        spVal, getResources().getDisplayMetrics());
        
            }
        }
    
    1. 自定义属性在layout.xml文件中的使用
      3.1 在使用之前必须声名命名空间:
      xmlns:app="http://schemas.android.com/apk/res-auto"
      这一步一般AndroidStudio会自动帮我们声明完成.

      声明命名空间.png
      3.2 自定义属性在自定义控件上的使用:
       <com.xvdong.custom.view.HorizontalProgressBarWithNumber
           app:progress_reached_bar_height="20dp"
           app:progress_unreached_bar_height="30dp"
           app:progress_text_color="@color/colorPrimaryDark"
           app:progress_text_size="20dp"
           app:progress_reached_color="@color/colorPrimaryDark"
           app:progress_text_offset="10dp"
           app:progress_text_visibility="visible"
           app:progress_unreached_color="@color/colorAccent"
           android:padding="10dp"
           android:id="@+id/id_progressbar01"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_marginEnd="10dp"
           android:layout_marginStart="10dp"
           android:layout_marginTop="10dp"/>
      
    2. 自定义进度条的使用

           private Handler mHandler = new Handler() {
               public void handleMessage(android.os.Message msg) {
                   int progress = mProgressBar.getProgress();
                   mProgressBar.setProgress(++progress);
                   if (progress >= 100) {
                       mHandler.removeMessages(MSG_PROGRESS_UPDATE);
                   }
                   mHandler.sendEmptyMessageDelayed(MSG_PROGRESS_UPDATE, 100);
               };
           };
           @Override
           protected void onCreate(Bundle savedInstanceState) {
               super.onCreate(savedInstanceState);
               setContentView(R.layout.activity_main);
               mProgressBar =  findViewById(R.id.id_progressbar01);
               mHandler.sendEmptyMessage(MSG_PROGRESS_UPDATE);
           }
      

    相关文章

      网友评论

          本文标题:自定义进度条之进阶篇

          本文链接:https://www.haomeiwen.com/subject/vaxgdftx.html