一. 前言
这个控件也可以说是为了做而做,是因为我在开发我的软件工程课程设计-连连看的时候,需要用到这个控件。
Github地址:CircleProgress
二. 自定义View
1. 自定义用到的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| private Paint progress_bg_paint;
private Paint progress_paint;
private Paint progress_value_paint;
private RelativeLayout layout;
private float progress = 0;
private float total_progress = 100;
private int startAngle = 0;
private int endAngle = 360;
private int textSize = 14;
private String textColor = "#ffffff";
private int textLeftPadding = 0;
|
2. 在values文件夹下自定义属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CircleProgress"> <attr name="progress" format="float"/> <attr name="total_progress" format="float"/> <attr name="startAngle" format="integer"/> <attr name="endAngle" format="integer"/> <attr name="textSize" format="integer"/> <attr name="textColor" format="string"/> <attr name="textLeftPadding" format="integer"/> </declare-styleable> </resources>
|
3. 创建构造方法
主要还是重写两个构造方法,需要解析属性的解析属性,最终都是要存储设置的值。
不管是哪一个构造方法都是要加载布局以及对三个画笔进行初始化操作。
我们重点看下绘制文本的时候如何设置自己指定的字体文件, 参考:安卓开发引用ttf字体文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:id="@+id/root">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/time" />
</RelativeLayout>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
public CircleProgress(Context context,int startAngle,int endAngle,int total_progress) { super(context);
this.startAngle = startAngle; this.endAngle = endAngle; this.total_progress = total_progress;
init(); }
public CircleProgress(Context context, @Nullable AttributeSet attrs) { super(context, attrs);
if (attrs != null){ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgress);
progress = typedArray.getFloat( R.styleable.CircleProgress_progress, progress ); setProgress(progress); total_progress = typedArray.getFloat( R.styleable.CircleProgress_total_progress, total_progress ); startAngle = typedArray.getInteger( R.styleable.CircleProgress_startAngle, startAngle ); endAngle = typedArray.getInteger( R.styleable.CircleProgress_endAngle, endAngle ); textSize = typedArray.getInteger( R.styleable.CircleProgress_textSize, textSize ); String temp_textColor = typedArray.getString( R.styleable.CircleProgress_textColor ); if (temp_textColor != null) { textColor = temp_textColor; } textLeftPadding = typedArray.getInteger( R.styleable.CircleProgress_textLeftPadding, 0 );
typedArray.recycle(); }
init(); }
private void init(){ progress_bg_paint = new Paint(Paint.ANTI_ALIAS_FLAG); progress_bg_paint.setColor(Color.parseColor("#9EE5A4")); progress_bg_paint.setStrokeWidth(PxUtil.dpToPx(10,getContext())); progress_bg_paint.setStyle(Paint.Style.STROKE); progress_bg_paint.setStrokeJoin(Paint.Join.ROUND); progress_bg_paint.setStrokeCap(Paint.Cap.ROUND);
progress_paint = new Paint(Paint.ANTI_ALIAS_FLAG); progress_paint.setColor(Color.parseColor("#CCBBBBBB")); progress_paint.setStrokeWidth(PxUtil.spToPx(10,getContext())); progress_paint.setStyle(Paint.Style.STROKE); progress_paint.setStrokeJoin(Paint.Join.ROUND); progress_paint.setStrokeCap(Paint.Cap.ROUND);
progress_value_paint = new Paint(Paint.ANTI_ALIAS_FLAG); progress_value_paint.setColor(Color.parseColor(textColor)); progress_value_paint.setTextSize(PxUtil.dpToPx(textSize,getContext())); progress_value_paint.setTypeface( Typeface.createFromAsset( getContext().getAssets(), "font/造字工房乐真体.ttf" ) );
View inflate = View.inflate(getContext(), R.layout.circle_progress, this); layout = inflate.findViewById(R.id.root); }
|
4. 绘制进度背景,进度以及进度文本
在这里,由于为了方便我的连连看,所以只考虑了连连看中的情况。时间是从90秒不停地减少的,所以如果是不断的增加的,代码需要重构。
由于progress是float,我们使用DecimalFormat类来规范其小数位数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas);
@SuppressLint("DrawAllocation") RectF rectF = new RectF( layout.getLeft(), layout.getTop(), layout.getRight(), layout.getBottom() ); Log.d("CircleProgress",rectF.toString());
canvas.drawArc( rectF,0, 360, false, progress_bg_paint );
canvas.drawArc( rectF, startAngle, (endAngle-startAngle)*((total_progress-progress)/total_progress), false, progress_paint );
String text = new DecimalFormat("##0.0").format(progress)+"秒"; float text_width = progress_value_paint.measureText(text); Paint.FontMetrics fontMetrics = progress_value_paint.getFontMetrics(); float text_height = (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom; canvas.drawText( text, PxUtil.dpToPx(textLeftPadding,getContext())+getPivotX()-text_width/2, getPivotY()+text_height, progress_value_paint ); }
public void setProgress(float progress) { this.progress = progress;
invalidate(); }
|
5. 默认的资源文件
这里控制的就是布局文件中TextView的样式,其width和height对整体呈现效果有影响。默认效果如下,但是该文件还不可以自定义,目前版本还没有自定义相关属性。如果以后需要再次使用该控件,会再次优化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#E48093" />
<stroke android:width="8dp" android:color="#EAB3BE" />
<size android:width="120dp" android:height="120dp"/>
</shape>
|
三. 具体的使用
首先需要添加依赖,添加依赖之后,在布局文件中这样调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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=".MainActivity">
<swu.xl.circleprogress.CircleProgress android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" app:total_progress="100" app:progress="20.0000" app:startAngle="270" app:endAngle="450" app:textColor="#ffffff" app:textSize="22" app:textLeftPadding="10" />
</RelativeLayout>
|