91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Android中通過自定義View實現一個環形進度條效果

發布時間:2020-12-04 16:10:48 來源:億速云 閱讀:172 作者:Leah 欄目:移動開發

這篇文章給大家介紹怎么在Android中通過自定義View實現一個環形進度條效果,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

功能分析

雖然功能比較簡單,但是仍然需要仔細分析

     1.圖標外還有一圈圓圈,可以設置寬度

     2.圓形進度條和進度條底部,可以設置寬度,顏色等

     3.內部有一個圓形圖片,可旋轉

實現思路分析

1.可以設置寬度的圓圈

這個比較容易,直接在onDraw方法中使用canvas繪制即可,當然,在間距和半徑的處理上需要仔細,控件本體其實還是一個長方形,我們需要選取較短的那一邊作為直徑,同時也要處理內部的padding

2.圓形進度條和進度條底部,可以設置寬度,顏色等

這個可以用canvas的drawArc方法來實現,通過繪制不同長度的弧形來達到顯示進度的目的,但是需要注意的是,我們需要計算好弧形的半徑以及開始和結束點。

3.內部有一個圓形圖片,可旋轉

這個需求可以分為三個部分,有圖片,圓形,可以旋轉

先說有圖,很簡單,canvas的drawbitmap方法繪制(canvas真是好東西)

再說圓形,這就比較復雜了,但是整體來說依然是使用canvas來對bitmap進行操作,會在代碼中細說

最后是可以旋轉,我們可以通過canvas的rotate方法來做。

效果展示

說了這么多,那么最后的效果是怎樣的呢?畢竟空口無憑,在進入代碼展示的環節之前還是看看最后的效果吧。

這是我自己做的一個定時鎖屏的項目,地址是這里是地址或者本地下載

這是這個項目運行鎖屏的時候的動圖(大家都喜歡動圖)

怎么在Android中通過自定義View實現一個環形進度條效果

代碼實現

下面開始展示代碼,并加以分析

我們主要的工作是在一個自定義的view中的onDraw方法實現的,所以,我們需要有一個繼承View類的子類,我們就叫他MyProgress吧

我們展示的就是這個MyProgress的onDraw方法

1.可以設置寬度的圓圈

很簡單,我們只需要調用canvas的drawCircle方法即可,但是需要注意對padding的處理,因為不處理就會無效

super.onDraw(canvas); //需要在函數開始的地方調用父類的onDraw
 
  final int paddingLeft = getPaddingLeft();
  final int paddingRight = getPaddingRight();
  final int paddingTop = getPaddingTop();
  final int paddingBottom = getPaddingBottom(); //獲取padding
 
  //get the view's width and height and decide the radiu
  int width = getWidth() - paddingLeft - paddingRight;
  int height = getHeight() - paddingTop - paddingBottom;
  radiu = Math.min(width , height) / 2 - boundWidth - progressWidth; //計算半徑,選取長寬中短的那個做處理,boundWidth是圓圈的寬度,progressWidth是進度條的寬度
 
  //setup the paint
  paint.setStyle(Paint.Style.STROKE); //設置paint為畫輪廓
  paint.setStrokeWidth(boundWidth); //設置寬度
  paint.setColor(Color.BLACK);  //設置顏色
 
  //draw the inner circle
  int centerX = paddingLeft + getWidth()/2;
  int centerY = paddingTop + getHeight() / 2; //計算圓的中心點
  canvas.drawCircle(centerX,centerY, radiu, paint); //繪制圓形

2.圓形進度條和進度條底部,可以設置寬度,顏色等

這里需要注意的就是開始的角度和結束的角度了,為了達到進度條目的,所以我們需要隨著業務狀態的改變來改變這個值

  //set paint for arc
  paint.setStrokeWidth(progressWidth);
  paint.setStrokeCap(Paint.Cap.ROUND);//設置進度寬度,設置末端是一個圓弧
 
  //prepare for draw arc
  RectF oval = new RectF();
  oval.left = centerX -totalRadiu ;
  oval.top =centerY- totalRadiu ;
  oval.right = centerX + totalRadiu;
  oval.bottom = centerY+ totalRadiu; //新建一個橢圓,設置其四個點的坐標
  paint.setColor(progressBackColor);//設置進度條背景的顏色
 
  //draw background arc
  canvas.drawArc(oval, arcStar, arcEnd, false, paint); //繪制底部的一個圓弧,作為背景
 
  //draw progress arc
  paint.setColor(progressColor);//設置進度條的顏色
  canvas.drawArc(oval, arcStar, progress, false, paint);//繪制進度條

