zoukankan      html  css  js  c++  java
  • Android自定义圆角矩形进度条2

    效果图:

      或 

    方法讲解:

    (1)invalidate()方法

    invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时, 调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。一般在自定义控件中会用到这个方法。

    (2)RectF方法的应用

    RectF是用来绘画矩形的方法。 

    RectF(left,top,right,bottom),四个参数的含义分别是父控件距离矩形左上右下边距的距离,以下用图来说明:

    drawRoundRect方法是用来绘制圆角矩形的,它的参数如下: 
    参数说明 

    rect:RectF对象。 
    rx:x方向上的圆角半径。 
    ry:y方向上的圆角半径。 
    paint:绘制时所使用的画笔。

    (3)onMeasure方法

    指定自定义控件在屏幕上的大小,onMeasure方法的两个参数是由上一层控件 传入的大小,而且是模式和尺寸混合在一起的数值,需要MeasureSpec.getMode(widthMeasureSpec) 得到模式,MeasureSpec.getSize(widthMeasureSpec)得到尺寸。

    onMeasure的几种模式分别为EXACTLY,AT_MOST,UNSPECIFIED。

    [1]MeasureSpec.EXACTLY

    MeasureSpec.EXACTLY是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width=”50dip”,或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。

    [2]MeasureSpec.AT_MOST

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

    [3]MeasureSpec.UNSPECIFIED

    MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。

    实现步骤:

    a、在values文件夹下新建attrs.xml,内容如下:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
    <declare-styleable name="CircleProgressBar">
    <attr name="croundColor" format="color"/>
    <attr name="croundProgressColor" format="color"/>
    <attr name="cfillColor" format="color"/>
    <attr name="croundWidth" format="dimension"></attr>
    <attr name="croundProgressWidth" format="dimension"></attr> 
    <attr name="ctextColor" format="color" /> 
    <attr name="ctextSize" format="dimension" /> 
    <attr name="cnumberSize" format="dimension" /> 
    <attr name="cparaLable" format="string" />
    <attr name="cunitLable" format="string" /> 
    </declare-styleable>
    
    <declare-styleable name="RoundRectProgressBar">
    <attr name="cbarRoundColor" format="color"/>
    <attr name="cbarProgressColor" format="color"/>
    <attr name="cbarFillColor" format="color"/>
    <attr name="cbarOrientation">
      <enum name="HORIZONTAL" value="0"></enum>
      <enum name="VERTICAL" value="1"></enum>
    </attr>
    </declare-styleable>
    
    </resources>
    

      


    b、新建RoundRectProgressBar类继承View

    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.util.AttributeSet;
    import android.view.View;
    
    /**
    * 自定义圆角矩形进度条view
    *
    * @author xl
    */
    public class RoundRectProgressBar extends View {
    
    private final static String TAG = RoundRectProgressBar.class.getSimpleName();
    
    /**
    * 画笔对象的引用
    */
    private Paint paint;
    
    /**
    * 圆角环的颜色
    */
    private int roundColor;
    
    /**
    * 进度的颜色
    */
    private int fillProgressColor;
    
    /**
    * 填充的颜色
    */
    private int fillColor;
    
    /**
    * 圆角矩形宽度
    */
    private int roundWidth;
    
    /**
    * 圆角矩形高度
    */
    private int roundHeight;
    
    /**
    * 进度条方向,0水平,1垂直
    */
    private int barOrientation;
    
    /**
    * 进度条最大值
    */
    private float max = 100;
    
    /**
    * 进度条当前值
    */
    private float progress = 30;
    
    public RoundRectProgressBar(Context context) {
    this(context, null);
    }
    
    public RoundRectProgressBar(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
    }
    
    public RoundRectProgressBar(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    //获取画笔
    paint = new Paint();
    TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundRectProgressBar);
    //获取自定义属性和默认值
    roundColor = mTypedArray.getColor(R.styleable.RoundRectProgressBar_cbarRoundColor, Color.RED);
    fillProgressColor = mTypedArray.getColor(R.styleable.RoundRectProgressBar_cbarProgressColor, Color.GREEN);
    fillColor = mTypedArray.getColor(R.styleable.RoundRectProgressBar_cbarFillColor, Color.BLUE);
    barOrientation = mTypedArray.getInt(R.styleable.RoundRectProgressBar_cbarOrientation, 0);
    //回收TypedArray资源
    mTypedArray.recycle();
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //设置抗锯齿效果
    paint.setAntiAlias(true);
    //设置画笔颜色
    paint.setColor(roundColor);
    //进度方向
    if (barOrientation == 0) {
    //水平,向右
    try {
    int round = roundHeight / 2;
    //RectF:绘制矩形,四个参数分别是left,top,right,bottom,类型是单精度浮点数
    RectF rf = new RectF(0, 0, roundWidth, roundHeight);
    //绘制圆角矩形,背景色为画笔颜色
    canvas.drawRoundRect(rf, round, round, paint);
    //设置progress内部是灰色
    paint.setColor(fillColor);
    RectF rectBlackBg = new RectF(2, 2, roundWidth - 2, roundHeight - 2);
    canvas.drawRoundRect(rectBlackBg, round, round, paint);
    //设置进度条进度及颜色
    float section = progress / max;
    RectF rectProgressBg = new RectF(2, 2, (roundWidth - 2) * section, roundHeight - 2);
    if (section != 0.0f) {
    paint.setColor(fillProgressColor);
    } else {
    paint.setColor(Color.TRANSPARENT);
    }
    canvas.drawRoundRect(rectProgressBg, round, round, paint);
    } catch (Exception e) {
    e.printStackTrace();
    }
    } else {
    //垂直,向上
    try {
    int round = roundWidth / 2;
    //RectF:绘制矩形,四个参数分别是left,top,right,bottom,类型是单精度浮点数
    RectF rf = new RectF(0, 0, roundWidth, roundHeight);
    //绘制圆角矩形,背景色为画笔颜色
    canvas.drawRoundRect(rf, round, round, paint);
    //设置progress内部是灰色
    paint.setColor(fillColor);
    RectF rectBlackBg = new RectF(2, 2, roundWidth - 2, roundHeight - 2);
    canvas.drawRoundRect(rectBlackBg, round, round, paint);
    //设置进度条进度及颜色
    float section = progress / max;
    RectF rectProgressBg = new RectF(2, roundHeight - 2 - (roundHeight - 4) * section, roundWidth - 2, roundHeight - 2);
    if (section != 0.0f) {
    paint.setColor(fillProgressColor);
    } else {
    paint.setColor(Color.TRANSPARENT);
    }
    canvas.drawRoundRect(rectProgressBg, round, round, paint);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    
    /**
    * dip转px
    *
    * @param dip
    * @return
    */
    private int dipToPx(int dip) {
    float scale = getContext().getResources().getDisplayMetrics().density;
    //加0.5是为了四舍五入
    return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1));
    }
    
    /**
    * 指定自定义控件在屏幕上的大小,onMeasure方法的两个参数是由上一层控件
    * 传入的大小,而且是模式和尺寸混合在一起的数值,需要MeasureSpec.getMode(widthMeasureSpec)
    * 得到模式,MeasureSpec.getSize(widthMeasureSpec)得到尺寸
    */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
    int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
    //MeasureSpec.EXACTLY,精确尺寸
    if (widthSpecMode == MeasureSpec.EXACTLY || widthSpecMode == MeasureSpec.AT_MOST) {
    roundWidth = widthSpecSize;
    } else {
    roundWidth = 0;
    }
    if (heightSpecMode == MeasureSpec.EXACTLY || heightSpecMode == MeasureSpec.AT_MOST) {
    roundHeight = heightSpecSize;
    } else {
    roundHeight = 0;
    }
    //MeasureSpec.AT_MOST,最大尺寸,只要不超过父控件允许的最大尺寸即可,MeasureSpec.UNSPECIFIED未指定尺寸
    //if (heightSpecMode == MeasureSpec.AT_MOST || heightSpecMode == MeasureSpec.UNSPECIFIED) {
    // roundHeight = dipToPx(20);
    //} else {
    // roundHeight = heightSpecSize;
    //}
    //设置控件实际大小
    setMeasuredDimension(roundWidth, roundHeight);
    }
    
    
    /**
    * 设置进度
    *
    * @param progress
    */
    public synchronized void setProgress(float progress) {
    if (progress < 0) {
    throw new IllegalArgumentException("value can not be negative");
    }
    if (progress > max) {
    this.progress = max;
    } else {
    this.progress = progress;
    }
    postInvalidate();
    }
    
    /**
    * 设置最大值
    *
    * @param max
    */
    public synchronized void setMax(float max) {
    if (max < 0) {
    throw new IllegalArgumentException("value can not be negative");
    }
    this.max = max;
    }
    
    }
    

      


    c、布局文件中引用activity_main.xml

    <ups.invt.com.view.RoundRectProgressBar
    android:id="@+id/bar"
    android:layout_width="20dp"
    android:layout_height="100dp"
    android_custom:cbarRoundColor="@color/transparent"
    android_custom:cbarFillColor="@color/white"
    android_custom:cbarProgressColor="@color/bar_fill_color"
    android_custom:cbarOrientation="VERTICAL"
    android:layout_centerInParent="true"/>
    

      


    d、MainActivity.java中设置进度

    progress = (RoundRectProgressBar) findViewById(R.id.bar);
    progress.setMax(100);
    
    progress.setProgress(80);


    完!!!
    ————————————————

    参考于:https://blog.csdn.net/xialong_927/article/details/86596932

  • 相关阅读:
    理解vertical-align
    理解css行高(line-height)
    react 生命周期函数
    react Diff 算法
    React中的虚拟DOM
    无限重启:windows更新之后,在输入密码页面无限重启进入不了系统
    [转]github 上传project代码
    【转】HTTP响应状态码参考簿
    TweenMax—ScrambleText插件 实现类似电脑破译密码的特效
    既然CPU一次只能执行一个线程,那多线程存在的意义是什么?
  • 原文地址:https://www.cnblogs.com/changyiqiang/p/11399187.html
Copyright © 2011-2022 走看看