当前位置:   article > 正文

android自定义改变宽度动画,Android自定义view之围棋动画效果的实现

android 棋子移动效果

前言

废话不多说直接开始

老规矩,文章最后有源码

完成效果图

棋子加渐变色

f461d9665769450d5f282cabe8df7981.gif

棋子不加渐变色

5a67a3a0d4fe8ea4b8a9fecfea9d550e.gif

一、测量

1.获取宽高

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

mWidth = w;

mHeight = h;

useWidth = mWidth;

if (mWidth > mHeight) {

useWidth = mHeight;

}

}

2.定义测量最小长度

将布局分为10份。以minwidth的1,3,5,7,9的倍数为标准点。

minwidth = useWidth / 10;

二、绘制背景(棋盘)

1.初始化画笔

mPaint = new Paint(); //创建画笔对象

mPaint.setColor(Color.BLACK); //设置画笔颜色

mPaint.setStyle(Paint.Style.FILL); //设置画笔模式为填充

mPaint.setStrokeWidth(4f); //设置画笔宽度为10px

mPaint.setAntiAlias(true); //设置抗锯齿

mPaint.setAlpha(255); //设置画笔透明度

2.画棋盘

//细的X轴

canvas.drawLine(minwidth, 3 * minwidth, 9 * minwidth, 3 * minwidth, mPaint);// 斜线

canvas.drawLine(minwidth, 5 * minwidth, 9 * minwidth, 5 * minwidth, mPaint);// 斜线

canvas.drawLine(minwidth, 7 * minwidth, 9 * minwidth, 7 * minwidth, mPaint);// 斜线

//细的y轴

canvas.drawLine(3 * minwidth, minwidth, 3 * minwidth, 9 * minwidth, mPaint);// 斜线

canvas.drawLine(5 * minwidth, minwidth, 5 * minwidth, 9 * minwidth, mPaint);// 斜线

canvas.drawLine(7 * minwidth, minwidth, 7 * minwidth, 9 * minwidth, mPaint);// 斜线

mPaint.setStrokeWidth(8f);

//粗的X轴(边框)

canvas.drawLine(minwidth, minwidth, 9 * minwidth, minwidth, mPaint);// 斜线

canvas.drawLine(minwidth, 9 * minwidth, 9 * minwidth, 9 * minwidth, mPaint);// 斜线

//粗的y轴(边框)

canvas.drawLine(minwidth, minwidth, minwidth, 9 * minwidth, mPaint);// 斜线

canvas.drawLine(9 * minwidth, minwidth, 9 * minwidth, 9 * minwidth, mPaint);// 斜线

绘制完后,发现有点小瑕疵

效果图:

44cdc90467b096b9fbcb4d75f6cdc33a.png

3.补棋盘瑕疵

canvas.drawPoint(minwidth, minwidth, mPaint);

canvas.drawPoint(9 * minwidth, minwidth, mPaint);

canvas.drawPoint(minwidth, 9 * minwidth, mPaint);

canvas.drawPoint(9 * minwidth, 9 * minwidth, mPaint);

效果图:

3da6b314a1eace2a42eacf5576b86980.png

三.画个不可改变的棋子(以便于了解动画移动位置)

位置比例

(3,3)(3,5)(3,7)

(5,3)(5,5)(5,7)

(7,3)(7,5)(7,7)

//画围棋

canvas.drawCircle(3*minwidth, 3*minwidth, useWidth/16, mPaint);

canvas.drawCircle(3*minwidth, 7*minwidth, useWidth/16, mPaint);

canvas.drawCircle(5*minwidth, 5*minwidth, useWidth/16, mPaint);

canvas.drawCircle(7*minwidth, 3*minwidth, useWidth/16, mPaint);

canvas.drawCircle(7*minwidth, 7*minwidth, useWidth/16, mPaint);

mPaint.setColor(rightcolor);

canvas.drawCircle(3*minwidth, 5*minwidth, useWidth/16, mPaint);

canvas.drawCircle(5*minwidth, 3*minwidth, useWidth/16, mPaint);