3.內部有一個圓形圖片,可旋轉

這一段比較復雜,直接用代碼解釋

  float totalRadiu = radiu +boundWidth +progressWidth/2;//設置外徑
 
  //draw the circlr pic
  if (drawable != null&&bitmap == null) {
   image = ((BitmapDrawable) drawable).getBitmap();//獲取設置的bitmap資源
 
   bitmap = Bitmap.createBitmap((int)(2*totalRadiu),(int)(2*totalRadiu), Bitmap.Config.ARGB_8888);
   Canvas bitmapCanvas = new Canvas(bitmap);//新建一個bitmap并新建一個canvas用以操作
 
   Paint bitmapPaint = new Paint();
   bitmapPaint.setAntiAlias(true);//新建一個paint并設置反鋸齒
 
   bitmapCanvas.drawCircle(totalRadiu, totalRadiu, radiu, bitmapPaint);//畫一個圓
 
   bitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//關鍵代碼,設置為交集模式,會讓后面的內容和已有內容取交集
   bitmapCanvas.drawBitmap(image,null,new RectF(0,0,2*totalRadiu,2*totalRadiu) , bitmapPaint);//繪制自己的圖片到現有畫布上
 
  }
  Rect rect = new Rect((int)(centerX -totalRadiu),(int)(centerY-totalRadiu),(int)(centerX+totalRadiu),(int)(centerY+ totalRadiu));//新建一個rect,設定邊界點
  canvas.save();
  if(isRotate)
  canvas.rotate(rotateDegree,centerX,centerY);//設置旋轉,為了實現圖片轉動效果,rotateDegree為旋轉角度
  canvas.drawBitmap(bitmap,null ,rect, paint);//繪制處理過的圖片

有了上面這些代碼,我們自定義View的主體部分就完成了,當然還有一些輔助的部分,比如更新進度和選擇角度的函數,設置一些顏色和寬度之類的參數等

完整代碼

MyProgress

public class MyProgressBar extends View {
 float progress = 360;
 float arcStar = 270;
 float arcEnd = 360;
 double rotateStep = 0.2;
 Bitmap bitmap;
 int totalTime;
 Bitmap image;
 Drawable drawable;
 int boundWidth = 5;
 private int progressWidth = 30;
 private boolean isRotate = false;
 private int progressColor = Color.GREEN;
 private int progressBackColor = Color.GREEN;
 private float rotateDegree = 0;
 
 
 public MyProgressBar(Context context) {
  super(context);
 }
 
 public MyProgressBar(Context context, AttributeSet attrs) {
  super(context, attrs);
 }
 
 public MyProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
 }
 
 private float radiu;
 private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
 
 public void setRadiu(float radiu) {
  this.radiu = radiu;
  invalidate();
 }
