android自定义View---6个小圆组成的加载动画
2018-01-30 14:57
871 查看
项目里面的一个 加载动画,是要做成一个按钮形状
这个是需求图
![](https://oscdn.geek-share.com/Uploads/Images/Content/201801/397fb584b9ca7fb5b81baf9e38edacb9)
这个是展示效果图:初步的图
![](https://oscdn.geek-share.com/Uploads/Images/Content/201801/329c8ca0dd55d9026c044eb2b5cab7a6)
这是我最后实现的效果图
![](https://oscdn.geek-share.com/Uploads/Images/Content/201801/dfd4a31c0febe26f452d77d1ac3a887b)
首先我们说一下这个6个小球的旋转,我们都可以看出,这个六个小球也是在画一个大圆,所以我们只要把大圆的半径确定了之后,在计算每个小圆的角度,再不断的进行绘制是不是就可以了?对,没错,就是这样的。那么在这之前我们是不是应该找到中间大圆的中心点,并且计算出半径啊。
其实这个中心点就是屏幕对角线的一半,请看代码
动画效果代码
最后的代码
这个是需求图
这个是展示效果图:初步的图
这是我最后实现的效果图
首先我们说一下这个6个小球的旋转,我们都可以看出,这个六个小球也是在画一个大圆,所以我们只要把大圆的半径确定了之后,在计算每个小圆的角度,再不断的进行绘制是不是就可以了?对,没错,就是这样的。那么在这之前我们是不是应该找到中间大圆的中心点,并且计算出半径啊。
其实这个中心点就是屏幕对角线的一半,请看代码
/** * 计算屏幕中心点 */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mCenterX = w / 2f; mCenterY = h / 2f; //屏幕对角线一半 mDiagonaalDist = (float) Math.sqrt((w * w + h * h) / 2); }
/** * 画六个小圆 */ private void drawCircle(Canvas canvas) { //得到每个小圆的间隔角度 float rotationAngle = (float) (2 * Math.PI / 6); //画6个小圆 for (int i = 0; i < 6; i++) { /** * 计算角度 * x = r*cos(a) * y = r*sin(a); */ double angle = i * rotationAngle + mCurrentRotationAngle;//不断的更新圆点的坐标位置 //因为最开始的计算是再屏幕的左上角,计算出每个圆点位置之后加上中心点X或者Y坐标就可以了 float cx = (float) (mCurrentRotationRadius * Math.cos(angle) + mCenterX); float cy = (float) (mCurrentRotationRadius * Math.sin(angle) + mCenterY); mpaint.setColor(mCircleColors);//设置小圆的颜色 canvas.drawCircle(cx, cy, mCircleRadius, mpaint); } }
动画效果代码
/** * 第一个动画:小圆旋转动画 * 要素:不断的绘制小圆--》控制左边---- 旋转的角度、公转的半径 */ private class RotationState extends SplashState { public RotationState() { //动画初始化 //花1600ms,计算某个时间当前的角度是多少:0~2π中的某个值 valueAnimator = ValueAnimator.ofFloat(0, (float) Math.PI * 2); valueAnimator.setInterpolator(new LinearInterpolator());//设置插值器,主要是为了小圆点的旋转时间平均,让动画没有停顿。 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {//回调监听 @Override public void onAnimationUpdate(ValueAnimator animation) { //得到某个时间点计算的结果 ----这个时间带你当前大圆旋转的角度 mCurrentRotationAngle = (float) animation.getAnimatedValue(); postInvalidate(); } }); valueAnimator.setDuration(mRotationDuration);//动画时间 valueAnimator.setRepeatCount(ValueAnimator.INFINITE);//不断重复 valueAnimator.start();//启动 }
最后的代码
public class SplashView extends View { private float mRotationRadius = 120;//大圆(里面包含很多小圆)的半径 private float mCircleRadius = 18;//每一个小圆的半径 private int mCircleColors;//小圆颜色列表,在initialize方法里面初始化 private long mRotationDuration = 1600;//大圆和小圆旋转时间 private int mSplashBgColor = Color.WHITE;//整体的背景颜色 /** * 参数,保存了一些绘制状态,会被动态的改变 */ //空心圆的初始半径 private float mHoleRadius = 0f; //当前大圆旋转角度 private float mCurrentRotationAngle = 0f; //当前大圆的半径 private float mCurrentRotationRadius = mRotationRadius; //绘制圆的画笔 private Paint mpaint = new Paint(); //绘制背景的画笔 private Paint mPaintBackground = new Paint(); //屏幕中心点坐标 private float mCenterX; private float mCenterY; //屏幕对角线一半 private float mDiagonaalDist; private ValueAnimator valueAnimator; /** * 如果要写再xml里面就需要三个构造函数 * * @param context */ public SplashView(Context context) { super(context); init(); } public SplashView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public SplashView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } @TargetApi(Build.VERSION_CODES.M) private void init() { mpaint.setAntiAlias(true);//初始化画小圆的画笔 mPaintBackground.setAntiAlias(true);//初始化画背景的画笔 mPaintBackground.setStyle(Paint.Style.STROKE);//设置样式 mPaintBackground.setColor(mSplashBgColor);//设置背景画笔颜色 mCircleColors = getContext().getColor(R.color.mc_cir_progress_button_red);//设置小圆的颜色 } /** * 计算屏幕中心点 */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mCenterX = w / 2f; mCenterY = h / 2f; //屏幕对角线一半 mDiagonaalDist = (float) Math.sqrt((w * w + h * h) / 2); } @Override protected void onDraw(Canvas canvas) { //绘制动画第一个动画 if (mstate == null) { mstate = new RotationState(); } mstate.drawState(canvas); super.onDraw(canvas); } private abstract class SplashState { public abstract void drawState(Canvas canvas); } //这里利用一个设计模式:策略模式 private SplashState mstate = null; /** * 第一个动画:小圆旋转动画 * 要素:不断的绘制小圆--》控制左边---- 旋转的角度、公转的半径 */ private class RotationState extends SplashState { public RotationState() { //动画初始化 //花1600ms,计算某个时间当前的角度是多少:0~2π中的某个值 valueAnimator = ValueAnimator.ofFloat(0, (float) Math.PI * 2); valueAnimator.setInterpolator(new LinearInterpolator());//设置插值器,主要是为了小圆点的旋转时间平均,让动画没有停顿。 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {//回调监听 @Override public void onAnimationUpdate(ValueAnimator animation) { //得到某个时间点计算的结果 ----这个时间带你当前大圆旋转的角度 mCurrentRotationAngle = (float) animation.getAnimatedValue(); postInvalidate(); } }); valueAnimator.setDuration(mRotationDuration);//动画时间 valueAnimator.setRepeatCount(ValueAnimator.INFINITE);//不断重复 valueAnimator.start();//启动 } public void cancle() { valueAnimator.cancel(); } @Override public void drawState(Canvas canvas) { //绘制动画 //1擦黑板 drawBackground(canvas); //2.画小圆 drawCircle(canvas); } } private void drawBackground(Canvas canvas) { if (mHoleRadius > 0f) { //得到画笔的宽度 = 对角线/2-空心圆的半径 float strokewidth = mDiagonaalDist - mHoleRadius; mPaintBackground.setStrokeWidth(strokewidth);//设置画笔的宽度 //画圆的半径 = 空心圆半径+画笔宽度/2 float radius = mHoleRadius + strokewidth / 2; //空心圆的半径越来越大 画笔的宽度就越来也小 canvas.drawCircle(mCenterX, mCenterY, radius, mPaintBackground); } else { canvas.drawColor(mSplashBgColor); } } /** * 画六个小圆 */ private void drawCircle(Canvas canvas) { //得到每个小圆的间隔角度 float rotationAngle = (float) (2 * Math.PI / 6); //画6个小圆 for (int i = 0; i < 6; i++) { /** * 计算角度 * x = r*cos(a) * y = r*sin(a); */ double angle = i * rotationAngle + mCurrentRotationAngle;//不断的更新圆点的坐标位置 //因为最开始的计算是再屏幕的左上角,计算出每个圆点位置之后加上中心点X或者Y坐标就可以了 float cx = (float) (mCurrentRotationRadius * Math.cos(angle) + mCenterX); float cy = (float) (mCurrentRotationRadius * Math.sin(angle) + mCenterY); mpaint.setColor(mCircleColors);//设置小圆的颜色 canvas.drawCircle(cx, cy, mCircleRadius, mpaint); } } }
相关文章推荐
- Android自定义View--加载动画
- Android自定义view利用Xfermode实现动态文字加载动画
- Android自定义view实现阻尼效果的加载动画
- android 自定义view 类似loadding从下往上加载的动画
- android学习-----自定义View 加载动画
- android自定义view之加载动画ColorBall
- Android自定义View实现loading动画加载效果
- 【Android自定义View实战】之仿百度加载动画,一种优雅的Loading方式
- android控件使用---recycleview自定义上拉加载,和加载多个布局及加入动画
- Android自定义View二(加载进度动画)
- Android上拉刷新下拉加载XRefreshView集成以及自定义GIF动画
- Android自定义加载loading view动画组件
- [置顶] Android 自定义view之 Xfermode 制作动态文字加载动画
- Android 自定义View修炼-自定义加载进度动画XCLoadingImageView
- Android自定义view-高仿小米视频加载动画效果
- android自定义view之加载动画ColorBall
- Android 自定义SurfaceView实现加载GIF动画
- android自定义View基础系列一(模仿365日历PC版加载动画)
- Android自定义View系列之Path绘制仿支付宝支付成功动画
- Android 自定义View之仿华为圆形加载进度条