国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android自定義View實現漸變色進度條

2019-10-22 18:11:08
字體:
來源:轉載
供稿:網友

在網上看到一個進度條效果圖,非常美觀,如下:

Android,漸變色,進度條

進行效果分解:

1.漸變色,看起來顏色變化并不復雜,使用LinearGradient應該可以實現。
2.圓頭,無非是畫兩個圓,外圓使用漸變色的顏色,內圓固定為白色。
3.灰底,還沒有走到的進度部分為灰色。
4.進度值,使用文本來顯示;
5.弧形的頭部,考慮使用直線進行連接,或者使用曲線,例如貝塞爾曲線;

我首先初步實現了進度條的模樣,發現樣子有了,卻不太美觀。
反思了一下,我只是個寫代碼的,對于哪種比例比較美觀,是沒有清晰的認識的,所以,還是參考原圖吧。

然后就進行了精細的測量:

將圖像放大4倍,進行測量,然后獲取到各部分的比例關系,具體過程就不細說了,說一下測量結果(按比例的):

視圖總長300,其中前面留空5,進度長258,然后再留空5,顯示文本占26,后面留空6;

高度分為4個:
外圓:10
字高:9
內圓:6
線粗:5
考慮上下各留空10,則視圖的高度為30。

考慮到視圖整體的效果,可以由用戶來設置長度值與高度值,按比例取最小值來進行繪圖。
首先計算出一個單位的實際像素數,各部分按比例來顯示即可。

還有一個弧形的頭部,是怎么實現的呢?
在放大之后,能看出來圖形比較簡單,看不出有弧度,那么,使用一小段直線連接就可以了。
估算這小段直線:線粗為2,呈30度角,長為8-10即可,連接直線與弧頂,起點在弧頂之左下方。
注意:在進度的起點時,不能畫出。避免出現一個很突兀的小尾巴。在2%進度之后,才開始畫。

在文字的繪制過程中,遇到一個小問題,就是文字不居中,略微偏下,上網查了下,原因是這樣的:我們繪制文本時,使用的這個函數:canvas.drawText(“30%”, x, y, paint);
其中的參數 y 是指字符串baseline的的位置,不是文本的中心。通過計算可以調整為居中,如下:

//計算坐標使文字居中FontMetrics fontMetrics = mPaint.getFontMetrics(); float fontHeight = fontMetrics.bottom - fontMetrics.top;float baseY = height/2 + fontHeight/2 - fontMetrics.bottom;

按比例來繪制之后,就確實是原來那個修長優雅的感覺了。
實際運行后,發現字體偏小,不太適合豎屏觀看,調大了些。

另外對于參數,做了如下幾個自定義屬性:
前景色:開始顏色,結束顏色;
進度條未走到時的默認顏色,
字體顏色。

屬性xml如下:

<?xml version="1.0" encoding="utf-8"?><resources> <attr name="startColor" format="color" /> <attr name="endColor" format="color" /> <attr name="backgroundColor" format="color" /> <attr name="textColor" format="color" /> <declare-styleable name="GoodProgressView"> <attr name="startColor" /> <attr name="endColor" /> <attr name="backgroundColor" /> <attr name="textColor" />  </declare-styleable></resources>

自定義View文件:

 

