愿君学长松,慎勿作桃李。这篇文章主要讲述Android自定义View——动态进度条相关的知识,希望能为你提供帮助。
效果图:
文章图片
这个是看了梁肖的demo, 根据他的思路自己写了一个, 但是我写的这个貌似计算还是有些问题, 这个过程还是有点曲折的, 不过还是觉得收获挺多的。比如通动画来进行动态的展示( 之前做的都是通过Handler进行更新的所以现在换一种思路觉得特别好) , 还有圆弧的起止角度, 矩形区域的计算等! 关于绘制我们可以循序渐进, 比如最开始先画圆, 然后再画周围的线, 最后设置动画部分就可以了。不多说了, 上代码了。
代码 自定义View
public class ColorProgressBar extends View{
//下面这两行在本demo中没什么用,
只是前几天看别人的代码时学到的按一定尺寸,
设置其他尺寸的方式,
自动忽略或者学习一下也不错
//private int defaultStepIndicatorNum=
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,40,getResources().getDisplayMetrics());
//int mCircleRadius=
0.28f*defaultStepIndicatorNum;
//布局的宽高
private int mWidth;
private int mHeight;
//底层圆画笔
private Paint mPaintbg;
//顶层圆的画笔
private Paint mPaintft;
//周围线的画笔
private Paint mPaintLine;
//外层线条的长度
private int mLongItem=
dip2px(20);
//线条与圆的间距
private int mDistanceItem=
dip2px(10);
//进度条的最大宽度(
取底层进度条与顶层进度条宽度最大的)
private int mProgressWidth;
//底层圆的颜色
private int mBackColor;
//顶层圆的颜色
private int mFrontColor;
//底层圆、顶层圆的宽度
private float mBackWidth;
private float mFrontWidth;
//设置进度
private float currentvalue;
//通过动画演示进度
private ValueAnimator animator;
private int curvalue;
public ColorProgressBar(Context context) {
this(context,null,0);
}public ColorProgressBar(Context context, AttributeSet attrs) {
this(context, attrs,0);
}public ColorProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta=
context.obtainStyledAttributes(attrs, R.styleable.ColorProgressBar);
mBackColor=
ta.getColor(R.styleable.ColorProgressBar_back_color, Color.BLACK);
mFrontColor=
ta.getColor(R.styleable.ColorProgressBar_front_color,mBackColor);
mBackWidth=
ta.getDimension(R.styleable.ColorProgressBar_back_width,dip2px(10));
mFrontWidth=
ta.getDimension(R.styleable.ColorProgressBar_front_width,dip2px(10));
mProgressWidth=
mBackWidth>
mFrontWidth?(int)mBackWidth:(int)mFrontWidth;
//注意释放资源
ta.recycle();
init();
}/**
* 都是画笔初始化
*/
private void init() {
mPaintbg=
new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintbg.setStrokeWidth(mProgressWidth);
mPaintbg.setColor(mBackColor);
mPaintbg.setStrokeCap(Paint.Cap.ROUND);
mPaintbg.setStyle(Paint.Style.STROKE);
mPaintft=
new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintft.setColor(mFrontColor);
mPaintft.setStyle(Paint.Style.STROKE);
mPaintft.setStrokeWidth(mFrontWidth);
mPaintft.setStrokeCap(Paint.Cap.ROUND);
mPaintLine=
new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintLine.setColor(Color.BLACK);
mPaintLine.setStrokeWidth(5);
}@
Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth=
mHeight=
getScreenWidth()*2/3;
setMeasuredDimension(mWidth,mHeight);
}@
Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制底层圆弧,
矩形的具体计算见图片
canvas.drawArc(new RectF(mProgressWidth+
mDistanceItem+
mLongItem,mProgressWidth+
mDistanceItem+
mLongItem,mWidth-mProgressWidth-mDistanceItem-mLongItem,mHeight-mProgressWidth-mDistanceItem-mLongItem),0,360,true,mPaintbg);
//绘制边缘线
canvas.save();
canvas.rotate(144,mWidth/2,mHeight/2);
for(int i=
0;
i<
=
30;
i+
+
){
canvas.rotate(-9,mWidth/2,mHeight/2);
if(i%5=
=
0){
canvas.drawLine(mWidth/2,10,mWidth/2,mLongItem,mPaintbg);
}else {
canvas.drawLine(mWidth/2,25,mWidth/2,mLongItem,mPaintLine);
}
}canvas.restore();
//给画笔设置渐变
SweepGradient sweepGradient=
new SweepGradient(mWidth/2,mHeight/2,Color.RED,Color.YELLOW);
mPaintft.setShader(sweepGradient);
//绘制顶层圆弧,
currentvalue在改变时呈现动态效果
canvas.drawArc(new RectF(mProgressWidth+
mDistanceItem+
mLongItem,mProgressWidth+
mDistanceItem+
mLongItem,mWidth-mProgressWidth-mDistanceItem-mLongItem,mHeight-mProgressWidth-mDistanceItem-mLongItem),135,currentvalue,false,mPaintft);
mPaintft.setTextSize(100);
mPaintft.setTextAlign(Paint.Align.CENTER);
//绘制文本
canvas.drawText(String.format("
%.0f"
,currentvalue),mWidth/2,mHeight/2+
50,mPaintft);
}/**
* 设置动画
* @
param value
*/
public void setCurrentValue(float value){
//currentvalue=
value;
animator=
ValueAnimator.ofFloat(currentvalue,value);
animator.setDuration(3000);
animator.setTarget(currentvalue);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@
Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
currentvalue=
(float) valueAnimator.getAnimatedValue();
curvalue=
curvalue/10;
invalidate();
}
});
animator.start();
}
private int dip2px(float dip){
float density=
getContext().getResources().getDisplayMetrics().density;
return (int)(dip*density+
0.5f);
}
}
private int getScreenWidth(){
WindowManager manager=
(WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
Display display=
manager.getDefaultDisplay();
if(Build.VERSION.SDK_INT>
=
13){
Point point=
new Point();
display.getSize(point);
return point.x;
}else {
return display.getWidth();
}
}
矩形计算
文章图片
Activity调用
@
Override
protected void onCreate(@
Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.colorprogressbar);
mBtStart1=
(Button) findViewById(R.id.bt1);
bar1=
(ColorProgressBar) findViewById(R.id.cp1);
mBtStart1.setOnClickListener(new View.OnClickListener() {
@
Override
public void onClick(View view) {
bar1.setCurrentValue(270);
}
});
}
自定义属性
<
declare-styleable name=
"
ColorProgressBar"
>
<
attr name=
"
back_color"
format=
"
color"
>
<
/attr>
<
attr name=
"
front_color"
format=
"
color"
>
<
/attr>
<
attr name=
"
back_width"
format=
"
dimension"
>
<
/attr>
<
attr name=
"
front_width"
format=
"
dimension"
>
<
/attr>
<
/declare-styleable>
布局 注意: 为了使用自定义属性需要添加一行代码( AS)
xmlns:app=
"
http://schemas.android.com/apk/res-auto"
【Android自定义View——动态进度条】布局
<
LinearLayout
xmlns:android=
"
http://schemas.android.com/apk/res/android"
xmlns:app=
"
http://schemas.android.com/apk/res-auto"
android:layout_width=
"
match_parent"
android:layout_height=
"
wrap_content"
android:orientation=
"
vertical"
>
<
Button
android:id=
"
@
+
id/bt1"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:text=
"
start1"
/>
<
com.demo.demo.networkdemo.colorprogressbar.widget.ColorProgressBar
android:id=
"
@
+
id/cp1"
android:layout_width=
"
232dp"
android:layout_height=
"
match_parent"
android:layout_gravity=
"
center_horizontal"
app:back_color=
"
@
color/colorPrimary"
app:front_color=
"
@
color/colorAccent"
android:background=
"
@
mipmap/ic_launcher"
/>
<
/LinearLayout>
推荐阅读
- Android中的沉浸式状态栏效果
- 问题AndroidStudio导入项目一直卡在Building gradle project infod的最快速解决方案
- Android6.0中的权限
- RxAndroid/java小记
- Android之Service的细枝末节
- Freeline 让AndroidStudio快的飞起来
- 安卓专项测试-对于小白,真的很多坑
- Leetcode: Android Unlock Patterns
- Kotlin的android扩展(对findViewById说再见(KAD 04))