继承View重写带两个参数的构造方法,一个参数的不行不会加载视图,构造方法中初始化画笔这样不用没次刷新都要初始化浪费内存,在ondraw方法中绘图,invalidate方法会掉用ondraw方法重新绘制.在attrs中声明你将要设置的属性,名字要和自定义类名一样,在布局文件中引用属性,随便输入属性名然后alt+enter自动生成命名空间,就可以引用自定义属性了.最后在主activity中调用接口,使用传来的参数current
public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final CircleProgressView myView = findViewById(R.id.circle); ValueAnimator animator = ValueAnimator.ofFloat(0, 100); animator.setDuration(4000); animator.setInterpolator(new LinearInterpolator()); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float current = (float) animation.getAnimatedValue(); myView.setmCurrent((int) current); } }); animator.start(); myView.setOnLoadingCompleteListener(new CircleProgressView.OnLoadingCompleteListener() { @Override public void complete(int current) { System.out.println(current); if (current == 100) { myView.setVisibility(View.GONE); Toast.makeText(MainActivity.this, "加载完成", Toast.LENGTH_SHORT).show(); } } }); } }
主activity
public class CircleProgressView extends View { private int mCurrent;//当前进度 private Paint mPaintOut; private Paint mPaintCurrent; private Paint mPaintText; private float mPaintWidth;//画笔宽度 private int mPaintColor = Color.RED;//画笔颜色 private int mTextColor = Color.BLACK;//字体颜色 private float mTextSize;//字体大小 private int location;//从哪个位置开始 private float startAngle;//开始角度 public CircleProgressView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView); location = array.getInt(R.styleable.CircleProgressView_location, 1); mPaintWidth = array.getDimension(R.styleable.CircleProgressView_progress_paint_width, dip2px(context,4));//默认4dp mPaintColor = array.getColor(R.styleable.CircleProgressView_progress_paint_color, mPaintColor); mTextSize = array.getDimension(R.styleable.CircleProgressView_progress_text_size, dip2px(context,18));//默认18sp mTextColor = array.getColor(R.styleable.CircleProgressView_progress_text_color, mTextColor); array.recycle(); //画笔->背景圆弧 mPaintOut = new Paint(); mPaintOut.setAntiAlias(true); mPaintOut.setStrokeWidth(mPaintWidth); mPaintOut.setStyle(Paint.Style.STROKE); mPaintOut.setColor(Color.GRAY); mPaintOut.setStrokeCap(Paint.Cap.ROUND); //画笔->进度圆弧 mPaintCurrent = new Paint(); mPaintCurrent.setAntiAlias(true); mPaintCurrent.setStrokeWidth(mPaintWidth); mPaintCurrent.setStyle(Paint.Style.STROKE); mPaintCurrent.setColor(mPaintColor); mPaintCurrent.setStrokeCap(Paint.Cap.ROUND); //画笔->绘制字体 mPaintText = new Paint(); mPaintText.setAntiAlias(true); mPaintText.setStyle(Paint.Style.FILL); mPaintText.setColor(mTextColor); mPaintText.setTextSize(mTextSize); if (location == 1) {//默认从左侧开始 startAngle = -180; } else if (location == 2) { startAngle = -90; } else if (location == 3) { startAngle = 0; } else if (location == 4) { startAngle = 90; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); RectF rectF = new RectF(mPaintWidth / 2, mPaintWidth / 2, getWidth() - mPaintWidth / 2, getHeight() - mPaintWidth / 2); canvas.drawArc(rectF, 0, 360, false, mPaintOut); //绘制当前进度 float sweepAngle = 360 * mCurrent / 100; canvas.drawArc(rectF, startAngle, sweepAngle, false, mPaintCurrent); //绘制进度数字 String text = mCurrent + "%"; //获取文字宽度 float textWidth = mPaintText.measureText(text, 0, text.length()); float dx = getWidth() / 2 - textWidth / 2; Paint.FontMetricsInt fontMetricsInt = mPaintText.getFontMetricsInt(); float dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom; float baseLine = getHeight() / 2 + dy; canvas.drawText(text, dx, baseLine, mPaintText); if (mLoadingCompleteListener != null ) { mLoadingCompleteListener.complete(mCurrent); } } public void setmCurrent(int mCurrent) { this.mCurrent = mCurrent; invalidate(); } public interface OnLoadingCompleteListener { void complete(int current); } //暴露回调方法 public void setOnLoadingCompleteListener(OnLoadingCompleteListener loadingCompleteListener) { this.mLoadingCompleteListener = loadingCompleteListener; } //监听 /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } private OnLoadingCompleteListener mLoadingCompleteListener; }
自定义view
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" xmlns:myview="http://schemas.android.com/apk/res-auto" android:id="@+id/line1" android:orientation="vertical" android:layout_height="match_parent" tools:context=".MainActivity"> <com.january.summer.CircleProgressView android:id="@+id/circle" android:layout_width="50dp" myview:location="left" android:layout_gravity="center" android:layout_height="50dp" /> </LinearLayout>
布局文件
<resources> <declare-styleable name="CircleProgressView">//要跟类名一样 <!--画笔宽度--> <attr name="progress_paint_width" format="dimension" /> <!--画笔颜色--> <attr name="progress_paint_color" format="color" /> <!--字体颜色--> <attr name="progress_text_color" format="color" /> <!--字体尺寸--> <attr name="progress_text_size" format="dimension" /> <!--加载进度的开始位置--> <attr name="location" format="enum"> <enum name="left" value="1" /> <enum name="top" value="2" /> <enum name="right" value="3" /> <enum name="bottom" value="4" /> </attr> </declare-styleable> </resources>
attrs文件,注意,demension属性使用时自动把dp转为px