Android 绘制圆形进度条
2015-09-02 17:45
465 查看
Android 绘制圆形进度条
最近项目上有一些需求,需要绘制圆形的进度条满足设计上和交互上的需求:实现思路
在画布上直接绘制View,需要了解一下几点1.需要画一个圆
2.圆圈上有不同进度的颜色
3.圆圈中有进度数字的展示
4.圆圈中间还有可以自定义不同文案提示
一、画圆
需要使用Canvas的该方法public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint) { drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter, paint); }
如下:
// 设置画笔相关属性 mPaint.setAntiAlias(true); mPaint.setColor(Color.rgb(0xe9, 0xe9, 0xe9)); canvas.drawColor(Color.TRANSPARENT); mPaint.setStrokeWidth(mCircleLineStrokeWidth); mPaint.setStyle(Style.STROKE); // 位置 mRectF.left = mCircleLineStrokeWidth / 2; // 左上角x mRectF.top = mCircleLineStrokeWidth / 2; // 左上角y mRectF.right = width - mCircleLineStrokeWidth / 2; // 左下角x mRectF.bottom = height - mCircleLineStrokeWidth / 2; // 右下角y // 绘制圆圈,进度条背景 canvas.drawArc(mRectF, -90, 360, false, mPaint);
此时画出了默认的背景圆圈:
二、画进度圆弧
其实实现很简单,换另外一种颜色同样在画布上画出即可,支持此时画的不是360°,而是通过进度计算出来的一个圆弧。mPaint.setColor(Color.rgb(0xf8, 0x60, 0x30)); canvas.drawArc(mRectF, -90, ((float) mProgress / mMaxProgress) * 360, false, mPaint);
如上即可,此时mProgress / mMaxProgress = 80/100;即可绘制出如下效果
三、画中间进度百分比
其实要用到Canvas中绘制文本的方法:public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) { native_drawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface); }
如下:
// 绘制进度文案显示 mPaint.setStrokeWidth(mTxtStrokeWidth); String text = mProgress + "%"; int textHeight = height / 4; mPaint.setTextSize(textHeight); int textWidth = (int) mPaint.measureText(text, 0, text.length()); mPaint.setStyle(Style.FILL); canvas.drawText(text, width / 2 - textWidth / 2, height / 2 + textHeight / 2, mPaint);
主要要计算好画的位置,drawText中对应就是相关的位置,相当于居中显示进度百分比文案。效果如下:
四、画圆圈中间提示文案
方法同三,只不过要计算出画的位置即可,效果图如下:五、总结
其实很多自定义的View都可以用Canvas直接画出来,如果项目上有类似这样的需求,可以先研究Canvas的使用和原理。最后附上源码:
public class CircleProgressView extends View {
private static final String TAG = "CircleProgressBar";
private int mMaxProgress = 100;
private int mProgress = 30;
private final int mCircleLineStrokeWidth = 8;
private final int mTxtStrokeWidth = 2;
// 画圆所在的距形区域
private final RectF mRectF;
private final Paint mPaint;
private final Context mContext;
private String mTxtHint1;
private String mTxtHint2;
public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mRectF = new RectF();
mPaint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = this.getWidth();
int height = this.getHeight();
if (width != height) {
int min = Math.min(width, height);
width = min;
height = min;
}
// 设置画笔相关属性
mPaint.setAntiAlias(true);
mPaint.setColor(Color.rgb(0xe9, 0xe9, 0xe9));
canvas.drawColor(Color.TRANSPARENT);
mPaint.setStrokeWidth(mCircleLineStrokeWidth);
mPaint.setStyle(Style.STROKE);
// 位置
mRectF.left = mCircleLineStrokeWidth / 2; // 左上角x
mRectF.top = mCircleLineStrokeWidth / 2; // 左上角y
mRectF.right = width - mCircleLineStrokeWidth / 2; // 左下角x
mRectF.bottom = height - mCircleLineStrokeWidth / 2; // 右下角y
// 绘制圆圈,进度条背景
canvas.drawArc(mRectF, -90, 360, false, mPaint);
mPaint.setColor(Color.rgb(0xf8, 0x60, 0x30)); canvas.drawArc(mRectF, -90, ((float) mProgress / mMaxProgress) * 360, false, mPaint);
// 绘制进度文案显示 mPaint.setStrokeWidth(mTxtStrokeWidth); String text = mProgress + "%"; int textHeight = height / 4; mPaint.setTextSize(textHeight); int textWidth = (int) mPaint.measureText(text, 0, text.length()); mPaint.setStyle(Style.FILL); canvas.drawText(text, width / 2 - textWidth / 2, height / 2 + textHeight / 2, mPaint);
if (!TextUtils.isEmpty(mTxtHint1)) {
mPaint.setStrokeWidth(mTxtStrokeWidth);
text = mTxtHint1;
textHeight = height / 8;
mPaint.setTextSize(textHeight);
mPaint.setColor(Color.rgb(0x99, 0x99, 0x99));
textWidth = (int) mPaint.measureText(text, 0, text.length());
mPaint.setStyle(Style.FILL);
canvas.drawText(text, width / 2 - textWidth / 2, height / 4 + textHeight / 2, mPaint);
}
if (!TextUtils.isEmpty(mTxtHint2)) {
mPaint.setStrokeWidth(mTxtStrokeWidth);
text = mTxtHint2;
textHeight = height / 8;
mPaint.setTextSize(textHeight);
textWidth = (int) mPaint.measureText(text, 0, text.length());
mPaint.setStyle(Style.FILL);
canvas.drawText(text, width / 2 - textWidth / 2, 3 * height / 4 + textHeight / 2, mPaint);
}
}
public int getMaxProgress() {
return mMaxProgress;
}
public void setMaxProgress(int maxProgress) {
this.mMaxProgress = maxProgress;
}
public void setProgress(int progress) {
this.mProgress = progress;
this.invalidate();
}
public void setProgressNotInUiThread(int progress) {
this.mProgress = progress;
this.postInvalidate();
}
public String getmTxtHint1() {
return mTxtHint1;
}
public void setmTxtHint1(String mTxtHint1) {
this.mTxtHint1 = mTxtHint1;
}
public String getmTxtHint2() {
return mTxtHint2;
}
public void setmTxtHint2(String mTxtHint2) {
this.mTxtHint2 = mTxtHint2;
}
}
Xml中配置:
<com.jackshy.demo.view.CircleProgressBar android:id="@+id/circleProgressbar" android:layout_width="74dp" android:layout_height="74dp" android:layout_centerInParent="true" />
MainActivity中使用:
import android.app.Activity; import android.os.Bundle; import android.view.Menu; import com.jackshy.demo.view.CircleProgressBar; public class MainActivity extends Activity { private CircleProgressBar mCircleBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } private void initViews() { mCircleBar = (CircleProgressBar) findViewById(R.id.circleProgressbar); mCircleBar.setProgress(80); } }
上述还可以做成进度条的形式,这时候需要启动非UI线程调用此方法即可:
public void setProgressNotInUiThread(int progress) { this.mProgress = progress; this.postInvalidate(); }
待续。
相关文章推荐
- 使用 Android 自带的 proguard 混淆源码
- Android Studio中Gradle使用详解
- Android文件的下载
- Android项目中如何用好构建神器Gradle?
- Android PhoneGap 利用 Activity 实现 CordovaInterface
- juahya 一个动态解析android layout xml 布局文件的框架
- android 电话状态的监听(来电和去电)
- Android5.0 Gallery2上编译Gallery模块出错
- Android官网Activities文档翻译
- 使用ScrollView属性fillViewport解决android布局不能撑满全屏的问题
- android如何打印当前的线程及进程
- Android 属性动画 (一)
- Android adb常见问题
- 《ArcGIS Runtime SDK for Android开发笔记》——(2)、Android Studio基本配置与使用
- Android中修改源码实现AutoCompeteTextView控件的模糊匹配
- Android 最火的快速开发框架XUtils
- android屏幕适配详解
- Android 清理应用缓存
- Android Studio安装插件
- 【沙龙干货分享】你要知道的N个Android适配问题