//start 函數使用 countDownTimer類來更新progress和旋轉角度
 public void start(long time) {
  bitmap = null;
 
  time *= 60000;
  final float step = (float) 360 / (time / 30);
  CountDownTimer mTimer = new CountDownTimer(time, 30) {
   public void onTick(long millisUntilFinished) {
    progress -= step;
    rotateDegree -= rotateStep;
    invalidate();
   }
 
   @Override
   public void onFinish() {
    end(step);
   }
 
  };
  mTimer.start();
 }
 
 private void end(float step) {
  progress -= step;
  invalidate();
  progress = 0;
  rotateDegree = 0;
  invalidate();
 }
 
 public void setBoundWidth(int width) {
  boundWidth = width;
 }
 
 public void setProgressWidth(int width) {
  progressWidth = width;
 }
 
 public void setProgressColor(int color) {
  progressColor = color;
 }
 
 public void setProgressBackColor(int color) {
  progressBackColor = color;
 }
 
 public void setDrawable(Drawable drawable) {
  this.drawable = drawable;
  invalidate();
 }
 public void setIsRote(boolean rotate)
 {
  this.isRotate = rotate;
  invalidate();
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
 
  final int paddingLeft = getPaddingLeft();
  final int paddingRight = getPaddingRight();
  final int paddingTop = getPaddingTop();
  final int paddingBottom = getPaddingBottom();
 
  //get the view's width and height and decide the radiu
  int width = getWidth() - paddingLeft - paddingRight;
  int height = getHeight() - paddingTop - paddingBottom;
  radiu = Math.min(width , height) / 2 - boundWidth - progressWidth;
 
  //setup the paint
  paint.setStyle(Paint.Style.STROKE);
  paint.setStrokeWidth(boundWidth);
  paint.setColor(Color.BLACK);
 
  //draw the inner circle
  int centerX = paddingLeft + getWidth()/2;
  int centerY = paddingTop + getHeight() / 2;
  canvas.drawCircle(centerX,centerY, radiu, paint);
  
 
  float totalRadiu = radiu +boundWidth +progressWidth/2;
 
  //draw the circlr pic
  if (drawable != null&&bitmap == null) {
   image = ((BitmapDrawable) drawable).getBitmap();
 
   bitmap = Bitmap.createBitmap((int)(2*totalRadiu),(int)(2*totalRadiu), Bitmap.Config.ARGB_8888);
   Canvas bitmapCanvas = new Canvas(bitmap);
 
   Paint bitmapPaint = new Paint();
   bitmapPaint.setAntiAlias(true);
 
   bitmapCanvas.drawCircle(totalRadiu, totalRadiu, radiu, bitmapPaint);
 
   bitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
   bitmapCanvas.drawBitmap(image,null,new RectF(0,0,2*totalRadiu,2*totalRadiu) , bitmapPaint);
 
 
  }
  Rect rect = new Rect((int)(centerX -totalRadiu),(int)(centerY-totalRadiu),(int)(centerX+totalRadiu),(int)(centerY+ totalRadiu));
  canvas.save();
  if(isRotate)
  canvas.rotate(rotateDegree,centerX,centerY);
  canvas.drawBitmap(bitmap,null ,rect, paint);
 
  canvas.restore();
  //set paint for arc
  paint.setStrokeWidth(progressWidth);
  paint.setStrokeCap(Paint.Cap.ROUND);
 
  //prepare for draw arc
  RectF oval = new RectF();
  oval.left = centerX -totalRadiu ;
  oval.top =centerY- totalRadiu ;
  oval.right = centerX + totalRadiu;
  oval.bottom = centerY+ totalRadiu;
  paint.setColor(progressBackColor);
 
  //draw background arc
  canvas.drawArc(oval, arcStar, arcEnd, false, paint);
 
  //draw progress arc
  paint.setColor(progressColor);
  canvas.drawArc(oval, arcStar, progress, false, paint);
 }
 
}

完整的工程,包括對這個自定義VIEW的應用例子可以參考我在GitHub上的工程地址在這里,也可以本地下載

總結

這個看似簡單的自定義View的制作當中還是遇到了不少值得思考的問題,這也是為什么有這篇文章的原因

      1.在處理圓形剪裁圖片的時候,要注意剪裁的canvas所用的坐標是相對于處理圖片的,而不是整體坐標

      2.在繪制時,應該盡量減少重復的處理,比如圓形圖片剪裁,一次就夠了,如果次數過多,每次更新進度的時候就會去進行一次,導致整個View比較卡,進度不準確

      3.對于自定義View中幾個關鍵點的坐標,應該用一個比較簡單易懂的表達式表示,否則做到后期會搞混淆,而陷入坐標的泥潭之中

      4.某些看起來很厲害的效果只要合理分析,分步實現,并不會很難

關于怎么在Android中通過自定義View實現一個環形進度條效果就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

三河市| 左贡县| 西吉县| 安新县| 渭源县| 尚义县| 芦山县| 金寨县| 会宁县| 滦平县| 驻马店市| 平遥县| 资中县| 庄河市| 陆河县| 永年县| 隆回县| 云南省| 秀山| 大洼县| 兰溪市| 滁州市| 鹤峰县| 郴州市| 滨州市| 二手房| 师宗县| 衡山县| 大丰市| 巴彦县| 舟山市| 沂水县| 海城市| 罗平县| 永泰县| 道真| 太康县| 高阳县| 宁国市| 师宗县| 佛学|