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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM