Android弧形ProgressBar、SeekBar
網上有很多弧形或者圓形的ProgressBar和SeekBar。前幾天無意中發現一個弧形的ProgressBar覺得挺不錯的,就下載來看看原始碼。
執行他的Demo的時候發現幾個問題,並且有些問題在issue裡面也有人提出了,但是作者一直沒有回覆,我把問題修復之後加上了Seek的功能,讓它能當做SeekBar用。
原作者的Demo效果圖
存在的問題:
不能透過XML配置控制元件的大小,原始碼裡面寫死了,寫成佔螢幕的百分比。
有幾個屬性的顏色值設定無效。比如預設的弧形背景色
放大縮小控制元件之後對應的字型沒有相應的調整大小
需要考慮的問題點:
我們從最下面帶刻度帶提示的效果圖入手
####我們呢先分析原作者的程式碼:
package com.shinelw.colorarcprogressbar;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.PaintFlagsDrawFilter;import android.graphics.RectF;import android.graphics.SweepGradient;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.view.View;import android.view.WindowManager;/** * colorful arc progress bar * Created by shinelw on 12/4/15. */public class ColorArcProgressBar extends View{ private int mWidth; private int mHeight; //直徑 private int diameter = 500; private RectF bgRect; //圓心 private float centerX; private float centerY; private Paint allArcPaint; private Paint progressPaint; private Paint vTextPaint; private Paint hintPaint; private Paint degreePaint; private Paint curSpeedPaint; private float startAngle = 135; private float sweepAngle = 270; private float currentAngle = 0; private float lastAngle; private int[] colors = {Color.GREEN, Color.YELLOW, Color.RED, Color.RED}; private ValueAnimator progressAnimator; private float maxValues = 60; private float curValues = 0; private int bgArcWidth = dipToPx(2); private int progressWidth = dipToPx(10); private int textSize = dipToPx(80); private int hintSize = dipToPx(22); private int curSpeedSize = dipToPx(13); private int aniSpeed = 1000; private int longdegree = dipToPx(13); private int shortdegree = dipToPx(5); private final int DEGREE_PROGRESS_DISTANCE = dipToPx(8); private String hintColor = "#676767"; private String longDegreeColor = "#d2d2d2"; private String shortDegreeColor = "#adadad"; private String bgArcColor = "#111111"; private boolean isShowCurrentSpeed = true; private String hintString = "Km/h"; // sweepAngle / maxValues 的值 private float k; public ColorArcProgressBar(Context context) { super(context); initView(); } public ColorArcProgressBar(Context context, AttributeSet attrs) { super(context, attrs); initView(); } public ColorArcProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = 2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE; int height= 2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE; setMeasuredDimension(width, height); } private void initView() { diameter = 3 * getScreenWidth() / 5; //弧形的矩陣區域 bgRect = new RectF(); bgRect.top = longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE; bgRect.left = longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE; bgRect.right = diameter + (longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE); bgRect.bottom = diameter + (longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE); //圓心 centerX = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE)/2; centerY = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE)/2; //外部刻度線 degreePaint = new Paint(); degreePaint.setColor(Color.parseColor(longDegreeColor)); //整個弧形 allArcPaint = new Paint(); allArcPaint.setAntiAlias(true); allArcPaint.setStyle(Paint.Style.STROKE); allArcPaint.setStrokeWidth(bgArcWidth); allArcPaint.setColor(Color.parseColor(bgArcColor)); allArcPaint.setStrokeCap(Paint.Cap.ROUND); //當前進度的弧形 progressPaint = new Paint(); progressPaint.setAntiAlias(true); progressPaint.setStyle(Paint.Style.STROKE); progressPaint.setStrokeCap(Paint.Cap.ROUND); progressPaint.setStrokeWidth(progressWidth); progressPaint.setColor(Color.GREEN); //當前速度顯示文字 vTextPaint = new Paint(); vTextPaint.setTextSize(textSize); vTextPaint.setColor(Color.WHITE); vTextPaint.setTextAlign(Paint.Align.CENTER); //顯示“km/h”文字 hintPaint = new Paint(); hintPaint.setTextSize(hintSize); hintPaint.setColor(Color.parseColor(hintColor)); hintPaint.setTextAlign(Paint.Align.CENTER); //顯示“km/h”文字 curSpeedPaint = new Paint(); curSpeedPaint.setTextSize(curSpeedSize); curSpeedPaint.setColor(Color.parseColor(hintColor)); curSpeedPaint.setTextAlign(Paint.Align.CENTER); } @Override protected void onDraw(Canvas canvas) { //抗鋸齒 canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG)); //畫刻度線 for (int i = 0; i 15 && i maxValues) { currentValues = maxValues; } if (currentValues = 0 ? 1 : -1)); } /** * 得到螢幕寬度 * @return */ private int getScreenWidth() { WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); DisplayMetrics displayMetrics = new DisplayMetrics(); windowManager.getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.widthPixels; } public void setIsShowCurrentSpeed(boolean isShowCurrentSpeed) { this.isShowCurrentSpeed = isShowCurrentSpeed; } /** * 初始載入頁面時設定載入動畫 */ public void setDefaultWithAnimator() { setAnimation(sweepAngle, currentAngle, 2000); } }123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
從以上程式碼可以看出:
-
在initView 的時候設定了弧形的直徑diameter = 3 * getScreenWidth() / 5;也就是弧形的直徑是根據螢幕的大小定的。
我們再看OnMeasure方法@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = 2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE; int height= 2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE; setMeasuredDimension(width, height); }
所以我們知道:不管你怎麼設定控制元件的寬高,都沒有效果。這是第一個問題
-
設定某些顏色值無效的問題:
顏色值的設定是通常作用於畫筆上,我們先看看幾個畫筆:private Paint allArcPaint;//背景弧形的畫筆(圓弧) private Paint progressPaint;//進度畫筆(當前速度) private Paint vTextPaint;//內容文字畫筆(80) private Paint hintPaint;//單位文字畫筆(km/h) private Paint degreePaint;//刻度畫筆(刻度條) private Paint curSpeedPaint;//標題文字畫筆(當前速度)
這些畫筆的顏色值在initView的時候初始化,但是顏色值並沒有在initConfig的時候取出屬性值並且配置,所以這是導致設定顏色無效的原因
注意:給畫筆設定的顏色值必須帶有透明度,不然會自動帶上全透明效果。看不到任何資訊
調整控制元件大小的時候圓弧內的文字沒有做出大小和位置的調整
在原始碼中,initView的時候就已經設定TextSize了,而initView是在例項化的時候呼叫的,這時候控制元件的大小都還沒有確定,所以需要把和大小相關的值都放到OnSizeChange中,或者在OnMeasure中獲取控制元件的實際大小之後再初始化這些值
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = w; mHeight = h; Log.v("ColorArcProgressBar", "onSizeChanged: mWidth:" + mWidth + " mHeight:" + mHeight); diameter = (int) (Math.min(mWidth, mHeight) - 2 * (longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2)); Log.v("ColorArcProgressBar", "onSizeChanged: diameter:" + diameter); //弧形的矩陣區域 bgRect = new RectF(); bgRect.top = longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2; bgRect.left = longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2; bgRect.right = diameter + (longDegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE); bgRect.bottom = diameter + (longDegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE); Log.v("ColorArcProgressBar", "initView: " + diameter); //圓心 centerX = (2 * (longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2) + diameter) / 2; centerY = (2 * (longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2) + diameter) / 2; sweepGradient = new SweepGradient(centerX, centerY, colors, null); mTouchInvalidateRadius = Math.max(mWidth, mHeight) / 2 - longDegree - DEGREE_PROGRESS_DISTANCE - progressWidth * 2; if(isAutoTextSize) { textSize = (float) (diameter * 0.3); hintSize = (float) (diameter * 0.1); curSpeedSize = (float) (diameter * 0.1); vTextPaint.setTextSize(textSize); hintPaint.setTextSize(hintSize); curSpeedPaint.setTextSize(curSpeedSize); } }
透過在OnSizeChange中初始化這些動態的尺寸,就解決了文字縮放的問題。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1868/viewspace-2806089/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android -- SeekBar(II)縱向seekBarAndroid
- Android 圓形ProgressBar 改變顏色Android
- Android自定義控制元件 帶文字提示的SeekBarAndroid控制元件
- Android SeekBar 自定義thumb,thumb旋轉動畫效果Android動畫
- AUTOCAD——弧形文字排列
- Android進階——自定義View之雙向選擇SeekbarAndroidView
- 中級實訓Android學習記錄——Toast、AlertDialog、ProgressBarAndroidAST
- ProgressBar及其子類
- WPF ProgressBar show value
- 自定義帶標尺的seekbar
- vue2+swiper 縱向弧形滾動效果Vue
- ProgressBar進度條顏色
- android自帶ProgressBar圓形進度條修改顏色的技巧方法無bug探索Android
- 直播平臺搭建原始碼,Android進度條ProgressBar顏色的漸變設定原始碼Android
- SeekBar進度和緩衝進度使用
- 使用 Flutter 自定義一個 ProgressBar - IntervalProgressBarFlutter
- flutter seekbar 可拖拽可點選的進度條Flutter
- Tkinter (33) 進度條部件 ttk.Progressbar
- 字型隨著ProgressBar的載入而滾動
- C++ Qt開發:ProgressBar進度條元件C++QT元件
- 很實用的進度條外掛ProgressBar.jsJS
- 學習筆記 ProgressBar三種style 水平兩種寫法筆記
- 直播帶貨平臺原始碼,利用ProgressBar實現垂直、水平進度條原始碼
- C# 根據BackgroundWoker非同步模型和ProgressBar控制元件,自定義進度條控制元件C#非同步模型控制元件
- [C#] (原創)一步一步教你自定義控制元件——04,ProgressBar(進度條)C#控制元件
- Android學習—— Android佈局Android
- [Android元件化]Android app BundleAndroid元件化APP
- Android之android exported="false"作用AndroidExportFalse
- AndroidAndroid
- Android APIs (Class Index - Android SDK)(一)AndroidAPIIndex
- Android APIs (Class Index - Android SDK)(二)AndroidAPIIndex
- Android總結篇系列:Android ServiceAndroid
- 2018.03.12、Android知識點-Android篇Android
- android開發 之 Bolts-AndroidAndroid
- Android解析ClassLoader(二)Android中的ClassLoaderAndroid
- 【Android SDK】在命令列管理Android SDKAndroid命令列
- Android Q (Android 10.0)系統新特性Android
- vector android:fillType gradient android:endX attribute not foundAndroid