Android自定义View之吃豆人动画(一)
2015-12-17 15:03
537 查看
- 先看效果图,但是图是没动的效果。代码的效果就是实现吃豆人一直吃豆子的效果。
自定义view的代码
这里view的宽高颜色都设置死了的,后面会将很多配置的东西抽到attrs.xml中。以便更多场景的使用。package com.simple_test_android.weiget.indicator; import com.nineoldandroids.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; import android.view.animation.LinearInterpolator; public class PcmanLoadingView extends View { private Paint mPcmanPaint, mCirclePaint, mEyePaint; private int width; private int height; protected Float translateX; protected Integer alpha; protected Float degrees1; protected Float degrees2; private boolean mHasAnimation; private int duration = 450; public PcmanLoadingView(Context context, AttributeSet attrs) { super(context, attrs); init(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { width = measureDimension(dp2px(70), widthMeasureSpec); height = measureDimension(dp2px(50), heightMeasureSpec); setMeasuredDimension(width, height); } /** * 测量方法 */ private int measureDimension(int defaultSize, int measureSpec) { int result = defaultSize; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else if (specMode == MeasureSpec.AT_MOST) { result = Math.min(defaultSize, specSize); } else { result = defaultSize; } return result; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawPcman(canvas); drawCircle(canvas); // 画眼睛 canvas.drawCircle(width / 3, height / 3, dp2px(2), mEyePaint); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (!mHasAnimation) { mHasAnimation = true; createAnimation(); } } private void init() { // 设置画吃豆人的画笔 mPcmanPaint = new Paint(); mPcmanPaint.setColor(Color.YELLOW); mPcmanPaint.setStyle(Paint.Style.FILL); mPcmanPaint.setAntiAlias(true); // 设置画豆子的画笔 mCirclePaint = new Paint(); mCirclePaint.setColor(Color.WHITE); mCirclePaint.setStyle(Paint.Style.FILL); mCirclePaint.setAntiAlias(true); // 设置画吃豆人眼睛的画笔 mEyePaint = new Paint(); mEyePaint.setColor(Color.BLACK); mEyePaint.setStyle(Paint.Style.FILL); mEyePaint.setAntiAlias(true); } /** * 画吃豆人 */ private void drawPcman(Canvas canvas) { float x = width / 2 - dp2px(10); float y = height / 2; canvas.save(); canvas.translate(x, y); canvas.rotate(degrees1); mPcmanPaint.setAlpha(255); RectF rectF1 = new RectF(-x / 1.7f, -y / 1.7f, x / 1.7f, y / 1.7f); canvas.drawArc(rectF1, 0, 270, true, mPcmanPaint); canvas.restore(); canvas.save(); canvas.translate(x, y); canvas.rotate(degrees2); mPcmanPaint.setAlpha(255); RectF rectF2 = new RectF(-x / 1.7f, -y / 1.7f, x / 1.7f, y / 1.7f); canvas.drawArc(rectF2, 90, 270, true, mPcmanPaint); canvas.restore(); } /** * 画豆子 */ private void drawCircle(Canvas canvas) { float radius = height / 11; mCirclePaint.setAlpha(alpha); canvas.drawCircle(translateX - (3 * radius), height / 2, radius, mCirclePaint); mCirclePaint.setAlpha(255); canvas.drawCircle(translateX, height / 2, radius, mCirclePaint); mCirclePaint.setAlpha(255); canvas.drawCircle(3 * radius + translateX, height / 2, radius, mCirclePaint); } /** * 创建动画 */ public void createAnimation() { float startT = width / 11; ValueAnimator translationAnim = ValueAnimator.ofFloat(width - startT, width / 2); translationAnim.setDuration(duration);// 设置动画的持续时间 translationAnim.setInterpolator(new LinearInterpolator());// 设置动画的速率为匀速 translationAnim.setRepeatCount(-1);// 设置动画重复播放次数,-1位一直重复 translationAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {// 动画绘制过程的监听 @Override public void onAnimationUpdate(ValueAnimator animation) { translateX = (Float) animation.getAnimatedValue(); postInvalidate();// 使用这个方法可以在非ui线程绘制view,当view依附在window上时,这个方法就会去调用外部线程 } }); translationAnim.start(); ValueAnimator alphaAnim = ValueAnimator.ofInt(255, 122); alphaAnim.setDuration(duration); alphaAnim.setRepeatCount(-1); alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { alpha = (Integer) animation.getAnimatedValue(); postInvalidate(); } }); alphaAnim.start(); ValueAnimator rotateAnim1 = ValueAnimator.ofFloat(0, 45, 0); rotateAnim1.setDuration(duration); rotateAnim1.setRepeatCount(-1); rotateAnim1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { degrees1 = (Float) animation.getAnimatedValue(); postInvalidate(); } }); rotateAnim1.start(); ValueAnimator rotateAnim2 = ValueAnimator.ofFloat(0, -45, 0); rotateAnim2.setDuration(duration); rotateAnim2.setRepeatCount(-1); rotateAnim2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { degrees2 = (Float) animation.getAnimatedValue(); postInvalidate(); } }); rotateAnim2.start(); } /** * dp转像素 */ private int dp2px(int dpValue) { return (int) (getContext().getResources().getDisplayMetrics().density * dpValue); } }
布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res/com.simple_test_android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#66000000" > <com.simple_test_android.weiget.indicator.PcmanLoadingView android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
还需要一个nineoldandroid.jar包,可以自行百度下载。
相关文章推荐
- 【Android开发基础】应用界面主题Theme使用方法
- 获取android版本号
- Android Root权限静默安装
- Android 解析doc、excel
- Android系统音量取消关联
- Android sqlite版本更新大致方案
- Android存储之SQLite数据库
- Android存储之SQLite数据库
- Android 尺寸单位转换和屏幕适配相关
- android常用应用的包名和startAcitivity名
- AndroidManifest.xml文件解析
- android 仿淘宝京东购物车 ListView嵌套CheckBox
- 浅谈android自定义view
- Android设备的USB通讯
- android开发仿iphone开关按钮动态效果
- Android中的AndroidAnnotations
- Android优化指南
- Android Intent的花样启动
- android 布局2层叠加 能隔着上层点到下层的处理方法
- Android ImageView ScaleTypes介绍