package com.customview.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.LinearGradient;import android.graphics.Paint;import android.graphics.Shader;import android.graphics.Paint.Cap;import android.graphics.Paint.FontMetrics;import android.graphics.Paint.Style;import android.util.AttributeSet;import android.util.Log;import android.view.View;import com.customview.R;public class GoodProgressView extends View{ private int[] mColors = { Color.RED, Color.MAGENTA};//進度條顏色(漸變色的2個點) private int backgroundColor = Color.GRAY;//進度條默認顏色 private int textColor = Color.GRAY;//文本顏色 private Paint mPaint;//畫筆 private int progressValue=0;//進度值// private RectF rect;//繪制范圍 public GoodProgressView(Context context, AttributeSet attrs) {  this(context, attrs, 0); } public GoodProgressView(Context context) { this(context, null); } // 獲得我自定義的樣式屬性  public GoodProgressView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 獲得我們所定義的自定義樣式屬性  TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.GoodProgressView, defStyle, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) {  int attr = a.getIndex(i);  switch (attr)  {  case R.styleable.GoodProgressView_startColor:  // 漸變色之起始顏色,默認設置為紅色  mColors[0] = a.getColor(attr, Color.RED);  break;   case R.styleable.GoodProgressView_endColor:  // 漸變色之結束顏色,默認設置為品紅  mColors[1] = a.getColor(attr, Color.MAGENTA);  break;   case R.styleable.GoodProgressView_backgroundColor:  // 進度條默認顏色,默認設置為灰色  backgroundColor = a.getColor(attr, Color.GRAY);  break;   case R.styleable.GoodProgressView_textColor:  // 文字顏色,默認設置為灰色  textColor = a.getColor(attr, Color.GRAY);  break;   } } a.recycle(); mPaint = new Paint(); progressValue=0; } public void setProgressValue(int progressValue){ if(progressValue>100){  progressValue = 100; } this.progressValue = progressValue; Log.i("customView","log: progressValue="+progressValue); } public void setColors(int[] colors){ mColors = colors;  } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = 0; int height = 0; /**  * 設置寬度  */ int specMode = MeasureSpec.getMode(widthMeasureSpec); int specSize = MeasureSpec.getSize(widthMeasureSpec); switch (specMode) { case MeasureSpec.EXACTLY:// 明確指定了  width = specSize;  break; case MeasureSpec.AT_MOST:// 一般為WARP_CONTENT  width = getPaddingLeft() + getPaddingRight() ;  break; } /**  * 設置高度  */ specMode = MeasureSpec.getMode(heightMeasureSpec); specSize = MeasureSpec.getSize(heightMeasureSpec); switch (specMode) { case MeasureSpec.EXACTLY:// 明確指定了  height = specSize;  break; case MeasureSpec.AT_MOST:// 一般為WARP_CONTENT  height = width/10;  break; } Log.i("customView","log: w="+width+" h="+height); setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int mWidth = getMeasuredWidth(); int mHeight = getMeasuredHeight(); //按比例計算進度條各部分的值 float unit = Math.min(((float)mWidth)/300, ((float)mHeight)/30); float lineWidth = 5*unit;//線粗 float innerCircleDiameter = 6*unit;//內圓直徑 float outerCircleDiameter = 10*unit;//外圓直徑 float wordHeight = 12*unit;//字高//9*unit// float wordWidth = 26*unit;//字長 float offsetLength = 5*unit;//留空// float width = 300*unit;//繪畫區域的長度 float height = 30*unit;//繪畫區域的高度 float progressWidth = 258*unit;//繪畫區域的長度 mPaint.setAntiAlias(true); mPaint.setStrokeWidth((float) lineWidth ); mPaint.setStyle(Style.STROKE); mPaint.setStrokeCap(Cap.ROUND); mPaint.setColor(Color.TRANSPARENT); float offsetHeight=height/2; float offsetWidth=offsetLength; float section = ((float)progressValue) / 100; if(section>1)  section=1; int count = mColors.length; int[] colors = new int[count]; System.arraycopy(mColors, 0, colors, 0, count);  //底部灰色背景,指示進度條總長度 mPaint.setShader(null); mPaint.setColor(backgroundColor);  canvas.drawLine(offsetWidth+section * progressWidth, offsetHeight, offsetWidth+progressWidth, offsetHeight, mPaint); //設置漸變色區域 LinearGradient shader = new LinearGradient(0, 0, offsetWidth*2+progressWidth , 0, colors, null,  Shader.TileMode.CLAMP); mPaint.setShader(shader); //畫出漸變色進度條 canvas.drawLine(offsetWidth, offsetHeight, offsetWidth+section*progressWidth, offsetHeight, mPaint); //漸變色外圓 mPaint.setStrokeWidth(1); mPaint.setStyle(Paint.Style.FILL); canvas.drawCircle(offsetWidth+section * progressWidth, offsetHeight, outerCircleDiameter/2, mPaint); //繪制兩條斜線,使外圓到進度條的連接更自然 if(section*100>1.8){  mPaint.setStrokeWidth(2*unit);  canvas.drawLine(offsetWidth+section * progressWidth-6*unit, offsetHeight-(float)1.5*unit,    offsetWidth+section * progressWidth-1*unit,offsetHeight-(float)3.8*unit, mPaint);  canvas.drawLine(offsetWidth+section * progressWidth-6*unit, offsetHeight+(float)1.5*unit,    offsetWidth+section * progressWidth-1*unit,offsetHeight+(float)3.8*unit, mPaint); } //白色內圓 mPaint.setShader(null); mPaint.setColor(Color.WHITE); canvas.drawCircle(offsetWidth+section * progressWidth, offsetHeight, innerCircleDiameter/2, mPaint);//白色內圓 //繪制文字--百分比 mPaint.setStrokeWidth(2*unit); mPaint.setColor(textColor); mPaint.setTextSize(wordHeight); //計算坐標使文字居中 FontMetrics fontMetrics = mPaint.getFontMetrics();  float fontHeight = fontMetrics.bottom - fontMetrics.top; float baseY = height/2 + fontHeight/2 - fontMetrics.bottom; canvas.drawText(""+progressValue+"%", progressWidth+2*offsetWidth, baseY, mPaint);//略微偏下,baseline }}

主xml:

放了兩個進度條,一個使用默認值,一個設置了進度條默認顏色與字體顏色:

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:custom="http://schemas.android.com/apk/res/com.customview" android:layout_width="match_parent" android:layout_height="match_parent" > <com.customview.view.GoodProgressView android:id="@+id/good_progress_view1" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp"   />  <com.customview.view.GoodProgressView android:id="@+id/good_progress_view2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true"  custom:backgroundColor="#ffcccccc" custom:textColor="#ff000000" android:padding="10dp"   /> </RelativeLayout>

Activity文件:

一個使用默認漸變色效果,一個的漸變色使用隨機顏色,這樣每次運行效果不同,比較有趣一些,另外我們也可以從隨機效果中找到比較好的顏色組合。進度的變化,是使用了一個定時器來推進。

 

package com.customview;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.WindowManager;import java.util.Random;import java.util.Timer;import java.util.TimerTask;import com.customview.view.GoodProgressView;import android.app.Activity;import android.graphics.Color;public class MainActivity extends Activity{ GoodProgressView good_progress_view1; GoodProgressView good_progress_view2; int progressValue=0;  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);//去掉信息欄 setContentView(R.layout.activity_main); good_progress_view1 = (GoodProgressView)findViewById(R.id.good_progress_view1); good_progress_view2 = (GoodProgressView)findViewById(R.id.good_progress_view2); //第一個進度條使用默認進度顏色,第二個指定顏色(隨機生成) good_progress_view2.setColors(randomColors()); timer.schedule(task, 1000, 1000); // 1s后執行task,經過1s再次執行   } Handler handler = new Handler() {  public void handleMessage(Message msg) {   if (msg.what == 1) {   Log.i("log","handler : progressValue="+progressValue);  //通知view,進度值有變化  good_progress_view1.setProgressValue(progressValue*2);  good_progress_view1.postInvalidate();  good_progress_view2.setProgressValue(progressValue);  good_progress_view2.postInvalidate();  progressValue+=1;  if(progressValue>100){   timer.cancel();  }  }   super.handleMessage(msg);   };  };  private int[] randomColors() { int[] colors=new int[2]; Random random = new Random(); int r,g,b; for(int i=0;i<2;i++){  r=random.nextInt(256);  g=random.nextInt(256);  b=random.nextInt(256);  colors[i]=Color.argb(255, r, g, b);  Log.i("customView","log: colors["+i+"]="+Integer.toHexString(colors[i])); } return colors; } Timer timer = new Timer();  TimerTask task = new TimerTask() {  @Override  public void run() {   // 需要做的事:發送消息   Message message = new Message();   message.what = 1;   handler.sendMessage(message);  }  }; }

最終效果如下:

豎屏時:

Android,漸變色,進度條

橫屏時:

Android,漸變色,進度條

源碼下載:Android漸變色進度條

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 肃宁县| 普陀区| 瓦房店市| 宝清县| 汾西县| 甘孜县| 林州市| 福建省| 绥德县| 洛宁县| 兰考县| 左贡县| 太谷县| 喀喇沁旗| 富裕县| 洛浦县| 时尚| 临夏市| 衡阳市| 虹口区| 辽阳市| 宁陕县| 西林县| 梅州市| 惠水县| 勃利县| 博野县| 新民市| 海口市| 民勤县| 静乐县| 福建省| 河曲县| 永登县| 溆浦县| 陵川县| 郓城县| 嘉峪关市| 花莲市| 松滋市| 芦山县|