您好,登錄后才能下訂單哦!
這個進度條可以反映真實進度,并且完成百分比的文字時隨著進度增加而移動的,所在位置也恰好是真實完成的百分比位置,效果如下:
思路如下:第一部分是左側的藍色直線,代表已經完成的進度;第二部分是右側灰色的直線,代表未完成的進度;第三部分是紅色的百分比的數字百分比文本,顯示當前確切的完成進度。
最關鍵的部分就是要確定百分比文本的確切位置,這里用了paint的getTextBounds方法,得到文本的寬高,然后再精確確定它的位置。
view代碼如下:
public class NumberProgressView extends View { /** * 進度條畫筆的寬度(dp) */ private int paintProgressWidth = 3; /** * 文字百分比的字體大小(sp) */ private int paintTextSize = 20; /** * 左側已完成進度條的顏色 */ private int paintLeftColor = 0xff67aae4; /** * 右側未完成進度條的顏色 */ private int paintRightColor = 0xffaaaaaa; /** * 百分比文字的顏色 */ private int paintTextColor = 0xffff0077; /** * Contxt */ private Context context; /** * 主線程傳過來進程 0 - 100 */ private int progress; /** * 得到自定義視圖的寬度 */ private int viewWidth; /** * 得到自定義視圖的Y軸中心點 */ private int viewCenterY; /** * 畫左邊已完成進度條的畫筆 */ private Paint paintleft = new Paint(); /** * 畫右邊未完成進度條的畫筆 */ private Paint paintRight = new Paint(); /** * 畫中間的百分比文字的畫筆 */ private Paint paintText = new Paint(); /** * 要畫的文字的寬度 */ private int textWidth; /** * 畫文字時底部的坐標 */ private float textBottomY; /** * 包裹文字的矩形 */ private Rect rect = new Rect(); /** * 文字總共移動的長度(即從0%到100%文字左側移動的長度) */ private int totalMovedLength; public NumberProgressView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; // 構造器中初始化數據 initData(); } /** * 初始化數據 */ private void initData() { //設置進度條畫筆的寬度 int paintProgressWidthPx = Utils.dip2px(context, paintProgressWidth); //設置百分比文字的尺寸 int paintTextSizePx = Utils.sp2px(context, paintTextSize); // 已完成進度條畫筆的屬性 paintleft.setColor(paintLeftColor); paintleft.setStrokeWidth(paintProgressWidthPx); paintleft.setAntiAlias(true); paintleft.setStyle(Style.FILL); // 未完成進度條畫筆的屬性 paintRight.setColor(paintRightColor); paintRight.setStrokeWidth(paintProgressWidthPx); paintRight.setAntiAlias(true); paintRight.setStyle(Style.FILL); // 百分比文字畫筆的屬性 paintText.setColor(paintTextColor); paintText.setTextSize(paintTextSizePx); paintText.setAntiAlias(true); paintText.setTypeface(Typeface.DEFAULT_BOLD); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); getWidthAndHeight(); } /** * 得到視圖等的高度寬度尺寸數據 */ private void getWidthAndHeight() { //得到包圍文字的矩形的寬高 paintText.getTextBounds("000%", 0, "000%".length(), rect); textWidth = rect.width(); textBottomY = viewCenterY + rect.height() / 2; //得到自定義視圖的高度 int viewHeight = getMeasuredHeight(); viewWidth = getMeasuredWidth(); viewCenterY = viewHeight / 2; totalMovedLength = viewWidth - textWidth; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //得到float型進度 float progressFloat = progress / 100.0f; //當前文字移動的長度 float currentMovedLentgh = totalMovedLength * progressFloat; //畫左側已經完成的進度條,長度為從Veiw左端到文字的左側 canvas.drawLine(0, viewCenterY, currentMovedLentgh, viewCenterY, paintleft); //畫右側未完成的進度條,這個進度條的長度不是嚴格按照百分比來縮放的,因為文字的長度會變化,所以它的長度縮放比例也會變化 if (progress < 10) { canvas.drawLine(currentMovedLentgh + textWidth * 0.5f, viewCenterY, viewWidth, viewCenterY, paintRight); } else if (progress < 100) { canvas.drawLine(currentMovedLentgh + textWidth * 0.75f, viewCenterY, viewWidth, viewCenterY, paintRight); } else { canvas.drawLine(currentMovedLentgh + textWidth, viewCenterY, viewWidth, viewCenterY, paintRight); } //畫文字(注意:文字要最后畫,因為文字和進度條可能會有重合部分,所以要最后畫文字,用文字蓋住重合的部分) canvas.drawText(progress + "%", currentMovedLentgh, textBottomY, paintText); } /** * @param progress 外部傳進來的當前進度 */ public void setProgress(int progress) { this.progress = progress; invalidate(); } }
調用者activity的代碼,設置進度條的進度:
public class NumberProgressBarActivity extends Activity { protected static final int WHAT_INCREASE = 1; private NumberProgressView np_numberProgressBar; private int progress; private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { progress++; np_numberProgressBar.setProgress(progress); handler.sendEmptyMessageDelayed(WHAT_INCREASE, getRadomNumber(50, 200)); if (progress >= 100) { handler.removeMessages(WHAT_INCREASE); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_number_progress_bar); np_numberProgressBar = (NumberProgressView) findViewById(R.id.np_numberProgressBar); Button btn_numberProgressBar = (Button) findViewById(R.id.btn_numberProgressBar); btn_numberProgressBar.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { increase(); } }); } private void increase() { progress = 0; np_numberProgressBar.setProgress(0); handler.removeMessages(WHAT_INCREASE); handler.sendEmptyMessage(WHAT_INCREASE); } /** * 得到兩個整數之間的一個隨機數 * * @param start 較小的數 * @param end 較大的數 * @return */ public int getRadomNumber(int start, int end) { return (int) (start + Math.random() * (end - start)); } }
工具方法:
/** * 將dip或dp值轉換為px值,保證尺寸大小不變 */ public static int dip2px(Context context, float dipValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); } /** * 將sp值轉換為px值,保證文字大小不變 */ public static int sp2px(Context context, float spValue) { final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); }
布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.example.viewdemo.view.NumberProgressView android:id="@+id/np_numberProgressBar" android:layout_width="wrap_content" android:layout_height="100dp" android:layout_margin="20dp" android:background="#33890075" /> <Button android:id="@+id/btn_numberProgressBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="開始"/> </LinearLayout>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。