import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.AttributeSet; import android.util.TypedValue; public class CustomView5 extends ViewGroup { private static int INDICATOR_LINE_TEXT_SIZE = 4; private String indicator_text; private int def_radius_color; private int small_radius_color; private int big_radius_color; private float def_radius; private float small_def_radius; private float big_def_radius; private int indicator_def_color; private int indicator_select_color; private float indicator_text_size; private float axis_size; private int axis_def_color; private int axis_size_select_color; private String[] indicator; private Paint def_radius_paint; private Paint small_radius_paint; private Paint big_radius_paint; private Paint indicator_def_paint; private Paint indicator_select_paint; private Paint axis_def_paint; private Paint axis_select_paint; private String indicator_first_text; private String indicator_last_text; private float indicator_text_margin_top; private int max_text_size; private int DEF_INTERVAL = 100; private int interval; public CustomView5(Context context) { super(context); } public CustomView5(Context context, @Nullable AttributeSet attrs) { super(context, attrs); // setWillNotDraw(false); // TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomView5); indicator_text = typedArray.getString(R.styleable.CustomView5_text_indicator); def_radius_color = typedArray.getColor(R.styleable.CustomView5_def_radius_color, Color.BLACK); small_radius_color = typedArray.getColor(R.styleable.CustomView5_small_radius_color, Color.BLACK); big_radius_color = typedArray.getColor(R.styleable.CustomView5_big_radius_color, Color.BLACK); def_radius = typedArray.getDimension(R.styleable.CustomView5_def_radius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics())); small_def_radius = typedArray.getDimension(R.styleable.CustomView5_small_radius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getResources().getDisplayMetrics())); big_def_radius = typedArray.getDimension(R.styleable.CustomView5_big_radius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 18, getResources().getDisplayMetrics())); indicator_text_margin_top = typedArray.getDimension(R.styleable.CustomView5_indicator_text_margin_top, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 18, getResources().getDisplayMetrics())); indicator_def_color = typedArray.getColor(R.styleable.CustomView5_indicator_textcolor_def, Color.BLACK); indicator_select_color = typedArray.getColor(R.styleable.CustomView5_indicator_textcolor_select, Color.BLACK); indicator_text_size = typedArray.getDimension(R.styleable.CustomView5_indicator_textsize, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, getResources().getDisplayMetrics())); axis_size = typedArray.getDimension(R.styleable.CustomView5_axis_size, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics())); axis_def_color = typedArray.getColor(R.styleable.CustomView5_axis_def_color, Color.BLACK); axis_size_select_color = typedArray.getColor(R.styleable.CustomView5_axis_select_color, Color.BLACK); typedArray.recycle(); initPait(); } private void initPait() { def_radius_paint = new Paint(Paint.ANTI_ALIAS_FLAG); def_radius_paint.setColor(def_radius_color); // small_radius_paint = new Paint(Paint.ANTI_ALIAS_FLAG); small_radius_paint.setColor(small_radius_color); // big_radius_paint = new Paint(Paint.ANTI_ALIAS_FLAG); big_radius_paint.setColor(big_radius_color); // indicator_def_paint = new Paint(Paint.ANTI_ALIAS_FLAG); indicator_def_paint.setColor(indicator_def_color); indicator_def_paint.setTextSize(indicator_text_size); // indicator_select_paint = new Paint(Paint.ANTI_ALIAS_FLAG); indicator_select_paint.setColor(indicator_select_color); indicator_select_paint.setTextSize(indicator_text_size); // axis_def_paint = new Paint(Paint.ANTI_ALIAS_FLAG); axis_def_paint.setColor(axis_def_color); axis_def_paint.setStrokeWidth(axis_size); // axis_select_paint = new Paint(Paint.ANTI_ALIAS_FLAG); axis_select_paint.setColor(axis_size_select_color); axis_select_paint.setStrokeWidth(axis_size); axis_select_paint.setStrokeCap(Paint.Cap.ROUND); splitIndicator(); } private void splitIndicator() { if (!TextUtils.isEmpty(indicator_text)) { indicator = indicator_text.split("#"); if (indicator.length > 0) { indicator_first_text = indicator[0]; indicator_last_text = indicator[indicator.length - 1]; for (String s : indicator) { if (s.length() > max_text_size) { max_text_size = s.length(); } } } } } private CircleView[] view; @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); int width = getMeasuredWidth(widthMode, widthSize); int height = getMeasuredHeight(heightMode, heightSize); view=new CircleView[indicator.length]; for (int i=0;i<indicator.length;i++){ CircleView circleView=new CircleView(getContext(),new CircleView.CircleViewPanit(def_radius,def_radius_paint, small_def_radius,small_radius_paint, big_def_radius,big_radius_paint)); addView(circleView); view[i]=circleView; } setMeasuredDimension(width, height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { interval = (int) ((getWidth() - getPaddingRight() - getPaddingLeft() - firstIndicatorTextMarginLeft() - lastIndicatorTextMarginRight()) / (indicator.length - 1)); //canvas.drawCircle(cx, big_def_radius, def_radius, def_radius_paint); for(int i=0;i<view.length;i++){ int left = (int) ((getPaddingLeft() + firstIndicatorTextMarginLeft() + interval * i)-big_def_radius); int top=getPaddingTop(); view[i].layout(left,top,left+(int) big_def_radius*2,(int) (top+big_def_radius*2)); } } private float firstIndicatorTextMarginLeft() { float indicator_first_margin_left; if (indicator_first_text.length() >= INDICATOR_LINE_TEXT_SIZE) { indicator_first_margin_left = indicator_def_paint.measureText(indicator_first_text.substring(0, INDICATOR_LINE_TEXT_SIZE)) / 2; } else { indicator_first_margin_left = indicator_def_paint.measureText(indicator_first_text.substring(0, indicator_first_text.length()))/2; } return indicator_first_margin_left; } private float lastIndicatorTextMarginRight() { float indicator_last_margin_right; if (indicator_last_text.length() >= INDICATOR_LINE_TEXT_SIZE) { indicator_last_margin_right = indicator_def_paint.measureText(indicator_last_text.substring(0, INDICATOR_LINE_TEXT_SIZE)) / 2; } else { indicator_last_margin_right = indicator_def_paint.measureText(indicator_last_text.substring(0, indicator_last_text.length()))/2; } return indicator_last_margin_right; } private int getMeasuredHeight(int heightMode, int heightSize) { int height = 0; if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { int lines = 0; if (max_text_size % INDICATOR_LINE_TEXT_SIZE > 0) { lines = max_text_size / INDICATOR_LINE_TEXT_SIZE + 1; } else { lines = max_text_size / INDICATOR_LINE_TEXT_SIZE; } height = (int) (getPaddingTop() + big_def_radius * 2 + rowTextHeight() * lines + indicator_text_margin_top + getPaddingBottom()); } return height; } private int rowTextHeight() { indicator_def_paint.setTextSize(indicator_text_size); Paint.FontMetrics fontMetrics = indicator_def_paint.getFontMetrics(); return (int) Math.ceil((fontMetrics.bottom - fontMetrics.top)); } private int getMeasuredWidth(int widthMode, int widthSize) { int width = 0; if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { if (indicator.length > 0) { width = (int) (getPaddingLeft() + getPaddingRight() + firstIndicatorTextMarginLeft() + lastIndicatorTextMarginRight() + DEF_INTERVAL * (indicator.length - 1)); } } return width; } private boolean drawDef=true; @Override protected void onDraw(Canvas canvas) { drawAxis(canvas); drawCircle(canvas); drawText(canvas); } private void drawCircle(Canvas canvas) { for (int i=0;i<view.length;i++){ if(i<=currentStep){ view[i].drawExcircle(true); } } } private void drawText(Canvas canvas) { for (int i = 0; i < indicator.length; i++) { Paint paint; if(i<=currentStep){ paint=indicator_select_paint; }else{ paint=indicator_def_paint; } float cx = getPaddingLeft() + firstIndicatorTextMarginLeft() + (interval * i); // Paint.FontMetrics fontMetrics = paint.getFontMetrics(); float startY = big_def_radius * 2 +indicator_text_margin_top+ rowTextHeight() - fontMetrics.descent; // int text_length = indicator[i].length(); int lines; if (text_length % INDICATOR_LINE_TEXT_SIZE > 0) { lines = text_length / INDICATOR_LINE_TEXT_SIZE + 1; for (int j = 0; j < lines; j++) { if (INDICATOR_LINE_TEXT_SIZE * (j + 1) > text_length) { float line_text_with = paint.measureText(indicator[i].substring(INDICATOR_LINE_TEXT_SIZE * j, text_length)); canvas.drawText(indicator[i].substring(INDICATOR_LINE_TEXT_SIZE * j, text_length), cx - line_text_with / 2, startY + rowTextHeight() * j , paint); } else { float line_text_with = paint.measureText(indicator[i].substring(INDICATOR_LINE_TEXT_SIZE * j, INDICATOR_LINE_TEXT_SIZE * (j + 1))); canvas.drawText(indicator[i].substring(INDICATOR_LINE_TEXT_SIZE * j, INDICATOR_LINE_TEXT_SIZE * (j + 1)), cx - line_text_with / 2, startY + rowTextHeight() * j, paint); } } } else { lines = text_length / INDICATOR_LINE_TEXT_SIZE; for (int k = 0; k < lines; k++) { float line_text_with = paint.measureText(indicator[i].substring(INDICATOR_LINE_TEXT_SIZE * k, INDICATOR_LINE_TEXT_SIZE * (k + 1))); canvas.drawText(indicator[i].substring(INDICATOR_LINE_TEXT_SIZE * k, INDICATOR_LINE_TEXT_SIZE * (k + 1)), cx - line_text_with / 2, startY + rowTextHeight() * k, paint); } } } } private void drawAxis(Canvas canvas) { canvas.drawLine(getCenterCircleX(), big_def_radius, getWidth() - getPaddingRight() - lastIndicatorTextMarginRight(), big_def_radius, axis_def_paint); canvas.drawLine(getCenterCircleX(), big_def_radius, getCenterCircleX()+currentStep*interval, big_def_radius, axis_select_paint); } private float getCenterCircleX() { return firstIndicatorTextMarginLeft() + getPaddingLeft(); } private int currentStep=0; public void currentStep(int currentStep) { if(currentStep>=1 && currentStep<=indicator.length){ this.currentStep=currentStep-1; invalidate(); }else{ throw new IndexOutOfBoundsException("没哟这一步呀,,,"); } } }
import android.content.Context; import android.graphics.Camera; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; public class CircleView extends View { private CircleViewPanit panits; private Camera camera; private Matrix matrix; public CircleView(Context context, CircleViewPanit panit) { super(context); this.panits = panit; camera = new Camera(); matrix = new Matrix(); } public CircleView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } private boolean def = true; private boolean drawExcircle=false; public void drawExcircle(boolean drawExcircle){ this.drawExcircle=drawExcircle; invalidate(); } private final static int FPS = 1000 / 60; private int degrees=0; @Override protected void onDraw(Canvas canvas) { float cx=getWidth()/2; float cy=getHeight()/2; if (def) { def = false; canvas.drawCircle(getWidth() / 2, getHeight() / 2, panits.getDef_radius(), panits.getDef_paint()); } if(drawExcircle){ canvas.drawCircle(getWidth() / 2, getHeight() / 2, panits.getBig_def_radius(), panits.getBig_radius_paint()); canvas.drawCircle(getWidth() / 2, getHeight() / 2, panits.getSmall_def_radius(), panits.getSmall_radius_paint()); //3D动画 TODO /* camera.save(); camera.rotateZ(degrees); camera.getMatrix(matrix); camera.restore(); // matrix.preTranslate(-cx,-cy); matrix.postTranslate(cx,cy); // canvas.setMatrix(matrix); // canvas.drawArc(new RectF(0,0,cx*2,cy*2),0,10,true,panits.getSmall_radius_paint()); canvas.drawArc(new RectF(0,0,cx*2,cy*2),120,10,true,panits.getSmall_radius_paint()); canvas.drawArc(new RectF(0,0,cx*2,cy*2),240,10,true,panits.getSmall_radius_paint()); // degrees+=20; postInvalidateDelayed(FPS);*/ } } public static class CircleViewPanit { private float def_radius; private Paint def_paint; private float small_def_radius; private Paint small_radius_paint; private float big_def_radius; private Paint big_radius_paint; public CircleViewPanit(float def_radius, Paint def_paint, float small_def_radius, Paint small_radius_paint, float big_def_radius, Paint big_radius_paint) { this.def_radius = def_radius; this.def_paint = def_paint; this.small_def_radius = small_def_radius; this.small_radius_paint = small_radius_paint; this.big_def_radius = big_def_radius; this.big_radius_paint = big_radius_paint; } public float getDef_radius() { return def_radius; } public void setDef_radius(float def_radius) { this.def_radius = def_radius; } public Paint getDef_paint() { return def_paint; } public void setDef_paint(Paint def_paint) { this.def_paint = def_paint; } public float getSmall_def_radius() { return small_def_radius; } public void setSmall_def_radius(float small_def_radius) { this.small_def_radius = small_def_radius; } public Paint getSmall_radius_paint() { return small_radius_paint; } public void setSmall_radius_paint(Paint small_radius_paint) { this.small_radius_paint = small_radius_paint; } public float getBig_def_radius() { return big_def_radius; } public void setBig_def_radius(float big_def_radius) { this.big_def_radius = big_def_radius; } public Paint getBig_radius_paint() { return big_radius_paint; } public void setBig_radius_paint(Paint big_radius_paint) { this.big_radius_paint = big_radius_paint; } } }
<declare-styleable name="CustomView5"> <attr name="text_indicator" format="string"></attr> <attr name="def_radius" format="dimension"></attr> <attr name="def_radius_color" format="color"></attr> <attr name="small_radius" format="dimension"></attr> <attr name="small_radius_color" format="color"></attr> <attr name="big_radius" format="dimension"></attr> <attr name="big_radius_color" format="color"></attr> <attr name="indicator_text_margin_top" format="dimension"></attr> <attr name="indicator_textsize" format="dimension"></attr> <attr name="indicator_textcolor_def" format="color"></attr> <attr name="indicator_textcolor_select" format="color"></attr> <attr name="axis_def_color" format="color"></attr> <attr name="axis_select_color" format="color"></attr> <attr name="axis_size" format="dimension"></attr> </declare-styleable>
<com.example.cameracustomview.CustomView5 android:id="@+id/custom5" android:layout_marginTop="20dp" android:paddingRight="8dp" android:paddingLeft="8dp" android:layout_width="match_parent" android:layout_height="wrap_content" app:text_indicator="五一啦五一啦五一啦五一啦五一啦五一啦#吃饭吃饭吃饭吃饭吃饭吃饭吃饭吃饭吃饭吃饭#干啥干啥干啥干啥干啥干啥干啥干啥干啥#豆豆豆豆豆豆豆豆豆豆豆豆豆豆#球球球球球球球球球球球球球球球球球" app:axis_def_color="#aaaaaa" app:axis_size="4dp" app:axis_select_color="#288AFC" app:def_radius="6dp" app:def_radius_color="#aaaaaa" app:small_radius="8dp" app:small_radius_color="#288AFC" app:big_radius="12dp" app:big_radius_color="#fff" app:indicator_text_margin_top="10dp" app:indicator_textsize="15sp" app:indicator_textcolor_def="#000000" app:indicator_textcolor_select="#288AFC" />
![](https://i-blog.csdnimg.cn/blog_migrate/9997ac2f9c1787ee99c97a41a8676c53.png)