目录
效果
按照惯例,放上效果图
前言
上一篇 文章把断点续传的功能分享了一下,有兴趣的朋友可以看一看。接下来就给大家分享一下自定义View 圆形加载条。
正文
自定义View CirclePercentView
public class CirclePercentView extends View {
//圆的半径
private float mRadius;
//色带的宽度
private float mStripeWidth;
//总体大小
private int mHeight;
private int mWidth;
//动画位置百分比进度
private int mCurPercent;
//实际百分比进度
private int mPercent;
//圆心坐标
private float x;
private float y;
//要画的弧度
private int mEndAngle;
//小圆的颜色
private int mSmallColor;
//大圆颜色
private int mBigColor;
//中心百分比文字大小
private float mCenterTextSize;
public CirclePercentView(Context context) {
this(context, null);
}
public CirclePercentView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CirclePercentView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePercentView, defStyleAttr, 0);
mStripeWidth = a.getDimension(R.styleable.CirclePercentView_stripeWidth, PxUtils.dpToPx(30, context));
mCurPercent = a.getInteger(R.styleable.CirclePercentView_percent, 0);
mSmallColor = a.getColor(R.styleable.CirclePercentView_smallColor, 0xffafb4db);
mBigColor = a.getColor(R.styleable.CirclePercentView_bigColor, 0xff6950a1);
mCenterTextSize = a.getDimensionPixelSize(R.styleable.CirclePercentView_centerTextSize, PxUtils.spToPx(20, context));
mRadius = a.getDimensionPixelSize(R.styleable.CirclePercentView_radius, PxUtils.dpToPx(100, context));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取测量模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//获取测量大小
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {
mRadius = widthSize / 2;
x = widthSize / 2;
y = heightSize / 2;
mWidth = widthSize;
mHeight = heightSize;
}
if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
mWidth = (int) (mRadius * 2);
mHeight = (int) (mRadius * 2);
x = mRadius;
y = mRadius;
}
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
mEndAngle = (int) (mCurPercent * 3.6);//mCurPercent=0~100.则mEndAngle=0~360.
//绘制大圆
Paint bigCirclePaint = new Paint();
bigCirclePaint.setAntiAlias(true);//抗锯齿,同:别名alias.
bigCirclePaint.setColor(mBigColor);
canvas.drawCircle(x, y, mRadius, bigCirclePaint);
//饼状图,
Paint sectorPaint = new Paint();
sectorPaint.setColor(mSmallColor);
sectorPaint.setAntiAlias(true);
//精度不一样。Rect是使用int类型作为数值,RectF是使用float类型作为数值。
RectF rect = new RectF(0, 0, mWidth, mHeight);
// 圆弧arc,即扇形.
canvas.drawArc(rect, 0, mEndAngle, true, sectorPaint);
// //绘制小圆,颜色 同 大圆.
// Paint smallCirclePaint = new Paint();
// smallCirclePaint.setAntiAlias(true);
// smallCirclePaint.setColor(mBigColor);
// canvas.drawCircle(x, y, mRadius - mStripeWidth, smallCirclePaint);
//绘制文本
Paint textPaint = new Paint();
String text = mCurPercent + "%";
textPaint.setTextSize(mCenterTextSize);
float textLength = textPaint.measureText(text);
textPaint.setColor(Color.WHITE);
canvas.drawText(text, x - textLength / 2, y, textPaint);
}
//外部设置百分比数
public void setPercent(int percent) {
if (percent > 100) {
throw new IllegalArgumentException("percent must less than 100!");
}
setCurPercent(percent);
}
//内部设置百分比 用于动画效果
private void setCurPercent(int percent) {
mPercent = percent;
new Thread(new Runnable() {
@Override
public void run() {
int sleepTime = 1;
for (int i = 0; i <= mPercent; i++) {
if (i % 20 == 0) {
sleepTime += 2;
}
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
mCurPercent = i;
CirclePercentView.this.postInvalidate();
}
}
}).start();
}
}
首先自定义View ,肯定是要继承View类的
CirclePercentView()
类中实现了三个构造方法,前两个方法调用第三个方法,我们在第三个方法中初始化自定义的变量,也就是相应的颜色,半径,宽度等等,onMeasure()
方法,继承自View,在方法中获得了视图的宽度和高度,根据高度和宽度,定义了相应的自定义高度和宽度,以及圆的坐标位置。-
onDraw()
方法,依旧重写于VIew 类中,这个方法就是绘制视图,比较麻烦;- 第一步设置了要画的弧度
- 一共3个
Plint
和一个Canvas
;bigCirclePaint
绘制大圆,设置了抗锯齿和颜色,sectorPaint
饼状图也就是效果中的扇形,设置了颜色和抗锯齿,textPaint
文本,中间的数字,cancas
就是画布,plint就相当于画笔,我们把画笔画在画布上就成功的现实了上面的效果
最后两个方法:外部百分比和内部的百分比,内部的百分比有一个动画效果;外部就是给外部留下了方法可以调用;
PxUtils
/**
* 用于px和 dp,sp的转换工具
*/
public class PxUtils {
public static int dpToPx(int dp, Context context) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
}
public static int spToPx(int sp,Context context) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
}
}
此方法就是dp和sp转为px的方法
主方法 MainActivity
public class MainActivity extends AppCompatActivity {
private Button mButton;
private CirclePercentView mCirclePercentView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCirclePercentView = (CirclePercentView) findViewById(R.id.circleView);
mButton = (Button) findViewById(R.id.button);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int n = (int)(1*100);
mCirclePercentView.setPercent(n);
}
});
}
}
- 定义了一个自定义View,一个Button
- 通过点击事件设置进度
activity_main 视图
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.wingsofts.circlepercentview.MainActivity">
<com.wingsofts.circlepercentview.CirclePercentView
android:id="@+id/circleView"
app:stripeWidth="15dp"
app:centerTextSize="16sp"
app:percent="45"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/button"
android:text="change"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
总结
其实自定义View就是很简单的东西 ,我们可以自己动手操作一下就可以了,主要就是画笔和画布之间,然后动态效果就是通过线程更新UI;就每次都重新绘画一下视图。
感谢
该项目是在网上浏览的时候看见的,给大家奉上Github
的地址