Android自定義View實(shí)現(xiàn)水平帶數(shù)字百分比進(jìn)度條
這個(gè)進(jìn)度條可以反映真實(shí)進(jìn)度,并且完成百分比的文字時(shí)隨著進(jìn)度增加而移動(dòng)的,所在位置也恰好是真實(shí)完成的百分比位置,效果如下:

思路如下:第一部分是左側(cè)的藍(lán)色直線,代表已經(jīng)完成的進(jìn)度;第二部分是右側(cè)灰色的直線,代表未完成的進(jìn)度;第三部分是紅色的百分比的數(shù)字百分比文本,顯示當(dāng)前確切的完成進(jìn)度。
最關(guān)鍵的部分就是要確定百分比文本的確切位置,這里用了paint的getTextBounds方法,得到文本的寬高,然后再精確確定它的位置。
view代碼如下:
public class NumberProgressView extends View {
/**
* 進(jìn)度條畫筆的寬度(dp)
*/
private int paintProgressWidth = 3;
/**
* 文字百分比的字體大?。╯p)
*/
private int paintTextSize = 20;
/**
* 左側(cè)已完成進(jìn)度條的顏色
*/
private int paintLeftColor = 0xff67aae4;
/**
* 右側(cè)未完成進(jìn)度條的顏色
*/
private int paintRightColor = 0xffaaaaaa;
/**
* 百分比文字的顏色
*/
private int paintTextColor = 0xffff0077;
/**
* Contxt
*/
private Context context;
/**
* 主線程傳過來進(jìn)程 0 - 100
*/
private int progress;
/**
* 得到自定義視圖的寬度
*/
private int viewWidth;
/**
* 得到自定義視圖的Y軸中心點(diǎn)
*/
private int viewCenterY;
/**
* 畫左邊已完成進(jìn)度條的畫筆
*/
private Paint paintleft = new Paint();
/**
* 畫右邊未完成進(jìn)度條的畫筆
*/
private Paint paintRight = new Paint();
/**
* 畫中間的百分比文字的畫筆
*/
private Paint paintText = new Paint();
/**
* 要畫的文字的寬度
*/
private int textWidth;
/**
* 畫文字時(shí)底部的坐標(biāo)
*/
private float textBottomY;
/**
* 包裹文字的矩形
*/
private Rect rect = new Rect();
/**
* 文字總共移動(dòng)的長度(即從0%到100%文字左側(cè)移動(dòng)的長度)
*/
private int totalMovedLength;
public NumberProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
// 構(gòu)造器中初始化數(shù)據(jù)
initData();
}
/**
* 初始化數(shù)據(jù)
*/
private void initData() {
//設(shè)置進(jìn)度條畫筆的寬度
int paintProgressWidthPx = Utils.dip2px(context, paintProgressWidth);
//設(shè)置百分比文字的尺寸
int paintTextSizePx = Utils.sp2px(context, paintTextSize);
// 已完成進(jìn)度條畫筆的屬性
paintleft.setColor(paintLeftColor);
paintleft.setStrokeWidth(paintProgressWidthPx);
paintleft.setAntiAlias(true);
paintleft.setStyle(Style.FILL);
// 未完成進(jìn)度條畫筆的屬性
paintRight.setColor(paintRightColor);
paintRight.setStrokeWidth(paintProgressWidthPx);
paintRight.setAntiAlias(true);
paintRight.setStyle(Style.FILL);
// 百分比文字畫筆的屬性
paintText.setColor(paintTextColor);
paintText.setTextSize(paintTextSizePx);
paintText.setAntiAlias(true);
paintText.setTypeface(Typeface.DEFAULT_BOLD);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
getWidthAndHeight();
}
/**
* 得到視圖等的高度寬度尺寸數(shù)據(jù)
*/
private void getWidthAndHeight() {
//得到包圍文字的矩形的寬高
paintText.getTextBounds("000%", 0, "000%".length(), rect);
textWidth = rect.width();
textBottomY = viewCenterY + rect.height() / 2;
//得到自定義視圖的高度
int viewHeight = getMeasuredHeight();
viewWidth = getMeasuredWidth();
viewCenterY = viewHeight / 2;
totalMovedLength = viewWidth - textWidth;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//得到float型進(jìn)度
float progressFloat = progress / 100.0f;
//當(dāng)前文字移動(dòng)的長度
float currentMovedLentgh = totalMovedLength * progressFloat;
//畫左側(cè)已經(jīng)完成的進(jìn)度條,長度為從Veiw左端到文字的左側(cè)
canvas.drawLine(0, viewCenterY, currentMovedLentgh, viewCenterY, paintleft);
//畫右側(cè)未完成的進(jìn)度條,這個(gè)進(jìn)度條的長度不是嚴(yán)格按照百分比來縮放的,因?yàn)槲淖值拈L度會(huì)變化,所以它的長度縮放比例也會(huì)變化
if (progress < 10) {
canvas.drawLine(currentMovedLentgh + textWidth * 0.5f, viewCenterY, viewWidth, viewCenterY, paintRight);
} else if (progress < 100) {
canvas.drawLine(currentMovedLentgh + textWidth * 0.75f, viewCenterY, viewWidth, viewCenterY, paintRight);
} else {
canvas.drawLine(currentMovedLentgh + textWidth, viewCenterY, viewWidth, viewCenterY, paintRight);
}
//畫文字(注意:文字要最后畫,因?yàn)槲淖趾瓦M(jìn)度條可能會(huì)有重合部分,所以要最后畫文字,用文字蓋住重合的部分)
canvas.drawText(progress + "%", currentMovedLentgh, textBottomY, paintText);
}
/**
* @param progress 外部傳進(jìn)來的當(dāng)前進(jìn)度
*/
public void setProgress(int progress) {
this.progress = progress;
invalidate();
}
}
調(diào)用者activity的代碼,設(shè)置進(jìn)度條的進(jìn)度:
public class NumberProgressBarActivity extends Activity {
protected static final int WHAT_INCREASE = 1;
private NumberProgressView np_numberProgressBar;
private int progress;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
progress++;
np_numberProgressBar.setProgress(progress);
handler.sendEmptyMessageDelayed(WHAT_INCREASE, getRadomNumber(50, 200));
if (progress >= 100) {
handler.removeMessages(WHAT_INCREASE);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_number_progress_bar);
np_numberProgressBar = (NumberProgressView) findViewById(R.id.np_numberProgressBar);
Button btn_numberProgressBar = (Button) findViewById(R.id.btn_numberProgressBar);
btn_numberProgressBar.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
increase();
}
});
}
private void increase() {
progress = 0;
np_numberProgressBar.setProgress(0);
handler.removeMessages(WHAT_INCREASE);
handler.sendEmptyMessage(WHAT_INCREASE);
}
/**
* 得到兩個(gè)整數(shù)之間的一個(gè)隨機(jī)數(shù)
*
* @param start 較小的數(shù)
* @param end 較大的數(shù)
* @return
*/
public int getRadomNumber(int start, int end) {
return (int) (start + Math.random() * (end - start));
}
}
工具方法:
/**
* 將dip或dp值轉(zhuǎn)換為px值,保證尺寸大小不變
*/
public static int dip2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
/**
* 將sp值轉(zhuǎn)換為px值,保證文字大小不變
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.viewdemo.view.NumberProgressView
android:id="@+id/np_numberProgressBar"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_margin="20dp"
android:background="#33890075"
/>
<Button
android:id="@+id/btn_numberProgressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="開始"/>
</LinearLayout>
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android 自定義View實(shí)現(xiàn)多節(jié)點(diǎn)進(jìn)度條功能
- Android自定義View實(shí)現(xiàn)音頻播放圓形進(jìn)度條
- Android自定義View實(shí)現(xiàn)漸變色進(jìn)度條
- Android自定義View實(shí)現(xiàn)加載進(jìn)度條效果
- Android自定義帶進(jìn)度條WebView仿微信加載過程
- Android view自定義實(shí)現(xiàn)動(dòng)態(tài)進(jìn)度條
- Android 自定義view和屬性動(dòng)畫實(shí)現(xiàn)充電進(jìn)度條效果
- android 自定義view實(shí)現(xiàn)彩虹進(jìn)度條功能
相關(guān)文章
Kotlin基礎(chǔ)學(xué)習(xí)之lambda中return語句詳解
這篇文章主要給大家介紹了關(guān)于Kotlin基礎(chǔ)學(xué)習(xí)之lambda中return語句的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或使用Kotlin具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
android教你打造獨(dú)一無二的上拉下拉刷新加載框架
本篇文章主要介紹了android教你打造獨(dú)一無二的下拉刷新加載框架,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-03-03
Android DynamicGrid實(shí)現(xiàn)拖曳交換位置功能
這篇文章主要為大家詳細(xì)介紹了Android DynamicGrid實(shí)現(xiàn)拖曳交換位置功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
Android打賞功能實(shí)現(xiàn)代碼(支付寶轉(zhuǎn)賬)
這篇文章主要介紹了Android打賞功能之支付寶轉(zhuǎn)賬 ,需要的朋友可以參考下2017-12-12
Android利用懸浮按鈕實(shí)現(xiàn)翻頁效果
這篇文章主要介紹了Android利用懸浮按鈕實(shí)現(xiàn)翻頁效果的相關(guān)資料,需要的朋友可以參考下2015-12-12
Android點(diǎn)擊事件的實(shí)現(xiàn)方式
這篇文章主要為大家詳細(xì)介紹了Android點(diǎn)擊事件的實(shí)現(xiàn)方式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
Android中CountDownTimer 實(shí)現(xiàn)倒計(jì)時(shí)功能
本篇文章主要介紹了Android中CountDownTimer 實(shí)現(xiàn)倒計(jì)時(shí)功能,CountDownTimer 是android 自帶的一個(gè)倒計(jì)時(shí)類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
Android切換前后臺(tái)點(diǎn)擊通知進(jìn)入當(dāng)前頁面
這篇文章主要介紹了Android切換前后臺(tái)點(diǎn)擊通知進(jìn)入當(dāng)前頁面,主要講述當(dāng)App退出到后臺(tái)的后,怎么點(diǎn)擊通知回到原來按下HOME鍵之前的前臺(tái)頁面,需要的朋友可以參考下2023-03-03