canvas.drawCircle(5*minwidth, 7*minwidth, useWidth/16, mPaint);

canvas.drawCircle(7*minwidth, 5*minwidth, useWidth/16, mPaint);

效果图:

21e050512fe93bb3396acd60f720dcf6.png

四.为动画开始做准备以及动画

1.三个辅助类为动画做准备(参数模仿Android官方Demo)

主要为get set构造,代码会贴到最后

2.自定义该接口实例来控制动画的更新计算表达式

public class XYEvaluator implements TypeEvaluator {

public Object evaluate(float fraction, Object startValue, Object endValue) {

XYHolder startXY = (XYHolder) startValue;

XYHolder endXY = (XYHolder) endValue;

return new XYHolder(startXY.getX() + fraction * (endXY.getX() - startXY.getX()),

startXY.getY() + fraction * (endXY.getY() - startXY.getY()));

}

}

3.棋子的创建

private ShapeHolder createBall(float x, float y, int color) {

OvalShape circle = new OvalShape();

circle.resize(useWidth / 8f, useWidth / 8f);

ShapeDrawable drawable = new ShapeDrawable(circle);

ShapeHolder shapeHolder = new ShapeHolder(drawable);

shapeHolder.setX(x - useWidth / 16f);

shapeHolder.setY(y - useWidth / 16f);

Paint paint = drawable.getPaint();

paint.setColor(color);

return shapeHolder;

}

4.动画的创建

private void createAnimation() {

if (bounceAnim == null) {

XYHolder lstartXY = new XYHolder(3 * minwidth - useWidth / 16f, 3 * minwidth - useWidth / 16f);

XYHolder processXY = new XYHolder(7 * minwidth - useWidth / 16f, 3 * minwidth - useWidth / 16f);

XYHolder lendXY = new XYHolder(7 * minwidth - useWidth / 16f, 7 * minwidth - useWidth / 16f);

bounceAnim = ObjectAnimator.ofObject(ballHolder, "xY",

new XYEvaluator(), lstartXY, processXY, lendXY, lstartXY);

bounceAnim.setDuration(animaltime);

bounceAnim.setRepeatCount(ObjectAnimator.INFINITE);

bounceAnim.setRepeatMode(ObjectAnimator.RESTART);

bounceAnim.addUpdateListener(this);

}

if (bounceAnim1 == null) {

XYHolder lstartXY = new XYHolder(7 * minwidth - useWidth / 16f, 7 * minwidth - useWidth / 16f);

XYHolder processXY = new XYHolder(3 * minwidth - useWidth / 16f, 7 * minwidth - useWidth / 16f);

XYHolder lendXY = new XYHolder(3 * minwidth - useWidth / 16f, 3 * minwidth - useWidth / 16f);

bounceAnim1 = ObjectAnimator.ofObject(ballHolder1, "xY",

new XYEvaluator(), lstartXY, processXY, lendXY, lstartXY);

bounceAnim1.setDuration(animaltime);

bounceAnim1.setRepeatCount(ObjectAnimator.INFINITE);

bounceAnim1.setRepeatMode(ObjectAnimator.RESTART);

bounceAnim1.addUpdateListener(this);

}

}

5.两个动画的同步执行

AnimatorSet animatorSet = new AnimatorSet();

animatorSet.play(bounceAnim).with(bounceAnim1);

animatorSet.start();

6.效果图

d59162fe66923d2989abf5dc84c319d5.gif

视觉效果:感觉白子不太明显

7.解决第6步问题

在棋子的创建方法中添加渐变色

RadialGradient gradient = new RadialGradient(useWidth / 16f, useWidth / 16f,

useWidth / 8f, color, Color.GRAY, Shader.TileMode.CLAMP);

paint.setShader(gradient);

shapeHolder.setPaint(paint);

效果图:

a3236ddddc4852094a8dfb267e9bf9e6.gif

五.自定义属性

attrs文件:

java文件中获取

/**

* 获取自定义属性

*/

