如圖:java
自定義屬性,在values文件夾下建立 attrs.xmlandroid
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="SuperCircleView"> <!-- 圓的半徑 --> <attr name="min_circle_radio" format="integer"/> <!-- 圓環的寬度 --> <attr name="ring_width" format="float"/> <!-- 內圓的顏色 --> <attr name="circle_color" format="color"/> <!-- 外圓的顏色 --> <attr name="max_circle_color" format="color"/> <!-- 圓環的默認顏色 --> <attr name="ring_normal_color" format="color"/> <!-- 圓環要顯示的彩色的區域(隨着數值的改變,顯示不一樣大小的彩色區域)--> <attr name="ring_color_select" format="integer"/> <!-- 繪製內容的數值 --> <attr name="maxValue" format="integer" /> <attr name="value" format="integer" /> </declare-styleable> </resources>
自定義viewcanvas
package com.chuanye.huanxingtu; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.SweepGradient; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.TextView; public class SuperCircleView extends View { private final String TAG = "SuperCircleView"; private ValueAnimator valueAnimator; private int mViewCenterX; //view寬的中心點(能夠暫時理解爲圓心) private int mViewCenterY; //view高的中心點(能夠暫時理解爲圓心) private int mMinRadio; //最裏面白色圓的半徑 private float mRingWidth; //圓環的寬度 private int mMinCircleColor; //最裏面圓的顏色 private int mRingNormalColor; //默認圓環的顏色 private Paint mPaint; private int color[] = new int[3]; //漸變顏色 private RectF mRectF; //圓環的矩形區域 private int mSelectRing = 0; //要顯示的彩色區域(歲數值變化) private int mMaxValue; public SuperCircleView(Context context) { super(context); Log.i(TAG,"SuperCircleView--->1SuperCircleView"); } public SuperCircleView(Context context, AttributeSet attrs) { super(context, attrs); Log.i(TAG,"SuperCircleView--->2SuperCircleView"); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SuperCircleView); //最裏面白色圓的半徑 mMinRadio = a.getInteger(R.styleable.SuperCircleView_min_circle_radio, 300); //圓環寬度 mRingWidth = a.getFloat(R.styleable.SuperCircleView_ring_width, 40); //最裏面的圓的顏色(綠色) mMinCircleColor = a.getColor(R.styleable.SuperCircleView_circle_color, context.getResources().getColor(R.color.green)); // mMinCircleColor = a.getColor(R.styleable.SuperCircleView_circle_color, context.getResources().getColor(R.color.green)); //圓環的默認顏色(圓環佔據的是裏面的圓的空間) mRingNormalColor = a.getColor(R.styleable.SuperCircleView_ring_normal_color, context.getResources().getColor(R.color.gray)); //圓環要顯示的彩色的區域 mSelectRing = a.getInt(R.styleable.SuperCircleView_ring_color_select, 0); mMaxValue = a.getInt(R.styleable.SuperCircleView_maxValue, 100); a.recycle(); //抗鋸齒畫筆 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //防止邊緣鋸齒 mPaint.setAntiAlias(true); //須要重寫onDraw就得調用此 this.setWillNotDraw(false); //圓環漸變的顏色 color[0] = Color.parseColor("#FFD300"); color[1] = Color.parseColor("#FF0084"); color[2] = Color.parseColor("#16FF00"); } public SuperCircleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); Log.i(TAG,"SuperCircleView--->3SuperCircleView"); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); Log.i(TAG,"SuperCircleView--->onLayout"); //view的寬和高,相對於父佈局(用於肯定圓心) int viewWidth = getMeasuredWidth(); int viewHeight = getMeasuredHeight(); mViewCenterX = viewWidth / 2; mViewCenterY = viewHeight / 2; //畫矩形 mRectF = new RectF(mViewCenterX - mMinRadio - mRingWidth / 2, mViewCenterY - mMinRadio - mRingWidth / 2, mViewCenterX + mMinRadio + mRingWidth / 2, mViewCenterY + mMinRadio + mRingWidth / 2); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.i(TAG,"SuperCircleView--->onDraw"); mPaint.setColor(mMinCircleColor); canvas.drawCircle(mViewCenterX, mViewCenterY, mMinRadio, mPaint); //畫默認圓環 drawNormalRing(canvas); //畫彩色圓環 drawColorRing(canvas); } /** * 畫默認圓環 * * @param canvas */ private void drawNormalRing(Canvas canvas) { Paint ringNormalPaint = new Paint(mPaint); ringNormalPaint.setStyle(Paint.Style.STROKE); ringNormalPaint.setStrokeWidth(mRingWidth); ringNormalPaint.setColor(mRingNormalColor);//圓環默認顏色爲灰色 canvas.drawArc(mRectF, 360, 360, false, ringNormalPaint); } /** * 畫彩色圓環 * * @param canvas */ private void drawColorRing(Canvas canvas) { Paint ringColorPaint = new Paint(mPaint); ringColorPaint.setStyle(Paint.Style.STROKE); ringColorPaint.setStrokeWidth(mRingWidth); ringColorPaint.setShader(new SweepGradient(mViewCenterX, mViewCenterX, color, null)); //逆時針旋轉90度 canvas.rotate(-90, mViewCenterX, mViewCenterY); canvas.drawArc(mRectF, 360, mSelectRing, false, ringColorPaint); ringColorPaint.setShader(null); } //***************************************用於更新圓環表示的數值***************************************************** /** * 設置當前值 * * @param value */ public void setValue(int value, TextView textView) { if (value > mMaxValue) { value = mMaxValue; } int start = 0; int end = value; startAnimator(start, end, 2000,textView); } private void startAnimator(int start, int end, long animTime, final TextView textView) { valueAnimator = ValueAnimator.ofInt(start, end); valueAnimator.setDuration(animTime); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Log.i(TAG, "onAnimationUpdate: animation.getAnimatedValue()::"+animation.getAnimatedValue()); int i = Integer.valueOf(String.valueOf(animation.getAnimatedValue())); textView.setText(i + ""); //每一個單位長度佔多少度 mSelectRing=(int) (360 * (i / 100f)); Log.i(TAG, "onAnimationUpdate: mSelectRing::"+mSelectRing); invalidate(); } }); valueAnimator.start(); } }
佈局app
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:gravity="center" tools:context=".Main1Activity"> <FrameLayout android:layout_width="300dp" android:layout_height="300dp" android:layout_gravity="center"> <com.chuanye.huanxingtu.SuperCircleView android:id="@+id/superview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" app:maxValue="100" app:value="20" app:ring_width="60" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginBottom="60dp" android:text="信息完成度" android:textColor="#CFD5DE" android:textSize="18sp" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="10dp" android:orientation="horizontal"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0" android:textColor="#506946" android:textSize="80sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="%" android:textSize="28sp" /> </LinearLayout> </FrameLayout> </LinearLayout>
MainActivity中dom
package com.chuanye.huanxingtu; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.TextView; import java.util.Random; public class Main1Activity extends AppCompatActivity { private static final String TAG = "Main1Activity"; SuperCircleView mSuperCircleView; TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main1); textView = findViewById(R.id.tv); mSuperCircleView = findViewById(R.id.superview); mSuperCircleView.setValue(100, textView); mSuperCircleView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //隨機設定圓環大小 int i = new Random().nextInt(100) + 1; Log.i(TAG, "onClick: i::" + i); mSuperCircleView.setValue(i, textView); } }); } }
完成ide
參考於://https://blog.csdn.net/zhangqunshuai/article/details/80733982佈局