自定義View---實現半圓環形進度條
阿新 • • 發佈:2019-01-06
圖表控制元件很多,這個多少能跟圖表控制元件扯上邊吧。
廢話不多說,看圖:
上面可以看到效果,支援各種自定義,支援點選
這裡沒有用到 自定義屬性。有興趣的可以自己設定下。直接看程式碼
public class CircleBar extends View {
private static final String TAG = "CircleBar";
private RectF mColorWheelRectangle = new RectF();//圓圈的矩形範圍
private Paint mDefaultWheelPaint;////繪製底部灰色圓圈的畫筆
private Paint mColorWheelPaint;//繪製藍色扇形的畫筆
private Paint textPaint;//中間數值文字的畫筆
private Paint textDesPaint;//描述文字的畫筆
private float mColorWheelRadius;
private float circleStrokeWidth;//圓圈的線條粗細
private float pressExtraStrokeWidth;
private int mTextColor = getResources().getColor(R.color.blue);//預設文字顏色
private int mWheelColor = getResources().getColor(R.color.blue);//預設圓環顏色
private String mText;
private String mTextDes;//文字的描述
private int mTextDesSize;//描述文字的大小
private int mCount;//為了做動畫
private float mSweepAnglePer;//扇形弧度百分比
private float mSweepAngle;//扇形弧度
private int mTextSize;//文字大小
private int mDistance;// 上下文字的距離
BarAnimation anim;//動畫
private int TIME = 1000;//時間
public CircleBar(Context context) {
super(context);
init(null, 0);
}
public CircleBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public CircleBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs, defStyle);
}
private void init(AttributeSet attrs, int defStyle) {
//初始化一些值
circleStrokeWidth = dip2px(getContext(), 10);
pressExtraStrokeWidth = dip2px(getContext(), 2);
mTextSize = dip2px(getContext(), 30);
mTextDesSize = dip2px(getContext(), 15);
mDistance = dip2px(getContext(), 30);//文字距離
//外圓環的畫筆
mColorWheelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mColorWheelPaint.setColor(mWheelColor);
mColorWheelPaint.setStyle(Style.STROKE);
mColorWheelPaint.setStrokeWidth(circleStrokeWidth);//圓圈的線條粗細
mColorWheelPaint.setStrokeCap(Paint.Cap.ROUND);//開啟顯示邊緣為圓形
//預設圓的畫筆
mDefaultWheelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDefaultWheelPaint.setColor(getResources().getColor(R.color.gray));
mDefaultWheelPaint.setStyle(Style.STROKE);
mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth);//圓圈的線條粗細
mDefaultWheelPaint.setStrokeCap(Paint.Cap.ROUND);//開啟顯示邊緣為圓形
//數值的畫筆
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
textPaint.setColor(mTextColor);
textPaint.setStyle(Style.FILL_AND_STROKE);
textPaint.setTextAlign(Align.LEFT);
textPaint.setTextSize(mTextSize);
//描述文字的畫筆
textDesPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
textDesPaint.setColor(getResources().getColor(R.color.gray));
textDesPaint.setStyle(Style.FILL_AND_STROKE);
textDesPaint.setTextSize(mTextDesSize);
textDesPaint.setTextAlign(Align.LEFT);
mText = "0";
mTextDes = "本次考試";
mSweepAngle = 0;
anim = new BarAnimation();
anim.setDuration(TIME);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawArc(mColorWheelRectangle, -180, 180, false, mDefaultWheelPaint);//畫外接的圓環
canvas.drawArc(mColorWheelRectangle, -180, mSweepAnglePer, false, mColorWheelPaint);//畫圓環
Rect bounds = new Rect();
String textstr = mCount + "";
textPaint.getTextBounds(textstr, 0, textstr.length(), bounds);
textDesPaint.getTextBounds(mTextDes, 0, mTextDes.length(), bounds);
// drawText各個屬性的意思(文字,x座標,y座標,畫筆)
canvas.drawText(
textstr + "",
(mColorWheelRectangle.centerX())
- (textPaint.measureText(textstr) / 2),
mColorWheelRectangle.centerY() + bounds.height() / 2 - 50,
textPaint);
canvas.drawText(mTextDes,
(mColorWheelRectangle.centerX())
- (textDesPaint.measureText(mTextDes) / 2),
mColorWheelRectangle.centerY() + bounds.height() / 2 - 50 - mDistance
, textDesPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = getDefaultSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
int min = Math.min(width, height);
setMeasuredDimension(min, min);
mColorWheelRadius = min - circleStrokeWidth - pressExtraStrokeWidth;
mColorWheelRectangle.set(circleStrokeWidth + pressExtraStrokeWidth, circleStrokeWidth + pressExtraStrokeWidth,
mColorWheelRadius, mColorWheelRadius);
}
@Override
public void setPressed(boolean pressed) {
Toast.makeText(getContext(), mText, Toast.LENGTH_SHORT).show();
}
public void startCustomAnimation() {
this.startAnimation(anim);
}
public void setText(String text) {
mText = text;
this.startAnimation(anim);
}
public void setDesText(String text) {
mTextDes = text;
this.startAnimation(anim);
}
public void setTextColor(int color) {
mTextColor = color;
textPaint.setColor(mTextColor);
}
public void setSweepAngle(float sweepAngle) {
mSweepAngle = sweepAngle;
}
public void setWheelColor(int color) {
this.mColorWheelPaint.setColor(color);
}
public class BarAnimation extends Animation {
/**
* Initializes expand collapse animation, has two types, collapse (1) and expand (0).
* 1 will collapse view and set to gone
*/
public BarAnimation() {
}
// * 動畫類利用了applyTransformation引數中的interpolatedTime引數(從0到1)的變化特點,
// * 實現了該View的某個屬性隨時間改變而改變。原理是在每次系統呼叫animation的applyTransformation()方法時,
// * 改變mSweepAnglePer,mCount的值,
// * 然後呼叫postInvalidate()不停的繪製view。
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
//mSweepAnglePer,mCount這兩個屬性只是動畫過程中要用到的臨時屬性,
//mText和mSweepAngle才是動畫結束之後表示扇形弧度和中間數值的真實值。
if (interpolatedTime < 1.0f) {
mSweepAnglePer = interpolatedTime * mSweepAngle;
mCount = (int) (interpolatedTime * Float.parseFloat(mText));
} else {
mSweepAnglePer = mSweepAngle;
mCount = Integer.parseInt(mText);
}
postInvalidate();
}
}
public static int dip2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}
註釋非常清楚了。就不詳細說明了。直接在在佈局中使用。因為沒有自定義屬性,大家懂的。
這裡新增點選事件,通常繼承自view都有onClick和oLongClick事件的。這裡加進去就好
//監聽器類介面
public static abstract interface OnClickListener{
public abstract void onClick(); //單擊事件處理介面
}
OnClickListener listener=null; //監聽器類物件
//實現這個View的監聽器
public void setOnClickListener(OnClickListener listener){
this.listener = listener; //引用監聽器類物件,在這裡可以使用監聽器類的物件
}