一、测量

===================================================================

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);// 斜线

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

效果图:

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201230150648950.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》浏览器打开:qq.cn.hn/FTe 开源分享

text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyNzYxMzk1,size_16,color_FFFFFF,t_70)

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);

效果图:

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

=======================================================================================

位置比例

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

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

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

//画围棋

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

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

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

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

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

mPaint.setColor(rightcolor);

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

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

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

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

效果图:

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

=============================================================================

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.效果图


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

7.解决第6步问题


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

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

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

paint.setShader(gradient);

shapeHolder.setPaint(paint);

效果图:

五.自定义属性

======================================================================

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();

}

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

=============================================================================

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

===============================================================================

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

八.源码

===================================================================

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(3minwidth, 3minwidth, useWidth/16, mPaint);

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

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

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

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

// mPaint.setColor(rightcolor);

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

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

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

// canvas.drawCircle(7minwidth, 5minwidth, 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;

Android自定义view之围棋动画,kotlin实现接口相关推荐

  1. Android自定义view之围棋动画

    Android自定义view之围棋动画 好久不见,最近公众号内粉丝要求上新一篇有点难度的自定义view文章,所以它来了!! 干货文,建议收藏 文章目录 Android自定义view之围棋动画 前言 完 ...

  2. Android自定义view之围棋动画,真牛皮

    @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, ...

  3. android view 渐变动画,Android自定义view渐变圆形动画

    本文实例为大家分享了Android自定义view渐变圆形动画的具体代码,供大家参考,具体内容如下 直接上效果图 自定义属性 attrs.xml文件 创建一个类 ProgressRing继承自 view ...

  4. android 自定义加载动画效果,Android自定义View实现loading动画加载效果

    项目开发中对Loading的处理是比较常见的,安卓系统提供的不太美观,引入第三发又太麻烦,这时候自己定义View来实现这个效果,并且进行封装抽取给项目提供统一的loading样式是最好的解决方式了. ...

  5. Android 自定义View之咖啡杯动画

    效果 大概思路 自定义view,直接继承view 复写onSizeChanged()方法,在此计算杯垫,杯子,烟雾效果的path 在onDraw()方法中,描绘杯垫,杯子 处理烟雾动画效果 画杯子 这 ...

  6. Android 自定义 View 之 LeavesLoading,kotlin入门书籍推荐

    // 计算移动因子 float fraction = (float) intervalTime / mLeafFloatTime; leaf.x = (1-fraction)*mProgressLen ...

  7. android下雨动画效果,Android 自定义View之下雨动画

    开始前先做个热身( ˘•灬•˘ ) 自己实现比较容易,但是到了要出博客整理思路,总结要点的时候就挠头,不知云所以,所以最简单的还是 如果对安卓UI有兴趣的朋友可以加我好友互相探讨, 思路 思路比较简单 ...

  8. android自定义view之星星动画

    先上效果图 其实上边效果分为几个部分,一个部分是多个小星星四处扩散,第二个部分是一个小星星从小变大,还有一个是实心圆的动画. 代码如下 第一:所有的小星星动画 public class StarVie ...

  9. 一篇文章带你走近Android自定义view

    系列文章目录 一篇文章带你走近Android自定义view 文章目录 系列文章目录 前言 一.为什么要自定义view 二.先看看一个超级简单的自定义view(三个构造函数) 三.了解手机的坐标系 四. ...

  10. android刷新时的圆形动画_Android自定义view渐变圆形动画

    本文实例为大家分享了Android自定义view渐变圆形动画的具体代码,供大家参考,具体内容如下 直接上效果图 自定义属性 attrs.xml文件 创建一个类 ProgressRing继承自 view ...

最新文章

  1. 固态器件理论(2)价和晶体结构
  2. python--函数
  3. 网站优化数据分析不建议你遗落这三点
  4. “面试不败计划”: java语言基础面试题(一)
  5. 网易数据中台建设实践
  6. guiconsole 操作命令
  7. sql中如何统计各种零件的总数量_数据蒋堂 | SQL是描述性语言?
  8. 获取本地IP和端口号的指令
  9. 反射在微信公众平台开发的应用
  10. phpmyadmin安全预防
  11. 设计思想之高内聚低耦合
  12. 抗衰落技术 — Rake接收和发射分集
  13. 火电厂给水串级控制系统仿真
  14. [bzoj5510]唱跳rap和篮球
  15. java excel转pdf
  16. 盛水容器问题php代码,盛水容器的形状如图2-13所示,已知各水面高程为▽1=1.15m,▽2=0.68m,▽3=0.44m...
  17. 支付宝与微信对账文件解析
  18. https请求报Connection reset问题
  19. 802.11ax简介
  20. 基于FPGA的数字钟——(三)时钟显示模块(数码管)

热门文章

  1. arcgis pro利用python进行空间插值
  2. SORPAS-焊接仿真模拟软件
  3. python循环结构高一信息技术会考_高一信息技术会考样题及参考答案
  4. ubuntu使用droidcam连接手机摄像头
  5. 算法导论终于看完了~
  6. 微软 Access数据库操作 中文教程
  7. 计量经济学计算机实验报告,计量经济学实验报告.doc
  8. 云播 Android,云播放(Air Playit)android版
  9. 一文了解新营销,数字经济时代如何以个人为中心重建品牌?
  10. 绝对纯净:龙行天下GHOST XP SP3软件自选安装纯净版 2010 V13.0 2010年6月