本文实例实现一个如下图所示的Android自定义控件,可以直观地展示某个球队在某个赛季的积分数和胜场、负场、平局数
首先对画布进行区域划分,整个控件分上下两部分
上边是个大的圆环,圆环中间两行文字,没什么难度,选好圆心坐标和半径后直接绘制即可,绘制文字也是如此。
下部分是三个小的圆弧进度条,弧的末端绘制一个小的实心圆
首先选好坐标和半径,然后先绘制三个圆环作为弧形进度条的背景
之后从12点钟开始绘制进度弧,知道了圆环的圆心和半径,也知道了弧对应于12点钟和圆环圆心的偏移角度
通过三角函数可以计算出进度弧终点坐标,以进度弧终点坐标为圆心绘制一个小的实心圆即可
动画效果通过Handler的postDelayed方法触发重绘即可实现
在项目中的效果如图所示:
测试代码如下:
final Random random=new Random();
final ScoreBoardView myView=(ScoreBoardView)findViewById(R.id.custom_view);
myView.setonClickListener(new View.onClickListener(){
@Override
public void onClick(View v){
myView.setColor(Color.BLUE);
myView.setScore(random.nextInt(28));
myView.setWinDrawLose(random.nextInt(12),random.nextInt(15),random.nextInt(26));
}
});
完整代码如下:
public class ScoreBoardView extends View {
private Context context;
private int mColor;
private int mScore, mWinNumber, mDrawNumber, mLoseNumber;
private final int FULL_SCORE = 30;
DecelerateInterpolator mDecelerateInterpolator = new DecelerateInterpolator();
private int mDuration = 10;
private int mCurrentTime = 0;
private TypedValue typedValue;
private TypedValue typedValue1;
private Handler mHandler = new Handler();
private Runnable mAnimation = new Runnable() {
@Override
public void run() {
if (mCurrentTime < mDuration) {
mCurrentTime++;
ScoreBoardView.this.invalidate();
}
}
};
private Paint paint = new Paint();
private Paint paintText = new Paint();
public ScoreBoardView(Context context) {
super(context);
this.context=context;
init();
}
public ScoreBoardView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
init();
}
public ScoreBoardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context=context;
init();
}
private void init() {
mColor = Color.rgb(95, 112, 72);
mScore = 0;
mWinNumber = 0;
mDrawNumber = 0;
mLoseNumber = 0;
typedValue=new TypedValue();
typedValue1=new TypedValue();
context.getTheme().resolveAttribute(R.attr.maintextclor, typedValue, true);
context.getTheme().resolveAttribute(R.attr.maintextclor_reverse,typedValue1,true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float totalWidth = getWidth();
float totalHeight = getHeight();
float AnimCurrentValue =mDecelerateInterpolator.getInterpolation(1.0f * mCurrentTime / mDuration);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(4);
paint.setColor(mColor);
float score_radius = totalHeight * 1 / 5, score_circle_x = totalWidth / 2, score_circle_y = totalHeight / 3;
canvas.drawCircle(score_circle_x, score_circle_y, score_radius, paint);
paintText.setAntiAlias(true);
paintText.setStyle(Paint.Style.STROKE);
paintText.setTextAlign(Paint.Align.CENTER);
paintText.setTextSize(score_radius * 3 / 4);
paintText.setColor(getResources().getColor(typedValue.resourceId));
canvas.drawText("" + mScore, score_circle_x, score_circle_y, paintText);
paintText.setTextSize(score_radius * 1 / 4);
paintText.setAlpha(80);
canvas.drawText("积分", score_circle_x, score_circle_y + score_radius / 2, paintText);
paint.setStrokeWidth(4);
paint.setAlpha(255);
float small_radius = totalHeight / 10;
float[] circleXs = new float[]{totalWidth / 2 - score_radius * 3 / 2,
totalWidth / 2,
totalWidth / 2 + score_radius * 3 / 2};
float circleY = totalHeight * 3 / 4;
float[] theta_values = new float[]{360 * mWinNumber / FULL_SCORE* AnimCurrentValue,
360 * mDrawNumber / FULL_SCORE* AnimCurrentValue,
360 * mLoseNumber / FULL_SCORE* AnimCurrentValue};
paint.setColor(getResources().getColor(typedValue1.resourceId));
canvas.drawCircle(circleXs[0], circleY, small_radius, paint);//画WIN背景圆
canvas.drawCircle(circleXs[1], circleY, small_radius, paint);//画DRAW背景圆
canvas.drawCircle(circleXs[2], circleY, small_radius, paint);//画LOSE背景圆
paint.setColor(mColor);
canvas.drawArc(new RectF(circleXs[0] - small_radius,
circleY - small_radius,
circleXs[0] + small_radius,
circleY + small_radius),
270, theta_values[0], false, paint);//画WIN圆形进度条
canvas.drawArc(new RectF(circleXs[1] - small_radius,
circleY - small_radius,
circleXs[1] + small_radius,
circleY + small_radius),
270, theta_values[1], false, paint);//画DRAW圆形进度条
canvas.drawArc(new RectF(circleXs[2] - small_radius,
circleY - small_radius,
circleXs[2] + small_radius,
circleY + small_radius),
270, theta_values[2], false, paint);//画LOSE圆形进度条
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(circleXs[0] + small_radius * (float) Math.sin(theta_values[0] * Math.PI / 180),
circleY - small_radius * (float) Math.cos(theta_values[0] * Math.PI / 180), 6, paint);//画WIN末尾小圆点
canvas.drawCircle(circleXs[1] + small_radius * (float) Math.sin(theta_values[1] * Math.PI / 180),
circleY - small_radius * (float) Math.cos(theta_values[1] * Math.PI / 180), 6, paint);//画DRAW末尾小圆点
canvas.drawCircle(circleXs[2] + small_radius * (float) Math.sin(theta_values[2] * Math.PI / 180),
circleY - small_radius * (float) Math.cos(theta_values[2] * Math.PI / 180), 6, paint);//画LOSE末尾小圆点
paintText.setColor(getResources().getColor(typedValue.resourceId));
paintText.setTextSize(small_radius * 2 / 3);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float textbaseLineOffset = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
canvas.drawText("" + (int)(mWinNumber * AnimCurrentValue), circleXs[0], circleY + textbaseLineOffset, paintText);
canvas.drawText("" + (int)(mDrawNumber * AnimCurrentValue), circleXs[1], circleY + textbaseLineOffset, paintText);
canvas.drawText("" + (int)(mLoseNumber * AnimCurrentValue), circleXs[2], circleY + textbaseLineOffset, paintText);
paintText.setTextSize(small_radius * 4 / 9);
canvas.drawText("胜场", circleXs[0], circleY - small_radius*4/3, paintText);
canvas.drawText("平局", circleXs[1], circleY - small_radius*4/3, paintText);
canvas.drawText("负场", circleXs[2], circleY - small_radius*4/3, paintText);
mHandler.postDelayed(mAnimation, 20);//启动动画
}
public void setColor(int mColor) {
this.mColor = mColor;
invalidate();
}
public void setScore(int score) {
this.mScore = score;
invalidate();
}
public void setWinDrawLose(int win,int draw,int lose) {
this.mWinNumber = win;
this.mDrawNumber = draw;
this.mLoseNumber = lose;
mCurrentTime =0;
invalidate();
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。



