代码不难, 主要是比较烦, 各种计算, 各种初始化, 涉及ValueAnimator的使用
效果如下:
控件代码(比较长):
public class BackgoundView extends View {
int[] villegeX=new int[8];
int[] villegeY=new int[8];
int[] cityX=new int[8];
int[] cityY=new int[8];
int[] pointX=new int[8];
int[] pointY=new int[8];
int villegeCircleX,villegeCircleY,cityCircleX,cityCircleY,radius;
int bgVillegeColor,bgCityColor;
int circleX,circleY;
int width,height;
int state=0;
Paint paint=new Paint();
Paint bgPaint=new Paint();
ValueAnimator[] valueAnimatorsX=new ValueAnimator[8];
ValueAnimator[] valueAnimatorsY=new ValueAnimator[8];
ValueAnimator valueAnimatorCircleX=new ValueAnimator();
ValueAnimator valueAnimatorCircleY=new ValueAnimator();
ValueAnimator bgValueAnimator=new ValueAnimator();
ArgbEvaluator argbEvaluator=new ArgbEvaluator();
public BackgoundView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);
bgPaint.setAntiAlias(true);
bgPaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Log.e("w h", w + " " + h);
initConfig(w,h);
initVillegePoint();
initCityPoint();
initAnim();
initListener();
}
private void initListener() {
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (valueAnimatorCircleX.isRunning()) return;
if (state==0){
state=1;
valueAnimatorCircleX.setIntValues(villegeCircleX,cityCircleX);
valueAnimatorCircleY.setIntValues(villegeCircleY,cityCircleY);
bgValueAnimator.setIntValues(bgVillegeColor,bgCityColor);
for (int i=0;i<8;i++){
valueAnimatorsX[i].setIntValues(villegeX[i],cityX[i]);
valueAnimatorsY[i].setIntValues(villegeY[i],cityY[i]);
}
}else if (state==1){
state=0;
valueAnimatorCircleX.setIntValues(cityCircleX, villegeCircleX);
valueAnimatorCircleY.setIntValues(cityCircleY, villegeCircleY);
bgValueAnimator.setIntValues(bgCityColor,bgVillegeColor);
for (int i=0;i<8;i++){
valueAnimatorsX[i].setIntValues(cityX[i],villegeX[i]);
valueAnimatorsY[i].setIntValues(cityY[i],villegeY[i]);
}
}
for (int i=0;i<8;i++){
valueAnimatorsX[i].start();
valueAnimatorsY[i].start();
}
valueAnimatorCircleX.start();
valueAnimatorCircleY.start();
bgValueAnimator.start();
}
});
}
private void initConfig(int w,int h) {
width=w;
height=h;
radius=width/9;
bgPaint.setColor(Color.WHITE);
bgVillegeColor=0xff00ccff;
bgCityColor=Color.BLUE;
}
private void initAnim() {
for (int i=0;i<valueAnimatorsX.length;i++){
final int _i=i;
valueAnimatorsX[i]=new ValueAnimator();
valueAnimatorsX[i].setIntValues(0, villegeX[i]);
valueAnimatorsX[i].setDuration(550);
valueAnimatorsX[i].addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int x=(int)animation.getAnimatedValue();
pointX[_i]=x;
invalidate();
}
});
}
for (int i=0;i<valueAnimatorsY.length;i++){
final int _i=i;
valueAnimatorsY[i]=new ValueAnimator();
valueAnimatorsY[i].setIntValues(height / 2, villegeY[i]);
valueAnimatorsY[i].setDuration(550);
valueAnimatorsY[i].addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int y=(int)animation.getAnimatedValue();
pointY[_i]=y;
invalidate();
}
});
}
circleX=villegeCircleX;
valueAnimatorCircleX.setDuration(600);
valueAnimatorCircleX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
circleX = (int) animation.getAnimatedValue();
invalidate();
}
});
valueAnimatorCircleY.setDuration(600);
valueAnimatorCircleY.setIntValues(height / 8, villegeCircleY);
valueAnimatorCircleY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
circleY = (int) animation.getAnimatedValue();
invalidate();
}
});
bgValueAnimator.setDuration(400);
bgValueAnimator.setIntValues(bgPaint.getColor(),bgVillegeColor);
bgValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int bgColor=(int) animation.getAnimatedValue();
bgColor= (int) argbEvaluator.evaluate((bgColor-bgVillegeColor)/(bgCityColor-bgVillegeColor+0.0f),bgVillegeColor,bgCityColor);
bgPaint.setColor(bgColor);
invalidate();
}
});
for (int i=0;i<8;i++) {
valueAnimatorsX[i].start();
valueAnimatorsY[i].start();
}
valueAnimatorCircleY.start();
bgValueAnimator.start();
}
private void initCityPoint() {
cityX[0]= (int) (width*0.25/6);
cityX[1]= (int) (width*0.25/6);
cityX[2]= (int) (width*1.8/6);
cityX[3]= (int) (width*1.8/6);
cityX[4]= (int) (width*3.6/6);
cityX[5]= (int) (width*3.6/6);
cityX[6]= (int) (width*5.7/6);
cityX[7]= (int) (width*5.7/6);
int offset1=height/6;
cityY[0]=height/2+offset1;
cityY[1]=height/2+offset1/2;
cityY[2]=height/2+offset1/2;
cityY[3]=height/2-offset1;
cityY[4]=height/2-offset1;
cityY[5]=height/2;
cityY[6]=height/2;
cityY[7]=height/2+offset1;
cityCircleX=width*3/11;
cityCircleY= (int) (height/2-offset1*2);
}
private void initVillegePoint() {
villegeX[0]=width*0/11;
villegeX[1]=width*1/11;
villegeX[2]=width*2/11;
villegeX[3]=width*4/11;
villegeX[4]=width*6/11;
villegeX[5]=width*8/11;
villegeX[6]=width*11/11;
villegeX[7]=width*11/11;
int offset1=height/8;
villegeY[0]=height/2+offset1;
villegeY[1]=height/2-offset1;
villegeY[2]=height/2+offset1;
villegeY[3]=height/2;
villegeY[4]=height/2+offset1;
villegeY[5]=height/2-offset1/2;
villegeY[6]=height/2+offset1;
villegeY[7]=height/2+offset1;
villegeCircleX=width*9/11;
villegeCircleY= (int) (height/2-offset1*1.3);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(0, 0, width, height, bgPaint);
canvas.drawCircle(circleX, circleY, radius, paint);
for (int i=0;i<villegeX.length-1;i++){
canvas.drawLine(pointX[i], pointY[i], pointX[i + 1], pointY[i + 1], paint);
}
}
}