我是靠谱客的博主 奋斗茉莉,这篇文章主要介绍Android自定义view之围棋动画效果的实现,现在分享给大家,希望可以做个参考。

前言

废话不多说直接开始

老规矩,文章最后有源码

完成效果图

棋子加渐变色

棋子不加渐变色

一、测量

1.获取宽高

复制代码
1
2
3
4
5
6
7
8
9
10
@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的倍数为标准点。

复制代码
1
minwidth = useWidth / 10;

二、绘制背景(棋盘)

1.初始化画笔

复制代码
1
2
3
4
5
6
mPaint = new Paint(); //创建画笔对象 mPaint.setColor(Color.BLACK); //设置画笔颜色 mPaint.setStyle(Paint.Style.FILL); //设置画笔模式为填充 mPaint.setStrokeWidth(4f); //设置画笔宽度为10px mPaint.setAntiAlias(true); //设置抗锯齿 mPaint.setAlpha(255); //设置画笔透明度

2.画棋盘

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//细的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);// 斜线

绘制完后,发现有点小瑕疵
效果图:

3.补棋盘瑕疵

复制代码
1
2
3
4
canvas.drawPoint(minwidth, minwidth, mPaint); canvas.drawPoint(9 * minwidth, minwidth, mPaint); canvas.drawPoint(minwidth, 9 * minwidth, mPaint); canvas.drawPoint(9 * minwidth, 9 * minwidth, mPaint);

效果图:

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

位置比例
(3,3)(3,5)(3,7)
(5,3)(5,5)(5,7)
(7,3)(7,5)(7,7)

复制代码
1
2
3
4
5
6
7
8
9
10
11
//画围棋 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);

效果图:

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

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

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

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

复制代码
1
2
3
4
5
6
7
8
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.棋子的创建

复制代码
1
2
3
4
5
6
7
8
9
10
11
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.动画的创建

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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.两个动画的同步执行

复制代码
1
2
3
AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bounceAnim).with(bounceAnim1); animatorSet.start();

6.效果图

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

7.解决第6步问题

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

复制代码
1
2
3
4
RadialGradient gradient = new RadialGradient(useWidth / 16f, useWidth / 16f, useWidth / 8f, color, Color.GRAY, Shader.TileMode.CLAMP); paint.setShader(gradient); shapeHolder.setPaint(paint);

效果图:

五.自定义属性

attrs文件:

复制代码
1
2
3
4
5
6
7
8
9
10
<declare-styleable name="WeiqiView"> <!-- 黑子颜色--> <attr name="leftscolor" format="reference|color"/> <!-- 白子颜色--> <attr name="rightscolor" format="reference|color"/> <!-- 棋盘颜色--> <attr name="qipancolor" format="reference|color"/> <!-- 动画时间--> <attr name="animalstime" format="integer"/> </declare-styleable>

java文件中获取

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/** * 获取自定义属性 */ 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(); }

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

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

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

八.源码

WeiqiView.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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

复制代码
1
2
3
4
5
6
7
8
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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
<resources> <declare-styleable name="WeiqiView"> <!-- 黑子颜色--> <attr name="leftscolor" format="reference|color"/> <!-- 白子颜色--> <attr name="rightscolor" format="reference|color"/> <!-- 棋盘颜色--> <attr name="qipancolor" format="reference|color"/> <!-- 动画时间--> <attr name="animalstime" format="integer"/> </declare-styleable> </resources>

布局调用

复制代码
1
2
3
4
5
<com.shenzhen.jimeng.lookui.UI.WeiqiView android:layout_centerInParent="true" android:id="@+id/weiqi" android:layout_width="400dp" android:layout_height="400dp"/>

activity文件中开启动画

复制代码
1
2
3
4
5
6
7
weiqi = (WeiqiView) findViewById(R.id.weiqi); weiqi.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { weiqi.startAnimation(); } });

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

最后

以上就是奋斗茉莉最近收集整理的关于Android自定义view之围棋动画效果的实现的全部内容,更多相关Android自定义view之围棋动画效果内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(119)

评论列表共有 0 条评论

立即
投稿
返回
顶部