Android開發自定義控制元件實現一個圓形進度條【帶數值和動畫】
實現一個如下圖所示的自定義控制元件,可以直觀地展示某個球隊在某個賽季的積分數和勝場、負場、平局數
首先對畫布進行區域劃分,整個控制元件分上下兩部分
上邊是個大的圓環,圓環中間兩行文字,沒什麼難度,選好圓心座標和半徑後直接繪製即可,繪製文字也是如此。
下部分是三個小的圓弧進度條,弧的末端繪製一個小的實心圓
首先選好座標和半徑,然後先繪製三個圓環作為弧形進度條的背景
之後從12點鐘開始繪製進度弧,知道了圓環的圓心和半徑,也知道了弧對應於12點鐘和圓環圓心的偏移角度
通過三角函式可以計算出進度弧終點座標,以進度弧終點座標為圓心繪製一個小的實心圓即可
動畫效果通過Handler的postDelayed方法觸發重繪即可實現
在專案中的效果如圖所示:
測試程式碼如下:
final Random random=new Random(); final ScoreBoardView myView=(ScoreBoardView)findViewById(R.id.custom_view); myView.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v){ myView.setColor(Color.BLUE); myView.setScore(random.nextInt(28)); myView.setWinDrawLose(random.nextInt(12),random.nextInt(15),random.nextInt(26)); } });
完整程式碼如下:
public class ScoreBoardView extends View {
private Context context;
/*弧的顏色*/
private int mColor;
/*積分數,勝場數,平局數,負場數*/
private int mScore, mWinNumber, mDrawNumber, mLoseNumber;
/*傳入數字的最大值*/
private final int FULL_SCORE = 30;
/*動畫插值器*/
DecelerateInterpolator mDecelerateInterpolator = new DecelerateInterpolator();
/*動畫持續時間(重新整理次數)*/
private int mDuration = 10;
/*動畫重新整理過程中的當前值*/
private int mCurrentTime = 0;
private TypedValue typedValue;
private TypedValue typedValue1;
private Handler mHandler = new Handler();
private Runnable mAnimation = new Runnable() {
@Override
public void run() {
if (mCurrentTime < mDuration) {
mCurrentTime++;
/*導致重繪呼叫onDraw,onDraw最後再次postDelay執行此動畫,直到達到指定的次數*/
ScoreBoardView.this.invalidate();
}
}
};
/*繪製圖形*/
private Paint paint = new Paint();
/*繪製文字*/
private Paint paintText = new Paint();
public ScoreBoardView(Context context) {
super(context);
this.context=context;
init();
}
public ScoreBoardView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
init();
}
public ScoreBoardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context=context;
init();
}
private void init() {
/*資料初始化,預設屬性*/
mColor = Color.rgb(95, 112, 72);
mScore = 0;
mWinNumber = 0;
mDrawNumber = 0;
mLoseNumber = 0;
typedValue=new TypedValue();
typedValue1=new TypedValue();
context.getTheme().resolveAttribute(R.attr.maintextclor, typedValue, true);
context.getTheme().resolveAttribute(R.attr.maintextclor_reverse,typedValue1,true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/*獲取控制元件總的寬高*/
float totalWidth = getWidth();
float totalHeight = getHeight();
/*
* DecelerateInterpolator:動畫從開始到結束,變化率是一個減速的過程。
* AccelerateInterpolator:動畫從開始到結束,變化率是一個加速的過程。
* CycleInterpolator:動畫從開始到結束,變化率是迴圈給定次數的正弦曲線
* AccelerateDecelerateInterpolator:動畫從開始到結束,變化率是先加速後減速的過程。
* LinearInterpolator:動畫從開始到結束,變化率是線性變化。
* */
/*計算當前時刻動畫進度值*/
float AnimCurrentValue =mDecelerateInterpolator.getInterpolation(1.0f * mCurrentTime / mDuration);
/*圖形畫筆設定*/
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
/*積分數,上邊的大圓*/
paint.setStrokeWidth(4);
paint.setColor(mColor);
/*積分大圓的中心座標和半徑*/
float score_radius = totalHeight * 1 / 5, score_circle_x = totalWidth / 2, score_circle_y = totalHeight / 3;
/*繪製圓弧*/
canvas.drawCircle(score_circle_x, score_circle_y, score_radius, paint);
/*文字畫筆基本設定*/
paintText.setAntiAlias(true);
paintText.setStyle(Paint.Style.STROKE);
/*文字從中間開始繪製*/
/*Paint.Align.CENTER:The text is drawn centered horizontally on the x,y origin*/
paintText.setTextAlign(Paint.Align.CENTER);
/*文字畫筆大小和顏色設定*/
paintText.setTextSize(score_radius * 3 / 4);
paintText.setColor(getResources().getColor(typedValue.resourceId));
/*圓心位置繪製積分數值*/
canvas.drawText("" + mScore, score_circle_x, score_circle_y, paintText);
/*縮小字型繪製文字資訊*/
paintText.setTextSize(score_radius * 1 / 4);
paintText.setAlpha(80);
/*圓心下邊繪製文字*/
canvas.drawText("積分", score_circle_x, score_circle_y + score_radius / 2, paintText);
/*設定畫筆,畫下邊的三個小圓*/
paint.setStrokeWidth(4);
paint.setAlpha(255);
/*下邊三個小圓的半徑*/
float small_radius = totalHeight / 10;
/*三個小圓的圓心的x座標*/
float[] circleXs = new float[]{totalWidth / 2 - score_radius * 3 / 2,
totalWidth / 2,
totalWidth / 2 + score_radius * 3 / 2};
/*三個小圓的圓心的y座標*/
float circleY = totalHeight * 3 / 4;
/*計算三個小圓弧掃過的角度*/
float[] theta_values = new float[]{360 * mWinNumber / FULL_SCORE* AnimCurrentValue,
360 * mDrawNumber / FULL_SCORE* AnimCurrentValue,
360 * mLoseNumber / FULL_SCORE* AnimCurrentValue};
/*設定畫筆顏色,繪製外圍圓環*/
paint.setColor(getResources().getColor(typedValue1.resourceId));
/*分別繪製三個外圍圓環*/
canvas.drawCircle(circleXs[0], circleY, small_radius, paint);//畫WIN背景圓
canvas.drawCircle(circleXs[1], circleY, small_radius, paint);//畫DRAW背景圓
canvas.drawCircle(circleXs[2], circleY, small_radius, paint);//畫LOSE背景圓
/*更改畫筆顏色,繪製圓弧進度條*/
paint.setColor(mColor);
/*drawArc的起始角度是3點鐘方向,因此要從12點鐘方向開始繪製,起始角度為270度*/
canvas.drawArc(new RectF(circleXs[0] - small_radius,
circleY - small_radius,
circleXs[0] + small_radius,
circleY + small_radius),
270, theta_values[0], false, paint);//畫WIN圓形進度條
canvas.drawArc(new RectF(circleXs[1] - small_radius,
circleY - small_radius,
circleXs[1] + small_radius,
circleY + small_radius),
270, theta_values[1], false, paint);//畫DRAW圓形進度條
canvas.drawArc(new RectF(circleXs[2] - small_radius,
circleY - small_radius,
circleXs[2] + small_radius,
circleY + small_radius),
270, theta_values[2], false, paint);//畫LOSE圓形進度條
/*繪製圓弧結束處的小圓點,實心圓*/
paint.setStyle(Paint.Style.FILL);
/*已知半徑、圓心位置、便宜角度,根據三角函式很方便計算出小實心圓圓心座標*/
canvas.drawCircle(circleXs[0] + small_radius * (float) Math.sin(theta_values[0] * Math.PI / 180),
circleY - small_radius * (float) Math.cos(theta_values[0] * Math.PI / 180), 6, paint);//畫WIN末尾小圓點
canvas.drawCircle(circleXs[1] + small_radius * (float) Math.sin(theta_values[1] * Math.PI / 180),
circleY - small_radius * (float) Math.cos(theta_values[1] * Math.PI / 180), 6, paint);//畫DRAW末尾小圓點
canvas.drawCircle(circleXs[2] + small_radius * (float) Math.sin(theta_values[2] * Math.PI / 180),
circleY - small_radius * (float) Math.cos(theta_values[2] * Math.PI / 180), 6, paint);//畫LOSE末尾小圓點
/*繪製文字*/
paintText.setColor(getResources().getColor(typedValue.resourceId));
paintText.setTextSize(small_radius * 2 / 3);
/*測量文字大小,確定繪製文字時垂直方向的位置*/
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float textBaseLineOffset = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
/*在三個小圓的正中心位置繪製相應的數字*/
canvas.drawText("" + (int)(mWinNumber * AnimCurrentValue), circleXs[0], circleY + textBaseLineOffset, paintText);
canvas.drawText("" + (int)(mDrawNumber * AnimCurrentValue), circleXs[1], circleY + textBaseLineOffset, paintText);
canvas.drawText("" + (int)(mLoseNumber * AnimCurrentValue), circleXs[2], circleY + textBaseLineOffset, paintText);
/*調整字型大小,繪製文字資訊*/
paintText.setTextSize(small_radius * 4 / 9);
canvas.drawText("勝場", circleXs[0], circleY - small_radius*4/3, paintText);
canvas.drawText("平局", circleXs[1], circleY - small_radius*4/3, paintText);
canvas.drawText("負場", circleXs[2], circleY - small_radius*4/3, paintText);
/*20ms重新整理一次資料*/
mHandler.postDelayed(mAnimation, 20);//啟動動畫
}
public void setColor(int mColor) {
this.mColor = mColor;
invalidate();
}
public void setScore(int score) {
this.mScore = score;
invalidate();
}
public void setWinDrawLose(int win,int draw,int lose) {
this.mWinNumber = win;
this.mDrawNumber = draw;
this.mLoseNumber = lose;
mCurrentTime =0;
invalidate();
}
}
相關文章
- Android自定義圓形進度條Android
- 自定義圓形進度條控制元件控制元件
- [-Flutter 自定義元件-] 圓形進度條Flutter元件
- android 自定義酷炫進度條動畫Android動畫
- 【Android】自定義ProgressView-進度條動畫AndroidView動畫
- ios自定義圓環進度條iOS
- Android 自定義 View:包含多種狀態的下載用圓形進度條AndroidView
- Android 自定義圓形旋轉進度條,仿微博頭像載入效果Android
- Vue canvas繪製圓形進度條動畫載入VueCanvas動畫
- Android Studio通過style和layer-list實現自定義進度條Android
- Flutter 波浪圓形進度條Flutter
- 【Android】自定義樹形控制元件Android控制元件
- echarts 繪製圓形進度條帶漸變色Echarts
- 實現環形進度條效果【一】
- Android自定義View之圖片外形特效——輕鬆實現圓角和圓形圖片AndroidView特效
- Qml 實現水波進度動畫條動畫
- vue 自定義指令實現,滾動條百分比進度條。Vue
- android自帶ProgressBar圓形進度條修改顏色的技巧方法無bug探索Android
- VirtualView Android 實現詳解(三)—— 新增一個自定義控制元件ViewAndroid控制元件
- Android 自定義帶動畫的柱狀圖Android動畫
- 可拖拽圓形進度條元件(支援移動端)元件
- 實現一個協程帶進度條下載器
- 直播網站原始碼,Canvas實現圓形時間倒數計時進度條網站原始碼Canvas
- CSS3圓形進度條效果CSSS3
- 使用canvas繪製圓形進度條Canvas
- 簡單好看的Android圓形進度條對話方塊開源庫Android
- 【Android初級】如何實現一個有動畫效果的自定義下拉選單Android動畫
- 短視訊開發app,自定義帶進度條的視訊播放按鈕APP
- android 自定義帶動畫的統計餅圖Android動畫
- C# 根據BackgroundWoker非同步模型和ProgressBar控制元件,自定義進度條控制元件C#非同步模型控制元件
- Android 圓角、圓形 ImageView 實現AndroidView
- 【UWP】實現一個波浪進度條
- Android Reveal圓形Activity轉場動畫Android動畫
- carousel 輪播自定義進度條
- laravel自定義命令列印進度條Laravel命令列
- Android花樣loading進度條(三)-配文字環形進度條Android
- Android自定義控制元件 帶文字提示的SeekBarAndroid控制元件
- 短視訊平臺搭建,Android自定義旋轉進度條Android
- Android自定義View,畫一個好看帶延長線的餅狀圖AndroidView