private void initCustomAttrs(Context context, AttributeSet attrs) {

//获取自定义属性

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.WeiqiView);

//获取颜色

leftcolor = ta.getColor(R.styleable.WeiqiView_leftscolor, Color.BLACK);

rightcolor = ta.getColor(R.styleable.WeiqiView_rightscolor, Color.WHITE);

qipancolor = ta.getColor(R.styleable.WeiqiView_qipancolor, Color.BLACK);

//获取动画时间

animaltime = ta.getInt(R.styleable.WeiqiView_animalstime, 2000);

//回收

ta.recycle();

}

六.自定义属性设置后运行效果

a48d4ae2c06e1b1c1f8afbbbde340001.gif

七.小改变,视觉效果就不一样了!

然后,把背景注释,像不像那些等待动画?

1201bc7e73297b1e8861726c8615ccc0.gif

八.源码

WeiqiView.java

public class WeiqiView extends View implements ValueAnimator.AnimatorUpdateListener {

private Paint mPaint;

private int mWidth;

private int mHeight;

private int useWidth, minwidth;

private int leftcolor;

private int rightcolor;

private int qipancolor;

private int animaltime;

//画一个圆(棋子)

ValueAnimator bounceAnim, bounceAnim1 = null;

ShapeHolder ball, ball1 = null;

QiziXYHolder ballHolder, ballHolder1 = null;

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

public WeiqiView(Context context) {

this(context, null);

}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

public WeiqiView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

public WeiqiView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

this(context, attrs, defStyleAttr, 0);

initCustomAttrs(context, attrs);

}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

public WeiqiView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

}

private void init() {

initPaint();

}

/**

* 获取自定义属性

*/

private void initCustomAttrs(Context context, AttributeSet attrs) {

//获取自定义属性。

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.WeiqiView);

//获取颜色

leftcolor = ta.getColor(R.styleable.WeiqiView_leftscolor, Color.BLACK);

rightcolor = ta.getColor(R.styleable.WeiqiView_rightscolor, Color.WHITE);

qipancolor = ta.getColor(R.styleable.WeiqiView_qipancolor, Color.BLACK);

animaltime = ta.getInt(R.styleable.WeiqiView_animalstime, 2000);

//回收

ta.recycle();

}

/**

* 初始化画笔

*/

private void initPaint() {

mPaint = new Paint(); //创建画笔对象

mPaint.setColor(Color.BLACK); //设置画笔颜色

mPaint.setStyle(Paint.Style.FILL); //设置画笔模式为填充

mPaint.setStrokeWidth(4f); //设置画笔宽度为10px

mPaint.setAntiAlias(true); //设置抗锯齿

mPaint.setAlpha(255); //设置画笔透明度

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

mWidth = w;

mHeight = h;

useWidth = mWidth;

if (mWidth > mHeight) {

useWidth = mHeight;

}

}

@RequiresApi(api = Build.VERSION_CODES.KITKAT)

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

init();

minwidth = useWidth / 10;

mPaint.setColor(qipancolor);

if (ball == null) {

ball = createBall(3 * minwidth, 3 * minwidth, leftcolor);

ballHolder = new QiziXYHolder(ball);

}

if (ball1 == null) {

ball1 = createBall(7 * minwidth, 7 * minwidth, rightcolor);

ballHolder1 = new QiziXYHolder(ball1);

}

//细的X轴

canvas.drawLine(minwidth, 3 * minwidth, 9 * minwidth, 3 * minwidth, mPaint);// 斜线

canvas.drawLine(minwidth, 5 * minwidth, 9 * minwidth, 5 * minwidth, mPaint);// 斜线

canvas.drawLine(minwidth, 7 * minwidth, 9 * minwidth, 7 * minwidth, mPaint);// 斜线

//细的y轴

canvas.drawLine(3 * minwidth, minwidth, 3 * minwidth, 9 * minwidth, mPaint);// 斜线

canvas.drawLine(5 * minwidth, minwidth, 5 * minwidth, 9 * minwidth, mPaint);// 斜线

