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)度條畫(huà)筆的寬度(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; /** * 主線程傳過(guò)來(lái)進(jìn)程 0 - 100 */ private int progress; /** * 得到自定義視圖的寬度 */ private int viewWidth; /** * 得到自定義視圖的Y軸中心點(diǎn) */ private int viewCenterY; /** * 畫(huà)左邊已完成進(jìn)度條的畫(huà)筆 */ private Paint paintleft = new Paint(); /** * 畫(huà)右邊未完成進(jìn)度條的畫(huà)筆 */ private Paint paintRight = new Paint(); /** * 畫(huà)中間的百分比文字的畫(huà)筆 */ private Paint paintText = new Paint(); /** * 要畫(huà)的文字的寬度 */ private int textWidth; /** * 畫(huà)文字時(shí)底部的坐標(biāo) */ private float textBottomY; /** * 包裹文字的矩形 */ private Rect rect = new Rect(); /** * 文字總共移動(dòng)的長(zhǎng)度(即從0%到100%文字左側(cè)移動(dòng)的長(zhǎ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)度條畫(huà)筆的寬度 int paintProgressWidthPx = Utils.dip2px(context, paintProgressWidth); //設(shè)置百分比文字的尺寸 int paintTextSizePx = Utils.sp2px(context, paintTextSize); // 已完成進(jìn)度條畫(huà)筆的屬性 paintleft.setColor(paintLeftColor); paintleft.setStrokeWidth(paintProgressWidthPx); paintleft.setAntiAlias(true); paintleft.setStyle(Style.FILL); // 未完成進(jìn)度條畫(huà)筆的屬性 paintRight.setColor(paintRightColor); paintRight.setStrokeWidth(paintProgressWidthPx); paintRight.setAntiAlias(true); paintRight.setStyle(Style.FILL); // 百分比文字畫(huà)筆的屬性 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)的長(zhǎng)度 float currentMovedLentgh = totalMovedLength * progressFloat; //畫(huà)左側(cè)已經(jīng)完成的進(jìn)度條,長(zhǎng)度為從Veiw左端到文字的左側(cè) canvas.drawLine(0, viewCenterY, currentMovedLentgh, viewCenterY, paintleft); //畫(huà)右側(cè)未完成的進(jìn)度條,這個(gè)進(jìn)度條的長(zhǎng)度不是嚴(yán)格按照百分比來(lái)縮放的,因?yàn)槲淖值拈L(zhǎng)度會(huì)變化,所以它的長(zhǎng)度縮放比例也會(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); } //畫(huà)文字(注意:文字要最后畫(huà),因?yàn)槲淖趾瓦M(jìn)度條可能會(huì)有重合部分,所以要最后畫(huà)文字,用文字蓋住重合的部分) canvas.drawText(progress + "%", currentMovedLentgh, textBottomY, paintText); } /** * @param progress 外部傳進(jìn)來(lái)的當(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="開(kāi)始"/> </LinearLayout>
以上就是本文的全部?jī)?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仿微信加載過(guò)程
- Android view自定義實(shí)現(xiàn)動(dòng)態(tài)進(jìn)度條
- Android 自定義view和屬性動(dòng)畫(huà)實(shí)現(xiàn)充電進(jìn)度條效果
- android 自定義view實(shí)現(xiàn)彩虹進(jìn)度條功能
相關(guān)文章
深入理解Android熱修復(fù)技術(shù)原理之代碼熱修復(fù)技術(shù)
在各種 Android 熱修復(fù)方案中,Andfix的即時(shí)生效令人印象深刻,它稍顯另類, 并不需要重新啟動(dòng),而是在加載補(bǔ)丁后直接對(duì)方法進(jìn)行替換就可以完成修復(fù),然而它的使用限制也遭遇到更多的質(zhì)疑2021-06-06Android ActionBar完全解析使用官方推薦的最佳導(dǎo)航欄(下)
這篇文章主要介紹了Android ActionBar完全解析使用官方推薦的最佳導(dǎo)航欄(下) ,需要的朋友可以參考下2017-04-04Android編程中號(hào)碼匹配位數(shù)修改的方法
這篇文章主要介紹了Android編程中號(hào)碼匹配位數(shù)修改的方法,涉及Android編程中參數(shù)修改的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11Android自定義控件實(shí)現(xiàn)帶文字提示的SeekBar
這篇文章主要給大家介紹了關(guān)于Android自定義控件實(shí)現(xiàn)帶文字提示的SeekBar的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12Android Studio 3.3.2 正式版的安裝教程圖解
這篇文章主要介紹了Android Studio 3.3.2 正式版的安裝教程圖解,本文分步驟通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2020-02-02Android獲取SDcard目錄及創(chuàng)建文件夾的方法
今天小編就為大家分享一篇Android獲取SDcard目錄及創(chuàng)建文件夾的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08Android數(shù)據(jù)庫(kù)增刪改查實(shí)戰(zhàn)案例
我們?cè)诰幊讨薪?jīng)常會(huì)遇到數(shù)據(jù)庫(kù)的操作,這篇文章主要給大家介紹了關(guān)于Android數(shù)據(jù)庫(kù)增刪改查的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04