拿来就可用的项目下载地址:https://github.com/hloong/CricleBarDemo
一个月前我去面试的时候被人问到一个类似的问题,当时没答上来,一回家找了下资料:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0325/1603.html, 根据上面链接,我自己改了下半小时后实现了比较粗糙的效果,如下图,截图不太好见谅哈~
具体分解成4个部分: 底部一个灰色的空心描边圈,中间一个文字,2边各一个半圆来做向上的动画;
具体代码:
public class CircleBarTwoSider extends View {
private RectF mColorWheelRectangle = new RectF();//圆圈的矩形范围
private Paint mDefaultWheelPaint; //绘制底部灰色圆圈的画笔
private Paint mColorWheelPaintLeft; //绘制蓝色扇形的画笔 左边的
private Paint mColorWheelPaintRight; //绘制蓝色扇形的画笔 右边的
private Paint textPaint; //中间文字的画笔
private float mColorWheelRadius; //圆圈普通状态下的半径
private float circleStrokeWidth; //圆圈的线条粗细
private float pressExtraStrokeWidth;//按下状态下增加的圆圈线条增加的粗细
private String mText;//中间文字内容
private int mCount; //为了达到数字增加效果而添加的变量,他和mText其实代表一个意思
private float mSweepAnglePer; //为了达到蓝色扇形增加效果而添加的变量,他和mSweepAngle其实代表一个意思
private float mSweepAngle; //扇形弧度
private int mTextSize;//文字颜色
BarAnimation anim;//动画类
private int TIME = 300;
public CircleBarTwoSider(Context context) {
super(context);
init(null, 0);
}
public CircleBarTwoSider(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public CircleBarTwoSider(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs, defStyle);
}
private void init(AttributeSet attrs, int defStyle) {
circleStrokeWidth = MyUtils.dip2px(getContext(), 10);
pressExtraStrokeWidth = MyUtils.dip2px(getContext(), 2);
mTextSize = MyUtils.dip2px(getContext(), 20);
mColorWheelPaintRight = new Paint(Paint.ANTI_ALIAS_FLAG);
mColorWheelPaintRight.setColor(0xFF29a6f6);
mColorWheelPaintRight.setStyle(Paint.Style.STROKE);
mColorWheelPaintRight.setStrokeMiter(0);
// mColorWheelPaintRight.setStrokeCap(Paint.Cap.ROUND);//开启显示边缘为圆形
mColorWheelPaintRight.setStrokeWidth(circleStrokeWidth);
mColorWheelPaintLeft = new Paint(Paint.ANTI_ALIAS_FLAG);
mColorWheelPaintLeft.setColor(0xFF29a6f6);
mColorWheelPaintLeft.setStyle(Paint.Style.STROKE);
mColorWheelPaintLeft.setStrokeMiter(0);
// mColorWheelPaintLeft.setStrokeCap(Paint.Cap.ROUND);//开启显示边缘为圆形
mColorWheelPaintLeft.setStrokeWidth(circleStrokeWidth);
mDefaultWheelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDefaultWheelPaint.setColor(0xFFeeefef);
mDefaultWheelPaint.setStyle(Paint.Style.STROKE);
mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
textPaint.setColor(0xFF333333);
textPaint.setStyle(Style.FILL_AND_STROKE);
textPaint.setTextAlign(Align.LEFT);
textPaint.setTextSize(mTextSize);
mText = "0";
mSweepAngle = 1;
anim = new BarAnimation();
anim.setDuration(TIME);//设置动画时常
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawArc(mColorWheelRectangle, -90, 360, false, mDefaultWheelPaint);
canvas.drawArc(mColorWheelRectangle, 90, mSweepAnglePer, false, mColorWheelPaintRight);
canvas.drawArc(mColorWheelRectangle, 90, -mSweepAnglePer, false, mColorWheelPaintLeft);
Rect bounds = new Rect();
String textstr="可以买:"+mCount+"";
textPaint.getTextBounds(textstr, 0, textstr.length(), bounds);
canvas.drawText(textstr+"", (mColorWheelRectangle.centerX()) - (textPaint.measureText(textstr) / 2),
mColorWheelRectangle.centerY() + bounds.height() / 2,textPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
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) {
// TODO Auto-generated method stub
Log.i("hloong","call setPressed ");
if (pressed) {
mColorWheelPaintLeft.setColor(0xFF165da6);
mColorWheelPaintRight.setColor(0xFF165da6);
textPaint.setColor(0xFF070707);
mColorWheelPaintLeft.setStrokeWidth(circleStrokeWidth+pressExtraStrokeWidth);
mColorWheelPaintRight.setStrokeWidth(circleStrokeWidth+pressExtraStrokeWidth);
mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth+pressExtraStrokeWidth);
textPaint.setTextSize(mTextSize-pressExtraStrokeWidth);
} else {
mColorWheelPaintLeft.setColor(0xFF29a6f6);
mColorWheelPaintRight.setColor(0xFF29a6f6);
textPaint.setColor(0xFF333333);
mColorWheelPaintLeft.setStrokeWidth(circleStrokeWidth);
mColorWheelPaintRight.setStrokeWidth(circleStrokeWidth);
mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth);
textPaint.setTextSize(mTextSize);
}
super.setPressed(pressed);
this.invalidate();
}
public void startCustomAnimation(){
this.startAnimation(anim);
}
public void setText(String text){
mText = text;
this.startAnimation(anim);
}
public void setSweepAngle(float sweepAngle){
mSweepAngle = sweepAngle;
}
/**
* 动画
* @author long
* 2015-3-20下午2:11:22
*/
public class BarAnimation extends Animation {
/**
* Initializes expand collapse animation, has two types, collapse (1) and expand (0).
* @param view The view to animate
* @param type The type of animation: 0 will expand from gone and 0 size to visible and layout size defined in xml.
* 1 will collapse view and set to gone
* 动画类利用了applyTransformation参数中的interpolatedTime参数(从0到1)的变化特点,
* 实现了该View的某个属性随时间改变而改变。原理是在每次系统调用animation的applyTransformation()方法时,
* 改变mSweepAnglePer,mCount的值,
* 然后调用postInvalidate()不停的绘制view。
*/
public BarAnimation() {
}
@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();
}
}
}
Activity的代码:
public class MainActivity extends Activity {
private CircleBarTwoSider circleBar;
private CircleBar circleBar2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
circleBar = (CircleBarTwoSider) findViewById(R.id.circle);
circleBar.setSweepAngle(120);//设置角度
circleBar.setText("27000");
circleBar.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view){
circleBar.startCustomAnimation();
}
});
circleBar2 = (CircleBar) findViewById(R.id.circle2);
circleBar2.setSweepAngle(120);
circleBar2.setText("500");
circleBar2.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view){
circleBar2.startCustomAnimation();
}
});
}
}