系列文章目录
Android自定义view之围棋动画(化繁为简)
文章最后有源码
文章目录
- 系列文章目录
- 前言
- 一、上篇文章的实现
- 二、第一个拓展(未优化)
- 效果:
- 思路:
- 1.在简单的实现中,仅借助了一个值来重复的循环得以实现动态的效果。而大多情况下动画是只显示一次的。而只让动效实现一次很简单:如下。
- 2.为了达到动画只执行一次的效果,需要借助一个布尔值。
- 此案例源码
- 三、第二个案例(本文重点)
- 效果
- 1.先实现一个球的直线运动
- 效果:
- 思路:
- 代码:
- 2.绘制另一个小球反方向运动
- 效果:
- 代码:
- 3.改变匀速
- 4.动画重复执行
- 效果:
- 思路:再添加另外的一个标识符,同理,将displacement的值变小。
- 5.源码
- 四、总结
前言
在上一篇文章中实现了简单的动态效果,假设这是一种动画的类型,那么能否像Android中的动画一样多个效果结合显示呢,这篇文章将以两个例子来进行拓展。第二个例子为围棋动画的精简版
上篇文章链接:Android自定义view之利用drawArc方法实现动态效果
一、上篇文章的实现
mSweep += SWEEP_INC;
if (mSweep > 360) {
mSweep -= 360;
}
//刷新View
invalidate();
二、第一个拓展(未优化)
效果:
思路:
1.在简单的实现中,仅借助了一个值来重复的循环得以实现动态的效果。而大多情况下动画是只显示一次的。而只让动效实现一次很简单:如下。
if (mSweep > 360) {
//mSweep -= 360;
}
如上,不将修改后的值复原即可。
这个效果的实现关键是将添加一个实心的样式画笔
mPaint1.setStyle(Paint.Style.FILL);
2.为了达到动画只执行一次的效果,需要借助一个布尔值。
private boolean viewContinue=true;
而逻辑代码也就变成了
if (viewContinue==true){
mSweep += SWEEP_INC;
if (mSweep > 360) {
mSweep1 += SWEEP_INC;
if (mSweep1>360){
viewContinue=false;
}
}
//刷新View
invalidate();
}
案例拓展:
- 可提供给用户一个方法使动画再执行一次,只需将mSweep,mSweep1改为0,并将viewContinue值改为true即可。
- 可放在数组中,进行多个效果的迭代。
此案例源码
public class MySampleView extends View {
private int mWidth;
private int mHeight;
private int useWidth, minwidth;
private Paint mPaint,mPaint1;
private Paint mFramePaint;
private RectF mBigOval;
private float mStart;
private float mSweep ,mSweep1;
private boolean viewContinue=true;
private static final float SWEEP_INC = 2;
public MySampleView(Context context) {
super(context);
}
public MySampleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MySampleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MySampleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private void init() {
initPaint();
}
private void initPaint() {
//初始化
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(0x88FF0000);
mPaint.setStrokeWidth(4);
mPaint1 = new Paint();
mPaint1.setAntiAlias(true);
mPaint1.setStyle(Paint.Style.FILL);
mPaint1.setColor(0x88FF0000);
//初始化
mFramePaint = new Paint();
mFramePaint.setAntiAlias(true);
mFramePaint.setStyle(Paint.Style.STROKE);
mFramePaint.setStrokeWidth(0);
}
@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;
}
}
@Override
protected void onDraw(Canvas canvas) {
init();
//定义一个最小标识
minwidth = useWidth / 10;
mBigOval = new RectF(minwidth, minwidth, minwidth*9, minwidth*9);
//绘制背景
canvas.drawColor(Color.WHITE);
canvas.drawRect(mBigOval, mFramePaint);
canvas.drawArc(mBigOval, mStart, mSweep, true, mPaint);
canvas.drawArc(mBigOval, mStart, mSweep1, true, mPaint1);
if (viewContinue==true){
mSweep += SWEEP_INC;
if (mSweep > 360) {
mSweep1 += SWEEP_INC;
if (mSweep1>360){
viewContinue=false;
}
}
//刷新View
invalidate();
}
}
}
三、第二个案例(本文重点)
相信很多朋友是看过博主这篇文章的:Android自定义view之围棋动画
效果
之前文章写得那么复杂是为了介绍一些Android自定义view的一些知识,而其实实现类似的效果极其的简单,那么直接开始。
1.先实现一个球的直线运动
效果:
思路:
借助一个偏移量改变绘制的小球位置。
代码:
displacement为偏移量
mBigOval = new RectF(minwidth+displacement, minwidth, minwidth*2+displacement, minwidth*2);
//绘制背景
canvas.drawColor(Color.WHITE);
//canvas.drawRect(mBigOval, mFramePaint);
canvas.drawArc(mBigOval, 0, 360, false, mPaint);
if (viewContinue){
displacement += SWEEP_INC;
if (displacement > minwidth*7) {
viewContinue=false;
}
//刷新View
invalidate();
}
2.绘制另一个小球反方向运动
效果:
代码:
mBigOval = new RectF(minwidth+displacement, minwidth, minwidth*2+displacement, minwidth*2);
mBigOval1 = new RectF(minwidth*8-displacement, minwidth, minwidth*9-displacement, minwidth*2);
//绘制背景
canvas.drawColor(Color.WHITE);
canvas.drawArc(mBigOval, 0, 360, false, mPaint);
canvas.drawArc(mBigOval1, 0, 360, false, mPaint1);
if (viewContinue){
displacement += SWEEP_INC;
if (displacement > minwidth*7) {
viewContinue=false;
}
//刷新View
invalidate();
}
3.改变匀速
根据情况增加displacement的值。如下
if (viewContinue){
displacement += SWEEP_INC;
if (displacement>minwidth*2){
displacement+=2;
}
if (displacement > minwidth*7) {
viewContinue=false;
}
//刷新View
invalidate();
}
4.动画重复执行
效果:
思路:再添加另外的一个标识符,同理,将displacement的值变小。
if (viewContinue){
displacement += SWEEP_INC;
if (displacement>minwidth*2){
displacement+=2;
}
if (displacement > minwidth*7) {
viewContinue=false;
viewContinue1=true;
}
//刷新View
invalidate();
}
if (viewContinue1){
displacement -= SWEEP_INC;
if (displacement<minwidth*5){
displacement-=2;
}
if (displacement <0) {
viewContinue1=false;
viewContinue=true;
}
//刷新View
invalidate();
}
如只需要执行一次来回,在viewContinue1的判断中不将viewContinue的值设为true。
5.源码
public class MySampleView extends View {
private int mWidth;
private int mHeight;
private int useWidth, minwidth;
private Paint mPaint,mPaint1;
private Paint mFramePaint;
private RectF mBigOval,mBigOval1;
private float displacement;
private boolean viewContinue=true,viewContinue1=false;
private static final float SWEEP_INC = 2;
public MySampleView(Context context) {
super(context);
}
public MySampleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MySampleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MySampleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private void init() {
initPaint();
}
private void initPaint() {
//初始化
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(0x88FF0000);
mPaint1 = new Paint();
mPaint1.setAntiAlias(true);
mPaint1.setStyle(Paint.Style.FILL);
mPaint1.setColor(0x88888888);
//初始化
mFramePaint = new Paint();
mFramePaint.setAntiAlias(true);
mFramePaint.setStyle(Paint.Style.STROKE);
mFramePaint.setStrokeWidth(0);
}
@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;
}
}
@Override
protected void onDraw(Canvas canvas) {
init();
//定义一个最小标识
minwidth = useWidth / 10;
mBigOval = new RectF(minwidth+displacement, minwidth, minwidth*2+displacement, minwidth*2);
mBigOval1 = new RectF(minwidth*8-displacement, minwidth, minwidth*9-displacement, minwidth*2);
//绘制背景
canvas.drawColor(Color.WHITE);
//canvas.drawRect(mBigOval, mFramePaint);
canvas.drawArc(mBigOval, 0, 360, false, mPaint);
canvas.drawArc(mBigOval1, 0, 360, false, mPaint1);
if (viewContinue){
displacement += SWEEP_INC;
if (displacement>minwidth*2){
displacement+=2;
}
if (displacement > minwidth*7) {
viewContinue=false;
viewContinue1=true;
}
//刷新View
invalidate();
}
if (viewContinue1){
displacement -= SWEEP_INC;
if (displacement<minwidth*5){
displacement-=2;
}
if (displacement <0) {
viewContinue1=false;
viewContinue=true;
}
//刷新View
invalidate();
}
}
}
四、总结
通过第二个案例实现,应该能够拓展开大家的思路,实现更加好的动态效果,相对于博主之前类似效果的文章,算是化繁为简了。想来应该能够对各位有所帮助。欢迎留言。