本文主要是介绍android 自定义 View(4)- 进度条(ProgressBar),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
参考:
Android 打造形形色色的进度条 实现可以如此简单
daimajia/NumberProgressBar
自定义视图(View
)是 Android
开发的一个进阶内容。随着开发的深入,肯定会出现系统提供的基础控件不符合需求的情况。一方面通过组合基础控件以形成新的布局,另一方面可以通过自定义控件的方式来更加灵活的实现需求
自定义视图涉及到 Android
系统许多方面的内容,下面根据自己的理解顺序来讲一讲如何自定义视图
主要内容
- 进度条浅析
- 水平进度条
- 文本进度条
- 圆形进度条
参考:ProgressBar
进度条是 Android
应用中经常使用的一种控件,在文件上传下载时,用进度条显示当前上传或者下载进度,更有利于用户体验
最简单的进度条应该就是一条线段,用两种颜色表示已完成和未完成,如果在线段上加上文本显示,更有利于说明当前进度,另外,还可以制作圆形进度条
水平进度条
学习 hongyang
的自定义进度条,利用 Android
内置的 ProgressBar
,重新绘制进度条。
下面实现最简单的水平进度条
水平进度条浅析
实现水平进度条,首先是确定进度条的颜色,可以先默认设置已完成和未完成进度条的颜色,然后利用控件 ProgressBar
的属性设置当前进度以及总进度值
通过自定义属性,可以设置颜色值
根据控件长宽属性,进行尺寸的重新测量,确定进度条的大小,实现更完善的水平进度条
实现进度条
新建 SimpleProgressbar.java
,继承 Android
控件 ProgressBar
,设置进度条的颜色,在 onDraw
方法中利用 ProgressBar
提供的属性 android:progress
设置当前进度
public class SimpleProgressbar extends ProgressBar {private static final String TAG = "SimpleProgressbar";public static final int DEFAULT_UNREACHED_COLOR = 0xFF912CEE;public static final int DEFAULT_REACHED_COLOR = 0xFF54FF9F;/*** 画笔*/private Paint paint;/*** 未到达进度条颜色*/private int unreachedColor;/*** 已到达进度条颜色*/private int reachedColor;public SimpleProgressbar(Context context) {// super(context);this(context, null);}public SimpleProgressbar(Context context, AttributeSet attrs) {// super(context, attrs);this(context, attrs, 0);}public SimpleProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);paint = new Paint();unreachedColor = DEFAULT_UNREACHED_COLOR;reachedColor = DEFAULT_REACHED_COLOR;}@Overrideprotected synchronized void onDraw(Canvas canvas) {// super.onDraw(canvas);// 获取画布的宽高int width = getWidth();int height = getHeight();// 获取进度条的实际宽高int lineWidth = width - getPaddingLeft() - getPaddingRight();int lineHeight = height - getPaddingTop() - getPaddingBottom();// 获取当前进度float ratio = getProgress() * 1.0f / getMax();// 获取未完成进度大小int unreachedWidth = (int) (lineWidth * (1 - ratio));// 获取已完成进度大小int reachedWidth = lineWidth - unreachedWidth;// 绘制已完成进度条,设置画笔颜色和大小paint.setColor(reachedColor);paint.setStrokeWidth(lineHeight);// 计算已完成进度条起点和终点的坐标int startX = getPaddingLeft();int startY = getHeight() / 2;int stopX = startX + reachedWidth;int stopY = startY;// 画线canvas.drawLine(startX, startY, stopX, stopY, paint);// 设置画笔颜色paint.setColor(unreachedColor);startX = getPaddingLeft() + reachedWidth;stopX = width - getPaddingRight();canvas.drawLine(startX, startY, stopX, stopY, paint);}}
布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.zj.progressnumber.MainActivity"><com.zj.progressnumber.SimpleProgressbarandroid:layout_width="match_parent"android:layout_height="30dp"android:layout_marginTop="30dp"android:background="@android:color/holo_orange_dark"android:padding="8dp"android:progress="30" /></android.support.design.widget.CoordinatorLayout>
每隔 500
毫秒增加进度条进度,实现如下:
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final SimpleProgressbar spb = (SimpleProgressbar) findViewById(R.id.spb);final int max = spb.getMax();new Thread(new Runnable() {@Overridepublic void run() {int progress = spb.getProgress();while ((progress + 1) <= max) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}spb.setProgress(progress + 1);progress = progress + 1;}}}).start();}
}
自定义进度条颜色
自定义已完成进度条和未完成进度条的颜色
<?xml version="1.0" encoding="utf-8"?>
<resources><attr name="reachedColor" format="color" /><attr name="unreachedColor" format="color" /><declare-styleable name="SimpleProgressbar"><attr name="reachedColor" /><attr name="unreachedColor" /></declare-styleable></resources>
修改 SimpleProgressbar.java
,增加自定义属性的查询:
public class SimpleProgressbar extends ProgressBar {private static final String TAG = "SimpleProgressbar";......public SimpleProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);...obtainStyledAttributes(context, attrs, defStyleAttr);}......private void obtainStyledAttributes(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SimpleProgressbar, defStyleAttr, 0);int count = a.getIndexCount();for (int i = 0; i < count; i++) {int attr = a.getIndex(i);switch (attr) {case R.styleable.SimpleProgressbar_reachedColor:reachedColor = a.getColor(attr, DEFAULT_REACHED_COLOR);break;case R.styleable.SimpleProgressbar_unreachedColor:unreachedColor = a.getColor(attr, DEFAULT_UNREACHED_COLOR);break;}}a.recycle();}
}
修改布局文件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:custom="http://schemas.android.com/apk/res/com.zj.progressnumber"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.zj.progressnumber.MainActivity"><com.zj.progressnumber.SimpleProgressbarandroid:id="@+id/spb"android:layout_width="match_parent"android:layout_height="30dp"android:layout_marginTop="30dp"android:background="@android:color/holo_orange_dark"android:padding="8dp"android:progress="30"custom:reachedColor="@android:color/holo_green_light"custom:unreachedColor="@android:color/holo_blue_light"/></android.support.design.widget.CoordinatorLayout>
修改程序,随机增加进度:
public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final SimpleProgressbar spb = (SimpleProgressbar) findViewById(R.id.spb);final int max = spb.getMax();new Thread(new Runnable() {@Overridepublic void run() {int progress = spb.getProgress();int random = (int) (Math.random() * 10) + 1;random = (progress + random) <= max ? random : (max - progress);while ((progress + random) <= max) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}progress = progress + random;spb.setProgress(progress);if (progress == max)break;random = (int) (Math.random() * 10) + 1;random = (progress + random) <= max ? random : (max - progress);}}}).start();}
}
设定进度条宽高
在上面的代码中,如果进度条宽高设定为 wrap_content
模式,无法正常显示,修改代码,设定最小的宽和高
完整代码如下:
public class SimpleProgressbar extends ProgressBar {private static final String TAG = "SimpleProgressbar";public static final int DEFAULT_UNREACHED_COLOR = 0xFF912CEE;public static final int DEFAULT_REACHED_COLOR = 0xFF54FF9F;// 进度条默认高,单位为 dppublic static final int DEFAULT_LINE_HEIGHT = 2;// 进度条默认宽,单位为 dppublic static final int DEFAULT_LINE_WIDTH = 100;/*** 画笔*/private Paint paint;/*** 未到达进度条颜色*/private int unreachedColor;/*** 已到达进度条颜色*/private int reachedColor;/*** 默认进度条最小的高(不含内边距)*/private int minLineHeight;/*** 默认进度条最小的宽(不含内边距)*/private int minLineWidth;/*** 实际使用的进度条的高(不含内边距)*/private int lineHeight;/*** 实际使用的进度条的宽(不含内边距)*/private int lineWidth;public SimpleProgressbar(Context context) {// super(context);this(context, null);}public SimpleProgressbar(Context context, AttributeSet attrs) {// super(context, attrs);this(context, attrs, 0);}public SimpleProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);paint = new Paint();unreachedColor = DEFAULT_UNREACHED_COLOR;reachedColor = DEFAULT_REACHED_COLOR;minLineHeight = dp2px(DEFAULT_LINE_HEIGHT);minLineWidth = dp2px(DEFAULT_LINE_WIDTH);obtainStyledAttributes(context, attrs, defStyleAttr);}@Overrideprotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int desiredWidth = minLineWidth + getPaddingLeft() + getPaddingRight();int desiredHeight = minLineHeight + getPaddingTop() + getPaddingBottom();int width;int height;if (widthMode == MeasureSpec.AT_MOST) {width = Math.min(widthSize, desiredWidth);} else {width = Math.max(widthSize, desiredWidth);}if (heightMode == MeasureSpec.AT_MOST) {height = Math.min(heightSize, desiredHeight);} else {height = Math.max(heightSize, desiredHeight);}setMeasuredDimension(width, height);}@Overrideprotected synchronized void onDraw(Canvas canvas) {// super.onDraw(canvas);// 获取画布的宽高int width = getWidth();int height = getHeight();// 获取进度条的实际宽高int lineWidth = width - getPaddingLeft() - getPaddingRight();int lineHeight = height - getPaddingTop() - getPaddingBottom();// 获取当前进度float ratio = getProgress() * 1.0f / getMax();// 获取未完成进度大小int unreachedWidth = (int) (lineWidth * (1 - ratio));// 获取已完成进度大小int reachedWidth = lineWidth - unreachedWidth;// 绘制已完成进度条,设置画笔颜色和大小paint.setColor(reachedColor);paint.setStrokeWidth(lineHeight);// 计算已完成进度条起点和终点的坐标int startX = getPaddingLeft();int startY = getHeight() / 2;int stopX = startX + reachedWidth;int stopY = startY;// 画线canvas.drawLine(startX, startY, stopX, stopY, paint);// 设置画笔颜色paint.setColor(unreachedColor);startX = getPaddingLeft() + reachedWidth;stopX = width - getPaddingRight();canvas.drawLine(startX, startY, stopX, stopY, paint);}private void obtainStyledAttributes(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SimpleProgressbar, defStyleAttr, 0);int count = a.getIndexCount();for (int i = 0; i < count; i++) {int attr = a.getIndex(i);switch (attr) {case R.styleable.SimpleProgressbar_reachedColor:reachedColor = a.getColor(attr, DEFAULT_REACHED_COLOR);break;case R.styleable.SimpleProgressbar_unreachedColor:unreachedColor = a.getColor(attr, DEFAULT_UNREACHED_COLOR);break;}}a.recycle();}/*** dp 2 px** @param dpVal*/protected int dp2px(int dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal, getResources().getDisplayMetrics());}
}
文本进度条
上面已实现了水平进度条,如果要在进度条上增加文本,需要考虑以下几点:
- 如何平衡文本和进度条的大小
- 如果插入文本
思路:判断文本的高和进度条的高,设置更大的值为文本进度条的高;文本值从 0%
变化到 100%
,在水平进度条上固定预留出文本显示最大值的宽
首先还是先把文本进度条画出来,实现如下,新建 ZProgressbar.java
:
public class ZProgressbar extends ProgressBar {private static final String TAG = "SimpleProgressbar";public static final int DEFAULT_UNREACHED_COLOR = 0xFF7D9EC0;public static final int DEFAULT_REACHED_COLOR = 0xFFC1FFC1;public static final int DEFAULT_TEXT_COLOR = 0xFF0000CD;public static final String DEFAULT_TEXT = "100%";// 进度条默认高,单位为 dppublic static final int DEFAULT_LINE_HEIGHT = 2;// 进度条默认宽,单位为 dppublic static final int DEFAULT_LINE_WIDTH = 100;// 文本大小,单位为 sppublic static final int DEFAULT_TEXT_SIZE = 12;private Paint paint;private Rect textBound;private int reachedColor;private int unreachedColor;private int textColor;private int lineHeight;private int minLineHeight;private int minLineWidth;private int textSize;private int textHeight;private int textWidth;public ZProgressbar(Context context) {// super(context);this(context, null);}public ZProgressbar(Context context, AttributeSet attrs) {// super(context, attrs);this(context, attrs, 0);}public ZProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);paint = new Paint();textBound = new Rect();unreachedColor = DEFAULT_UNREACHED_COLOR;reachedColor = DEFAULT_REACHED_COLOR;textColor = DEFAULT_TEXT_COLOR;minLineHeight = dp2px(DEFAULT_LINE_HEIGHT);minLineWidth = dp2px(DEFAULT_LINE_WIDTH);textSize = sp2px(DEFAULT_TEXT_SIZE);// 计算文本的宽和高paint.setTextSize(textSize);paint.getTextBounds(DEFAULT_TEXT, 0, DEFAULT_TEXT.length(), textBound);textWidth = textBound.width();textHeight = textBound.height();}@Overrideprotected synchronized void onDraw(Canvas canvas) {// super.onDraw(canvas);int width = getWidth();int height = getHeight();int contentWidth = width - getPaddingLeft() - getPaddingRight();lineHeight = height - getPaddingTop() - getPaddingBottom();float ratio = getProgress() * 1.0f / getMax();int unreachedWidth = (int) ((contentWidth - textWidth) * (1 - ratio));int reachedWidth = contentWidth - textWidth - unreachedWidth;paint.setColor(reachedColor);paint.setStrokeWidth(lineHeight);int startX = getPaddingLeft();int startY = height / 2;int stopX = getPaddingLeft() + reachedWidth;int stopY = height / 2;canvas.drawLine(startX, startY, stopX, stopY, paint);String currentText = getProgress() + "%";paint.getTextBounds(currentText, 0, currentText.length(), textBound);paint.setColor(textColor);paint.setTextSize(textSize);startX = getPaddingLeft() + reachedWidth + (textWidth - textBound.width()) / 2;Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();startY = (height - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;canvas.drawText(currentText, startX, startY, paint);paint.setColor(unreachedColor);paint.setStrokeWidth(lineHeight);startX = getPaddingLeft() + reachedWidth + textWidth;startY = height / 2;stopX = width - getPaddingRight();stopY = height / 2;canvas.drawLine(startX, startY, stopX, stopY, paint);}/*** dp 2 px** @param dpVal*/protected int dp2px(int dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal, getResources().getDisplayMetrics());}/*** sp 2 px** @param spVal* @return*/protected int sp2px(int spVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,spVal, getResources().getDisplayMetrics());}
}
布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:custom="http://schemas.android.com/apk/res/com.zj.progressnumber"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="8dp"tools:context="com.zj.progressnumber.MainActivity"><com.zj.progressnumber.ZProgressbarandroid:id="@+id/zpb"android:layout_width="match_parent"android:layout_height="30dp"android:layout_marginTop="100dp"android:progress="10" /></android.support.design.widget.CoordinatorLayout>
程序实现如下:
接下里增加尺寸测量部分:
public class ZProgressbar extends ProgressBar {private static final String TAG = "SimpleProgressbar";public static final int DEFAULT_UNREACHED_COLOR = 0xFF7D9EC0;public static final int DEFAULT_REACHED_COLOR = 0xFFC1FFC1;public static final int DEFAULT_TEXT_COLOR = 0xFF0000CD;public static final String DEFAULT_TEXT = "100%";// 进度条默认高,单位为 dppublic static final int DEFAULT_LINE_HEIGHT = 2;// 进度条默认宽,单位为 dppublic static final int DEFAULT_LINE_WIDTH = 100;// 文本大小,单位为 sppublic static final int DEFAULT_TEXT_SIZE = 12;private Paint paint;private Rect textBound;private int reachedColor;private int unreachedColor;private int textColor;private int lineHeight;private int minLineHeight;private int minLineWidth;private int textSize;private int textHeight;private int textWidth;public ZProgressbar(Context context) {// super(context);this(context, null);}public ZProgressbar(Context context, AttributeSet attrs) {// super(context, attrs);this(context, attrs, 0);}public ZProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);paint = new Paint();textBound = new Rect();unreachedColor = DEFAULT_UNREACHED_COLOR;reachedColor = DEFAULT_REACHED_COLOR;textColor = DEFAULT_TEXT_COLOR;minLineHeight = dp2px(DEFAULT_LINE_HEIGHT);minLineWidth = dp2px(DEFAULT_LINE_WIDTH);textSize = sp2px(DEFAULT_TEXT_SIZE);}@Overrideprotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);// 计算文本的宽和高paint.setTextSize(textSize);paint.getTextBounds(DEFAULT_TEXT, 0, DEFAULT_TEXT.length(), textBound);textWidth = textBound.width();textHeight = textBound.height();// 比较文本的高和线段的高int minHeight = textHeight > minLineHeight ? textHeight : minLineHeight;int desiredWidth = minLineWidth + getPaddingLeft() + getPaddingRight();int desiredHeight = minHeight + getPaddingTop() + getPaddingBottom();int width;int height;if (widthMode == MeasureSpec.AT_MOST) {width = desiredWidth;} else {width = Math.max(widthSize, desiredWidth);}if (heightMode == MeasureSpec.AT_MOST) {height = desiredHeight;lineHeight = minLineHeight;} else {height = Math.max(heightSize, desiredHeight);lineHeight = height - getPaddingLeft() - getPaddingRight();}setMeasuredDimension(width, height);}@Overrideprotected synchronized void onDraw(Canvas canvas) {// super.onDraw(canvas);int width = getWidth();int height = getHeight();int contentWidth = width - getPaddingLeft() - getPaddingRight();float ratio = getProgress() * 1.0f / getMax();int unreachedWidth = (int) ((contentWidth - textWidth) * (1 - ratio));int reachedWidth = contentWidth - textWidth - unreachedWidth;paint.setColor(reachedColor);paint.setStrokeWidth(lineHeight);int startX = getPaddingLeft();int startY = height / 2;int stopX = getPaddingLeft() + reachedWidth;int stopY = height / 2;canvas.drawLine(startX, startY, stopX, stopY, paint);String currentText = getProgress() + "%";paint.getTextBounds(currentText, 0, currentText.length(), textBound);paint.setColor(textColor);paint.setTextSize(textSize);startX = getPaddingLeft() + reachedWidth + (textWidth - textBound.width()) / 2;Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();startY = (height - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;canvas.drawText(currentText, startX, startY, paint);paint.setColor(unreachedColor);paint.setStrokeWidth(lineHeight);startX = getPaddingLeft() + reachedWidth + textWidth;startY = height / 2;stopX = width - getPaddingRight();stopY = height / 2;canvas.drawLine(startX, startY, stopX, stopY, paint);}/*** dp 2 px** @param dpVal*/protected int dp2px(int dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal, getResources().getDisplayMetrics());}/*** sp 2 px** @param spVal* @return*/protected int sp2px(int spVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,spVal, getResources().getDisplayMetrics());}
}
最后增加自定义属性,控制文本颜色,进度条颜色,文本大小以及是否显示文本
完整代码如下:
public class ZProgressbar extends ProgressBar {private static final String TAG = "SimpleProgressbar";public static final int DEFAULT_UNREACHED_COLOR = 0xFF7D9EC0;public static final int DEFAULT_REACHED_COLOR = 0xFFC1FFC1;public static final int DEFAULT_TEXT_COLOR = 0xFF0000CD;public static final String DEFAULT_TEXT = "100%";// 进度条默认高,单位为 dppublic static final int DEFAULT_LINE_HEIGHT = 2;// 进度条默认宽,单位为 dppublic static final int DEFAULT_LINE_WIDTH = 100;// 文本大小,单位为 sppublic static final int DEFAULT_TEXT_SIZE = 8;private Paint paint;private Rect textBound;private int reachedColor;private int unreachedColor;private int textColor;private int lineHeight;private int minLineHeight;private int minLineWidth;private int textSize;private int textHeight;private int textWidth;private boolean isShowText;public ZProgressbar(Context context) {// super(context);this(context, null);}public ZProgressbar(Context context, AttributeSet attrs) {// super(context, attrs);this(context, attrs, 0);}public ZProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);paint = new Paint();textBound = new Rect();unreachedColor = DEFAULT_UNREACHED_COLOR;reachedColor = DEFAULT_REACHED_COLOR;textColor = DEFAULT_TEXT_COLOR;minLineHeight = dp2px(DEFAULT_LINE_HEIGHT);minLineWidth = dp2px(DEFAULT_LINE_WIDTH);textSize = sp2px(DEFAULT_TEXT_SIZE);isShowText = true;obtainStyledAttributes(context, attrs, defStyleAttr);}@Overrideprotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);// 计算文本的宽和高paint.setTextSize(textSize);paint.getTextBounds(DEFAULT_TEXT, 0, DEFAULT_TEXT.length(), textBound);textWidth = textBound.width();textHeight = textBound.height();int minHeight = minLineHeight;if (isShowText) {// 比较文本的高和线段的高minHeight = textHeight > minLineHeight ? textHeight : minLineHeight;}int desiredWidth = minLineWidth + getPaddingLeft() + getPaddingRight();int desiredHeight = minHeight + getPaddingTop() + getPaddingBottom();int width;int height;if (widthMode == MeasureSpec.AT_MOST) {width = desiredWidth;} else {width = Math.max(widthSize, desiredWidth);}if (heightMode == MeasureSpec.AT_MOST) {height = desiredHeight;lineHeight = minLineHeight;} else {height = Math.max(heightSize, desiredHeight);lineHeight = height - getPaddingLeft() - getPaddingRight();}setMeasuredDimension(width, height);}@Overrideprotected synchronized void onDraw(Canvas canvas) {// super.onDraw(canvas);int width = getWidth();int height = getHeight();int contentWidth = width - getPaddingLeft() - getPaddingRight();if (isShowText) {float ratio = getProgress() * 1.0f / getMax();int unreachedWidth = (int) ((contentWidth - textWidth) * (1 - ratio));int reachedWidth = contentWidth - textWidth - unreachedWidth;paint.setColor(reachedColor);paint.setStrokeWidth(lineHeight);int startX = getPaddingLeft();int startY = height / 2;int stopX = getPaddingLeft() + reachedWidth;int stopY = height / 2;canvas.drawLine(startX, startY, stopX, stopY, paint);String currentText = getProgress() + "%";paint.getTextBounds(currentText, 0, currentText.length(), textBound);paint.setColor(textColor);paint.setTextSize(textSize);startX = getPaddingLeft() + reachedWidth + (textWidth - textBound.width()) / 2;Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();startY = (height - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;canvas.drawText(currentText, startX, startY, paint);paint.setColor(unreachedColor);paint.setStrokeWidth(lineHeight);startX = getPaddingLeft() + reachedWidth + textWidth;startY = height / 2;stopX = width - getPaddingRight();stopY = height / 2;canvas.drawLine(startX, startY, stopX, stopY, paint);} else {float ratio = getProgress() * 1.0f / getMax();int unreachedWidth = (int) (contentWidth * (1 - ratio));int reachedWidth = contentWidth - unreachedWidth;paint.setColor(reachedColor);paint.setStrokeWidth(lineHeight);int startX = getPaddingLeft();int startY = height / 2;int stopX = getPaddingLeft() + reachedWidth;int stopY = height / 2;canvas.drawLine(startX, startY, stopX, stopY, paint);paint.setColor(unreachedColor);paint.setStrokeWidth(lineHeight);startX = getPaddingLeft() + reachedWidth;startY = height / 2;stopX = width - getPaddingRight();stopY = height / 2;canvas.drawLine(startX, startY, stopX, stopY, paint);}}private void obtainStyledAttributes(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ZProgressbar, defStyleAttr, 0);int count = a.getIndexCount();for (int i = 0; i < count; i++) {int attr = a.getIndex(i);switch (attr) {case R.styleable.ZProgressbar_reachedColor:reachedColor = a.getColor(attr, DEFAULT_REACHED_COLOR);break;case R.styleable.ZProgressbar_unreachedColor:unreachedColor = a.getColor(attr, DEFAULT_UNREACHED_COLOR);break;case R.styleable.ZProgressbar_textColor:textColor = a.getColor(attr, DEFAULT_TEXT_COLOR);break;case R.styleable.ZProgressbar_textSize:textSize = sp2px((int) a.getDimension(attr, DEFAULT_TEXT_SIZE));break;case R.styleable.ZProgressbar_isShowText:isShowText = a.getBoolean(attr, true);break;}}a.recycle();}/*** dp 2 px** @param dpVal*/protected int dp2px(int dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal, getResources().getDisplayMetrics());}/*** sp 2 px** @param spVal* @return*/protected int sp2px(int spVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,spVal, getResources().getDisplayMetrics());}
}
资源文件如下:
<?xml version="1.0" encoding="utf-8"?>
<resources><attr name="reachedColor" format="color" /><attr name="unreachedColor" format="color" /><attr name="textSize" format="dimension" /><attr name="textColor" format="color" /><attr name="isShowText" format="boolean" /><declare-styleable name="SimpleProgressbar"><attr name="reachedColor" /><attr name="unreachedColor" /></declare-styleable><declare-styleable name="ZProgressbar"><attr name="reachedColor" /><attr name="unreachedColor" /><attr name="textSize" /><attr name="textColor" /><attr name="isShowText" /></declare-styleable></resources>
布局如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="8dp"tools:context="com.zj.progressnumber.MainActivity"><com.zj.progressnumber.SimpleProgressbarandroid:id="@+id/spb"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="50dp"android:background="@android:color/holo_green_light"android:padding="8dp"android:progress="10"app:reachedColor="@android:color/holo_orange_light"app:unreachedColor="@color/colorAccent" /><com.zj.progressnumber.ZProgressbarandroid:id="@+id/zpb"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="100dp"android:background="@android:color/holo_green_light"android:padding="8dp"android:progress="10"app:reachedColor="@color/colorPrimary"app:textColor="@android:color/holo_orange_dark"app:unreachedColor="@color/colorAccent" /></android.support.design.widget.CoordinatorLayout>
程序如下:
public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final SimpleProgressbar spb = (SimpleProgressbar) findViewById(R.id.spb);addProgress(spb);ZProgressbar zpb = (ZProgressbar) findViewById(R.id.zpb);addProgress(zpb);}private void addProgress(final ProgressBar spb) {final int max = spb.getMax();new Thread(new Runnable() {@Overridepublic void run() {int progress = spb.getProgress();int random = (int) (Math.random() * 10) + 1;random = (progress + random) <= max ? random : (max - progress);while ((progress + random) <= max) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}progress = progress + random;spb.setProgress(progress);if (progress == max)break;random = (int) (Math.random() * 10) + 1;random = (progress + random) <= max ? random : (max - progress);}}}).start();}
}
圆形进度条
画圆形进度条,需要绘制 3
个部分:圆,圆弧,文本
其中 圆 表示进度条,圆弧 表示当前进度,文本 显示在圆中间
最简单的圆形进度条
老规矩,先实现最简单的圆形进度条:圆和圆弧。新建 RoundProgressbar.java
:
public class RoundProgressbar extends ProgressBar {/*** 画笔*/private Paint paint;/*** 绘制圆弧时使用*/private RectF rectF;/*** 圆半径*/int radius;/*** 圆心横坐标*/int centerX;/*** 圆心纵坐标*/int centerY;public RoundProgressbar(Context context) {
// super(context);this(context, null);}public RoundProgressbar(Context context, AttributeSet attrs) {
// super(context, attrs);this(context, attrs, 0);}public RoundProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);paint = new Paint();// 设置画笔宽度为 30 像素paint.setStrokeWidth(30);rectF = new RectF();}@Overrideprotected synchronized void onDraw(Canvas canvas) {
// super.onDraw(canvas);int width = getWidth();int height = getHeight();int contentWidth = width - getPaddingLeft() - getPaddingRight();int contentHeight = height - getPaddingTop() - getPaddingBottom();// 设置圆心为画布正中心radius = contentWidth >= contentHeight ? contentWidth / 2 : contentHeight / 2;centerX = width / 2;centerY = height / 2;// 仅绘制边paint.setStyle(Paint.Style.STROKE);paint.setColor(Color.BLUE);canvas.drawCircle(centerX, centerY, radius, paint);rectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);float ratio = getProgress() * 1.0f / getMax();int angle = (int) (ratio * 360);paint.setColor(Color.RED);paint.setStyle(Paint.Style.STROKE);canvas.drawArc(rectF, 0, angle, false, paint);}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="8dp"tools:context="com.zj.progressnumber.MainActivity"><com.zj.progressnumber.RoundProgressbarandroid:id="@+id/rpb"android:layout_width="200dp"android:layout_height="200dp"android:background="@android:color/holo_green_light"android:progress="50"android:padding="20dp" /></android.support.design.widget.CoordinatorLayout>
实现:
自定义属性和尺寸测量
在上面的基础上增加画笔宽度的自定义属性,以及进行尺寸测量
public class RoundProgressbar extends ProgressBar {// 设置默认圆大小,单位为 dppublic static final int DEFAULT_RADIUS = 30;// 设置默认画笔宽度,单位为 dppublic static final int DEFAULT_STROKE_WIDTH = 1;/*** 画笔*/private Paint paint;/*** 绘制圆弧时使用*/private RectF rectF;/*** 圆半径*/int radius;/*** 圆心横坐标*/int centerX;/*** 圆心纵坐标*/int centerY;/*** 画笔宽度*/int paintWidth;public RoundProgressbar(Context context) {
// super(context);this(context, null);}public RoundProgressbar(Context context, AttributeSet attrs) {
// super(context, attrs);this(context, attrs, 0);}public RoundProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);paint = new Paint();rectF = new RectF();radius = dp2px(DEFAULT_RADIUS);paintWidth = dp2px(DEFAULT_STROKE_WIDTH);obtainStyledAttributes(context, attrs, defStyleAttr);}@Overrideprotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int desiredWidth = radius * 2 + getPaddingLeft() + getPaddingRight();int desiredHeight = radius * 2 + getTop() + getBottom();int width;int height;if (widthMode == MeasureSpec.AT_MOST) {width = desiredWidth;} else {width = Math.max(widthSize, desiredWidth);}if (heightMode == MeasureSpec.AT_MOST) {height = desiredHeight;} else {height = Math.max(heightSize, desiredHeight);}setMeasuredDimension(width, height);}@Overrideprotected synchronized void onDraw(Canvas canvas) {
// super.onDraw(canvas);int width = getWidth();int height = getHeight();int contentWidth = width - getPaddingLeft() - getPaddingRight();int contentHeight = height - getPaddingTop() - getPaddingBottom();// 设置圆心为画布正中心radius = contentWidth >= contentHeight ? contentHeight / 2 : contentWidth / 2;centerX = width / 2;centerY = height / 2;// 仅绘制边paint.setStyle(Paint.Style.STROKE);paint.setColor(Color.BLUE);paint.setStrokeWidth(paintWidth);canvas.drawCircle(centerX, centerY, radius, paint);rectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);float ratio = getProgress() * 1.0f / getMax();int angle = (int) (ratio * 360);paint.setColor(Color.RED);paint.setStyle(Paint.Style.STROKE);canvas.drawArc(rectF, 0, angle, false, paint);}private void obtainStyledAttributes(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RoundProgressbar, defStyleAttr, 0);int count = a.getIndexCount();for (int i = 0; i < count; i++) {int attr = a.getIndex(i);switch (attr) {case R.styleable.RoundProgressbar_strokeWidth:paintWidth = dp2px((int) a.getDimension(attr, DEFAULT_STROKE_WIDTH));break;}}a.recycle();}/*** dp 2 px** @param dpVal*/protected int dp2px(int dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal, getResources().getDisplayMetrics());}
}
属性文件:
<?xml version="1.0" encoding="utf-8"?>
<resources><attr name="strokeWidth" format="dimension" /><declare-styleable name="RoundProgressbar"><attr name="strokeWidth" /></declare-styleable></resources>
布局文件:
<com.zj.progressnumber.RoundProgressbarandroid:id="@+id/rpb"android:layout_width="300dp"android:layout_height="300dp"android:background="@android:color/holo_green_light"android:padding="20dp"android:progress="20"app:strokeWidth="1dp" />
实现:
增加文本
在圆中心增加文本显示
public class RoundProgressbar extends ProgressBar {public static final int DEFAULT_UNREACHED_COLOR = 0;public static final int DEFAULT_REACHED_COLOR = 0;public static final int DEFAULT_TEXT_COLOR = 0;// 设置默认圆大小,单位为 dppublic static final int DEFAULT_RADIUS = 60;// 设置默认画笔宽度,单位为 dppublic static final int DEFAULT_STROKE_WIDTH = 1;// 设置文字默认大小,单位为 sppublic static final int DEFAULT_TEXT_SIZE = 12;/*** 画笔*/private Paint paint;/*** 绘制圆弧时使用*/private RectF rectF;/*** 文字大小*/private Rect rect;/*** 圆半径*/int radius;/*** 圆心横坐标*/int centerX;/*** 圆心纵坐标*/int centerY;/*** 画笔宽度*/int paintWidth;/*** 文字大小*/int textSize;public RoundProgressbar(Context context) {
// super(context);this(context, null);}public RoundProgressbar(Context context, AttributeSet attrs) {
// super(context, attrs);this(context, attrs, 0);}public RoundProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);paint = new Paint();rectF = new RectF();rect = new Rect();radius = dp2px(DEFAULT_RADIUS);paintWidth = dp2px(DEFAULT_STROKE_WIDTH);textSize = sp2px(DEFAULT_TEXT_SIZE);obtainStyledAttributes(context, attrs, defStyleAttr);}@Overrideprotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int desiredWidth = radius * 2 + getPaddingLeft() + getPaddingRight();int desiredHeight = radius * 2 + getTop() + getBottom();int width;int height;if (widthMode == MeasureSpec.AT_MOST) {width = desiredWidth;} else {width = Math.max(widthSize, desiredWidth);}if (heightMode == MeasureSpec.AT_MOST) {height = desiredHeight;} else {height = Math.max(heightSize, desiredHeight);}setMeasuredDimension(width, height);}@Overrideprotected synchronized void onDraw(Canvas canvas) {
// super.onDraw(canvas);int width = getWidth();int height = getHeight();int contentWidth = width - getPaddingLeft() - getPaddingRight();int contentHeight = height - getPaddingTop() - getPaddingBottom();// 设置圆心为画布正中心radius = contentWidth >= contentHeight ? contentHeight / 2 : contentWidth / 2;centerX = width / 2;centerY = height / 2;// 仅绘制边paint.setStyle(Paint.Style.STROKE);paint.setColor(Color.BLUE);paint.setStrokeWidth(paintWidth);canvas.drawCircle(centerX, centerY, radius, paint);rectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);float ratio = getProgress() * 1.0f / getMax();int angle = (int) (ratio * 360);paint.setColor(Color.RED);paint.setStyle(Paint.Style.STROKE);canvas.drawArc(rectF, 0, angle, false, paint);String text = getProgress() + "%";paint.setStyle(Paint.Style.FILL);paint.setTextSize(textSize);paint.getTextBounds(text, 0, text.length(), rect);int startX = centerX - rect.width() / 2;Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();int startY = (height - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;canvas.drawText(text, startX, startY, paint);}private void obtainStyledAttributes(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RoundProgressbar, defStyleAttr, 0);int count = a.getIndexCount();for (int i = 0; i < count; i++) {int attr = a.getIndex(i);switch (attr) {case R.styleable.RoundProgressbar_strokeWidth:paintWidth = dp2px((int) a.getDimension(attr, DEFAULT_STROKE_WIDTH));break;case R.styleable.RoundProgressbar_textSize:textSize = sp2px((int) (a.getDimension(attr, DEFAULT_TEXT_SIZE)));break;}}a.recycle();}/*** dp 2 px** @param dpVal*/protected int dp2px(int dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal, getResources().getDisplayMetrics());}/*** sp 2 px** @param spVal* @return*/protected int sp2px(int spVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,spVal, getResources().getDisplayMetrics());}
}
增加了自定义属性 - 文字大小:
<?xml version="1.0" encoding="utf-8"?>
<resources><attr name="textSize" format="dimension" /><attr name="strokeWidth" format="dimension" /><declare-styleable name="RoundProgressbar"><attr name="strokeWidth" /><attr name="textSize" /></declare-styleable></resources>
实现:
完善
目前,圆形进度条已实现进度显示和文本显示,下面增加自定义属性,可以自定义颜色
完整代码如下:
public class RoundProgressbar extends ProgressBar {public static final int DEFAULT_UNREACHED_COLOR = 0xFF6495ED;public static final int DEFAULT_REACHED_COLOR = 0xFFFF0000;public static final int DEFAULT_TEXT_COLOR = 0xFF0000CD;// 设置默认圆大小,单位为 dppublic static final int DEFAULT_RADIUS = 60;// 设置默认画笔宽度,单位为 dppublic static final int DEFAULT_STROKE_WIDTH = 1;// 设置文字默认大小,单位为 sppublic static final int DEFAULT_TEXT_SIZE = 12;private Paint paint;private RectF rectF;private Rect rect;int radius;int centerX;int centerY;int unreachedColor;int reachedColor;int textColor;int paintWidth;int textSize;public RoundProgressbar(Context context) {
// super(context);this(context, null);}public RoundProgressbar(Context context, AttributeSet attrs) {
// super(context, attrs);this(context, attrs, 0);}public RoundProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);paint = new Paint();rectF = new RectF();rect = new Rect();radius = dp2px(DEFAULT_RADIUS);paintWidth = dp2px(DEFAULT_STROKE_WIDTH);textSize = sp2px(DEFAULT_TEXT_SIZE);unreachedColor = DEFAULT_UNREACHED_COLOR;reachedColor = DEFAULT_REACHED_COLOR;textColor = DEFAULT_TEXT_COLOR;obtainStyledAttributes(context, attrs, defStyleAttr);}@Overrideprotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int desiredWidth = radius * 2 + getPaddingLeft() + getPaddingRight();int desiredHeight = radius * 2 + getTop() + getBottom();int width;int height;if (widthMode == MeasureSpec.AT_MOST) {width = desiredWidth;} else {width = Math.max(widthSize, desiredWidth);}if (heightMode == MeasureSpec.AT_MOST) {height = desiredHeight;} else {height = Math.max(heightSize, desiredHeight);}setMeasuredDimension(width, height);}@Overrideprotected synchronized void onDraw(Canvas canvas) {
// super.onDraw(canvas);int width = getWidth();int height = getHeight();int contentWidth = width - getPaddingLeft() - getPaddingRight();int contentHeight = height - getPaddingTop() - getPaddingBottom();// 设置圆心为画布正中心radius = contentWidth >= contentHeight ? contentHeight / 2 : contentWidth / 2;centerX = width / 2;centerY = height / 2;// 仅绘制边paint.setStyle(Paint.Style.STROKE);paint.setColor(unreachedColor);paint.setStrokeWidth(paintWidth);canvas.drawCircle(centerX, centerY, radius, paint);rectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);float ratio = getProgress() * 1.0f / getMax();int angle = (int) (ratio * 360);paint.setColor(reachedColor);paint.setStyle(Paint.Style.STROKE);canvas.drawArc(rectF, 0, angle, false, paint);String text = getProgress() + "%";paint.setColor(textColor);paint.setStyle(Paint.Style.FILL);paint.setTextSize(textSize);paint.getTextBounds(text, 0, text.length(), rect);int startX = centerX - rect.width() / 2;Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();int startY = (height - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;canvas.drawText(text, startX, startY, paint);}private void obtainStyledAttributes(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RoundProgressbar, defStyleAttr, 0);int count = a.getIndexCount();for (int i = 0; i < count; i++) {int attr = a.getIndex(i);switch (attr) {case R.styleable.RoundProgressbar_strokeWidth:paintWidth = dp2px((int) a.getDimension(attr, DEFAULT_STROKE_WIDTH));break;case R.styleable.RoundProgressbar_textSize:textSize = sp2px((int) (a.getDimension(attr, DEFAULT_TEXT_SIZE)));break;case R.styleable.RoundProgressbar_unreachedColor:unreachedColor = a.getColor(attr, DEFAULT_UNREACHED_COLOR);break;case R.styleable.RoundProgressbar_reachedColor:reachedColor = a.getColor(attr, DEFAULT_REACHED_COLOR);break;case R.styleable.RoundProgressbar_textColor:textColor = a.getColor(attr, DEFAULT_TEXT_COLOR);break;}}a.recycle();}/*** dp 2 px** @param dpVal*/protected int dp2px(int dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal, getResources().getDisplayMetrics());}/*** sp 2 px** @param spVal* @return*/protected int sp2px(int spVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,spVal, getResources().getDisplayMetrics());}
}
资源文件:
<?xml version="1.0" encoding="utf-8"?>
<resources><attr name="reachedColor" format="color" /><attr name="unreachedColor" format="color" /><attr name="textSize" format="dimension" /><attr name="textColor" format="color" /><attr name="strokeWidth" format="dimension" /><declare-styleable name="RoundProgressbar"><attr name="strokeWidth" /><attr name="textSize" /><attr name="textColor" /><attr name="unreachedColor" /><attr name="reachedColor" /></declare-styleable></resources>
布局文件:
<com.zj.progressnumber.RoundProgressbarandroid:id="@+id/rpb"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@android:color/holo_green_light"android:padding="20dp"/>
实现:
这篇关于android 自定义 View(4)- 进度条(ProgressBar)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!