欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android自定義控件實現(xiàn)帶數(shù)值和動畫的圓形進度條

 更新時間:2018年12月25日 09:51:16   作者:王世暉  
這篇文章主要為大家詳細介紹了Android自定義控件實現(xiàn)帶數(shù)值和動畫的圓形進度條,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例實現(xiàn)一個如下圖所示的Android自定義控件,可以直觀地展示某個球隊在某個賽季的積分數(shù)和勝場、負場、平局數(shù)

首先對畫布進行區(qū)域劃分,整個控件分上下兩部分

上邊是個大的圓環(huán),圓環(huán)中間兩行文字,沒什么難度,選好圓心坐標和半徑后直接繪制即可,繪制文字也是如此。

下部分是三個小的圓弧進度條,弧的末端繪制一個小的實心圓

首先選好坐標和半徑,然后先繪制三個圓環(huán)作為弧形進度條的背景

之后從12點鐘開始繪制進度弧,知道了圓環(huán)的圓心和半徑,也知道了弧對應于12點鐘和圓環(huán)圓心的偏移角度

通過三角函數(shù)可以計算出進度弧終點坐標,以進度弧終點坐標為圓心繪制一個小的實心圓即可

動畫效果通過Handler的postDelayed方法觸發(fā)重繪即可實現(xiàn)

在項目中的效果如圖所示:

測試代碼如下:

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;
 /*積分數(shù),勝場數(shù),平局數(shù),負場數(shù)*/
 private int mScore, mWinNumber, mDrawNumber, mLoseNumber;
 /*傳入數(shù)字的最大值*/
 private final int FULL_SCORE = 30;
 /*動畫插值器*/
 DecelerateInterpolator mDecelerateInterpolator = new DecelerateInterpolator();
 /*動畫持續(xù)時間(刷新次數(shù))*/
 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++;
    /*導致重繪調(diào)用onDraw,onDraw最后再次postDelay執(zhí)行此動畫,直到達到指定的次數(shù)*/
    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() {
  /*數(shù)據(jù)初始化,默認屬性*/
  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:動畫從開始到結束,變化率是循環(huán)給定次數(shù)的正弦曲線
  * AccelerateDecelerateInterpolator:動畫從開始到結束,變化率是先加速后減速的過程。
  * LinearInterpolator:動畫從開始到結束,變化率是線性變化。
  * */
  /*計算當前時刻動畫進度值*/
  float AnimCurrentValue =mDecelerateInterpolator.getInterpolation(1.0f * mCurrentTime / mDuration);
 
  /*圖形畫筆設置*/
  paint.setAntiAlias(true);
  paint.setStyle(Paint.Style.STROKE);
 
  /*積分數(shù),上邊的大圓*/
  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));
  /*圓心位置繪制積分數(shù)值*/
  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};
  /*設置畫筆顏色,繪制外圍圓環(huán)*/
  paint.setColor(getResources().getColor(typedValue1.resourceId));
  /*分別繪制三個外圍圓環(huán)*/
  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);
  /*已知半徑、圓心位置、便宜角度,根據(jù)三角函數(shù)很方便計算出小實心圓圓心坐標*/
  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;
  /*在三個小圓的正中心位置繪制相應的數(shù)字*/
  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);
  /*調(diào)整字體大小,繪制文本信息*/
  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刷新一次數(shù)據(jù)*/
  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();
 }
}

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Android-實現(xiàn)切換Fragment頁功能的實現(xiàn)代碼

    Android-實現(xiàn)切換Fragment頁功能的實現(xiàn)代碼

    本篇文章主要介紹了Android-實現(xiàn)切換Fragment頁功能的實現(xiàn)代碼,具有一定的參加價值,有興趣的可以了解一下。
    2017-02-02
  • Android帶清除功能的輸入框控件EditTextWithDel

    Android帶清除功能的輸入框控件EditTextWithDel

    這篇文章主要為大家詳細介紹了Android帶清除功能的輸入框控件EditTextWithDel,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Kotlin中空判斷處理操作實例

    Kotlin中空判斷處理操作實例

    最近使用kotlin重構項目,遇到了一個小問題,在Java中,可能會遇到判斷某個對象是否為空,為空執(zhí)行一段邏輯,不為空執(zhí)行另外一段邏輯,下面這篇文章主要給大家介紹了關于Kotlin中空判斷處理操作的相關資料,需要的朋友可以參考下
    2022-07-07
  • Android中TextView文本高亮和點擊行為的封裝方法

    Android中TextView文本高亮和點擊行為的封裝方法

    這篇文章主要介紹了Android中TextView文本高亮和點擊行為的封裝方法,文中介紹的非常詳細,相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。
    2017-03-03
  • android底部菜單欄實現(xiàn)原理與代碼

    android底部菜單欄實現(xiàn)原理與代碼

    底部菜單欄很重要,我看了一下很多應用軟件都是用了底部菜單欄做,我這里使用了tabhost做了一種通用的(就是可以像微信那樣顯示未讀消息數(shù)量的,雖然之前也做過但是layout下的xml寫的太臃腫,這里去掉了很多不必要的層,個人看起來還是不錯的,所以貼出來方便以后使用
    2013-01-01
  • Android系統(tǒng)默認對話框添加圖片功能

    Android系統(tǒng)默認對話框添加圖片功能

    這篇文章主要介紹了Android系統(tǒng)默認對話框添加圖片的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-01-01
  • Android逆向入門之常見Davlik字節(jié)碼解析

    Android逆向入門之常見Davlik字節(jié)碼解析

    Dalvik是Google公司自己設計用于Android平臺的虛擬機。Dalvik虛擬機是Google等廠商合作開發(fā)的Android移動設備平臺的核心組成部分之一,本篇文章我們來詳細解釋常見Davlik字節(jié)碼
    2021-11-11
  • Android中l(wèi)ayout屬性大全

    Android中l(wèi)ayout屬性大全

    這篇文章主要介紹了Android中l(wèi)ayout屬性含義及用法,較為詳細的總結分析了layout屬性相關用法,需要的朋友可以參考下
    2015-05-05
  • Android Studio卡很久(loading)的問題解決辦法

    Android Studio卡很久(loading)的問題解決辦法

    這篇文章主要介紹了Android Studio卡很久(loading很久)的問題的相關資料,需要的朋友可以參考下
    2017-05-05
  • 親自動手編寫Android通用刷新控件

    親自動手編寫Android通用刷新控件

    這篇文章主要記錄了親自動手編寫Android通用刷新控件的詳細過程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06

最新評論