canvas.drawLine(7 * minwidth, minwidth, 7 * minwidth, 9 * minwidth, mPaint);// 斜线

mPaint.setStrokeWidth(8f);

//粗的X轴(边框)

canvas.drawLine(minwidth, minwidth, 9 * minwidth, minwidth, mPaint);// 斜线

canvas.drawLine(minwidth, 9 * minwidth, 9 * minwidth, 9 * minwidth, mPaint);// 斜线

//粗的y轴(边框)

canvas.drawLine(minwidth, minwidth, minwidth, 9 * minwidth, mPaint);// 斜线

canvas.drawLine(9 * minwidth, minwidth, 9 * minwidth, 9 * minwidth, mPaint);// 斜线

//补瑕疵

canvas.drawPoint(minwidth, minwidth, mPaint);

canvas.drawPoint(9 * minwidth, minwidth, mPaint);

canvas.drawPoint(minwidth, 9 * minwidth, mPaint);

canvas.drawPoint(9 * minwidth, 9 * minwidth, mPaint);

// //画围棋

// canvas.drawCircle(3*minwidth, 3*minwidth, useWidth/16, mPaint);

// canvas.drawCircle(3*minwidth, 7*minwidth, useWidth/16, mPaint);

// canvas.drawCircle(5*minwidth, 5*minwidth, useWidth/16, mPaint);

// canvas.drawCircle(7*minwidth, 3*minwidth, useWidth/16, mPaint);

// canvas.drawCircle(7*minwidth, 7*minwidth, useWidth/16, mPaint);

// mPaint.setColor(rightcolor);

// canvas.drawCircle(3*minwidth, 5*minwidth, useWidth/16, mPaint);

// canvas.drawCircle(5*minwidth, 3*minwidth, useWidth/16, mPaint);

// canvas.drawCircle(5*minwidth, 7*minwidth, useWidth/16, mPaint);

// canvas.drawCircle(7*minwidth, 5*minwidth, useWidth/16, mPaint);

canvas.save();

canvas.translate(ball.getX(), ball.getY());

ball.getShape().draw(canvas);

canvas.restore();

canvas.save();

canvas.translate(ball1.getX(), ball1.getY());

ball1.getShape().draw(canvas);

canvas.restore();

}

private ShapeHolder createBall(float x, float y, int color) {

OvalShape circle = new OvalShape();

circle.resize(useWidth / 8f, useWidth / 8f);

ShapeDrawable drawable = new ShapeDrawable(circle);

ShapeHolder shapeHolder = new ShapeHolder(drawable);

shapeHolder.setX(x - useWidth / 16f);

shapeHolder.setY(y - useWidth / 16f);

Paint paint = drawable.getPaint();

paint.setColor(color);

RadialGradient gradient = new RadialGradient(useWidth / 16f, useWidth / 16f,

useWidth / 8f, color, Color.GRAY, Shader.TileMode.CLAMP);

paint.setShader(gradient);

shapeHolder.setPaint(paint);

return shapeHolder;

}

private void createAnimation() {

if (bounceAnim == null) {

XYHolder lstartXY = new XYHolder(3 * minwidth - useWidth / 16f, 3 * minwidth - useWidth / 16f);

XYHolder processXY = new XYHolder(7 * minwidth - useWidth / 16f, 3 * minwidth - useWidth / 16f);

XYHolder lendXY = new XYHolder(7 * minwidth - useWidth / 16f, 7 * minwidth - useWidth / 16f);

bounceAnim = ObjectAnimator.ofObject(ballHolder, "xY",

new XYEvaluator(), lstartXY, processXY, lendXY, lstartXY);

bounceAnim.setDuration(animaltime);

bounceAnim.setRepeatCount(ObjectAnimator.INFINITE);

bounceAnim.setRepeatMode(ObjectAnimator.RESTART);

bounceAnim.addUpdateListener(this);

}

if (bounceAnim1 == null) {

XYHolder lstartXY = new XYHolder(7 * minwidth - useWidth / 16f, 7 * minwidth - useWidth / 16f);

XYHolder processXY = new XYHolder(3 * minwidth - useWidth / 16f, 7 * minwidth - useWidth / 16f);

XYHolder lendXY = new XYHolder(3 * minwidth - useWidth / 16f, 3 * minwidth - useWidth / 16f);

bounceAnim1 = ObjectAnimator.ofObject(ballHolder1, "xY",

new XYEvaluator(), lstartXY, processXY, lendXY, lstartXY);

bounceAnim1.setDuration(animaltime);

bounceAnim1.setRepeatCount(ObjectAnimator.INFINITE);

bounceAnim1.setRepeatMode(ObjectAnimator.RESTART);

bounceAnim1.addUpdateListener(this);

}

}

public void startAnimation() {

createAnimation();

AnimatorSet animatorSet = new AnimatorSet();

animatorSet.play(bounceAnim).with(bounceAnim1);

animatorSet.start();

}

@Override

public void onAnimationUpdate(ValueAnimator animation) {

invalidate();

}

}

QiziXYHolder.java

public class QiziXYHolder {

private ShapeHolder mBall;

public QiziXYHolder(ShapeHolder ball) {

mBall = ball;

}

public void setXY(XYHolder xyHolder) {

mBall.setX(xyHolder.getX());

mBall.setY(xyHolder.getY());

}

public XYHolder getXY() {

return new XYHolder(mBall.getX(), mBall.getY());

}

}

ShapeHolder.java

public class ShapeHolder {

private float x = 0, y = 0;

private ShapeDrawable shape;

private int color;

private RadialGradient gradient;

private float alpha = 1f;

private Paint paint;

public void setPaint(Paint value) {

paint = value;

}

public Paint getPaint() {

return paint;

}

public void setX(float value) {

x = value;

}

public float getX() {

return x;

}

public void setY(float value) {

y = value;

}

public float getY() {

return y;

}

public void setShape(ShapeDrawable value) {

shape = value;

}

public ShapeDrawable getShape() {

return shape;

}

public int getColor() {

return color;

}

public void setColor(int value) {

shape.getPaint().setColor(value);

color = value;

}

public void setGradient(RadialGradient value) {

gradient = value;

}

public RadialGradient getGradient() {

return gradient;

}

public void setAlpha(float alpha) {

this.alpha = alpha;

shape.setAlpha((int)((alpha * 255f) + .5f));

}

public float getWidth() {

return shape.getShape().getWidth();

}

public void setWidth(float width) {

Shape s = shape.getShape();

s.resize(width, s.getHeight());

}

public float getHeight() {

return shape.getShape().getHeight();

}

public void setHeight(float height) {

Shape s = shape.getShape();

s.resize(s.getWidth(), height);

}

public ShapeHolder(ShapeDrawable s) {

shape = s;

}

}

XYEvaluator.java

public class XYEvaluator implements TypeEvaluator {

public Object evaluate(float fraction, Object startValue, Object endValue) {

XYHolder startXY = (XYHolder) startValue;

XYHolder endXY = (XYHolder) endValue;

return new XYHolder(startXY.getX() + fraction * (endXY.getX() - startXY.getX()),

startXY.getY() + fraction * (endXY.getY() - startXY.getY()));

}

}

XYHolder.java

public class XYHolder {

private float mX;

private float mY;

public XYHolder(float x, float y) {

mX = x;

mY = y;

}

public float getX() {

return mX;

}

public void setX(float x) {

mX = x;

}

public float getY() {

return mY;

}

public void setY(float y) {

mY = y;

}

}

attrs.xml

布局调用

android:layout_centerInParent="true"

android:id="@+id/weiqi"

android:layout_width="400dp"

android:layout_height="400dp"/>

activity文件中开启动画

weiqi = (WeiqiView) findViewById(R.id.weiqi);

weiqi.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

weiqi.startAnimation();

}

});

到此这篇关于Android自定义view之围棋动画效果的实现的文章就介绍到这了,更多相关Android自定义view围棋动画内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/81479
推荐阅读
相关标签
  

闽ICP备14008679号