您的位置:首页 > 其它

自定义LoadingView大全之转动立方体

2016-07-06 22:51 218 查看
回声的千结百绕

而守候的是

执着

一仓央嘉措

概述

这篇是自定义LoadingView大全的第四篇博客,也是写得最累最费心费脑的一篇博客,我现在眼睛还疲惫的难受。作为一名程序猿,我在表达能力方面比较欠缺,我希望我能够把它讲清楚。在讲解的过程当中我都会配以图片加以说明。

上图吧:



第一次看到这样的效果,是不是让你眼前一亮,格逼一下就上去了。你可能会问,实现起来会不会很难啊,可以明确的说实现不难,需要你有足够的耐心。

具体实现

分析

在开始动手写代码之前,我习惯会去先分析转动的立方体该怎么去绘制和添加动画。先来看看下面这张示意图:



先来看看大的立方体,它是由9个面组成,分成了三个阶段。

第一阶段:从A运动到B

数字标出1,2,3,4,5左上运动,每个点的X,Y都在减少;6,7,8,9右下运动,每个点的X,Y坐标都在增大。左右两边长的立方体总共运动了菱形的一个边长,那么可以知道每个长的立方体运动了边长的二分之一。

第二阶段:从B运动到C

1,2面右上运动,每个点的X坐标增大,Y减少;3,4,5,6面没有运动;7,8,9面左下运动,X坐标减少,Y增大。如果把1,2面看成一个立方体则运动了一个菱形的边长。7,8,9面同理。

第三阶段:从C运动到A

3,4,5,7,8,9面左上运动X,Y坐标都在减少;1,2,6面右下运动X,Y都在增大且运动了半个菱形的边长。

比较复杂的是需要去绘制大的立方体A,可以把A分离成9个面,绘制每个面,那么我们先来分析一个面:



设定a为30°,对应的三角形高度为h,那么另一条长度为√3h(根号)。

把A画到坐标系上,如图:



这样是不是就很明了,我们只需要知道中心点坐标,h的长度就可以画出A(大的立方体)。OK,只要画出A,后面的就简单了。

编码

获取中心点坐标以及h的长度:

centerX = w / 2;

mWidth = Math.min(w, h);

//平行四边形的最小角度为30度
mItemWidth = mWidth / 16 * (float) Math.sqrt(3);

mItemHeight = mWidth / 16;


在ondraw方法中处理不同阶段的绘制:

if (mValueAnimator >= 0 && mValueAnimator < (1.0f / 3)) {
//绘制第一阶段
drawStage1(canvas, mValueAnimator);
if (mShadow) {
drawShadow1(canvas, mValueAnimator);
}
} else if (mValueAnimator >= (1.0f / 3) && mValueAnimator < (1.0f / 3 * 2)) {
//绘制第二阶段
drawStage2(canvas, mValueAnimator);
if (mShadow) {
drawShadow2(canvas, mValueAnimator);
}
} else if (mValueAnimator >= (1.0f / 3 * 2) && mValueAnimator <= 1.0f) {
//绘制第三阶段
drawStage3(canvas, mValueAnimator);
if (mShadow) {
drawShadow3(canvas, mValueAnimator);
}
}


mValueAnimator 取值(0.0f~1.0f);mShadow是否显示阴影。

第一阶段绘制:

//这里2个立方体都在移动,每个立方体在X轴方向移动的距离为mItemWidth/2
float moveX = mItemWidth / 2.0f * valueAnimator / (1.0f / 3);
float moveY = mItemHeight / 2.0f * valueAnimator / (1.0f / 3);

//顺时针绘制平行四边形
//向后移动在X 方向 减少   Y方向减少
Path p = new Path();
p.moveTo(centerX - 2 * mItemWidth - moveX, 4 * mItemHeight - moveY);
p.lineTo(centerX - mItemWidth - moveX, 3 * mItemHeight - moveY);
p.lineTo(centerX - moveX, 4 * mItemHeight - moveY);
p.lineTo(centerX - mItemWidth - moveX, 5 * mItemHeight - moveY);
p.close();
canvas.drawPath(p, mPaint);

//向后移动在X 方向 减少   Y方向减少
p.reset();
p.moveTo(centerX - 2 * mItemWidth - moveX, 4 * mItemHeight - moveY);
p.lineTo(centerX - mItemWidth - moveX, 5 * mItemHeight - moveY);
p.lineTo(centerX - mItemWidth - moveX, 7 * mItemHeight - moveY);
p.lineTo(centerX - 2 * mItemWidth - moveX, 6 * mItemHeight - moveY);
p.close();
canvas.drawPath(p, mPaintLeft);

//向前移动在X 方向 X方向增加   Y方向增加
p.reset();
p.moveTo(centerX + moveX, 4 * mItemHeight + moveY);
p.lineTo(centerX - mItemWidth + moveX, 3 * mItemHeight + moveY);
p.lineTo(centerX + moveX, 2 * mItemHeight + moveY);
p.lineTo(centerX + mItemWidth + moveX, 3 * mItemHeight + moveY);
p.close();
canvas.drawPath(p, mPaint);

//向前移动在X 方向 X方向增加   Y方向增加
p.reset();
p.moveTo(centerX + moveX, 4 * mItemHeight + moveY);
p.lineTo(centerX + mItemWidth + moveX, 3 * mItemHeight + moveY);
p.lineTo(centerX + 2 * mItemWidth + moveX, 4 * mItemHeight + moveY);
p.lineTo(centerX + mItemWidth + moveX, 5 * mItemHeight + moveY);
p.close();
canvas.drawPath(p, mPaint);

//向前移动在X 方向 X方向增加   Y方向增加
p.reset();
p.moveTo(centerX + moveX, 4 * mItemHeight + moveY);
p.lineTo(centerX + mItemWidth + moveX, 5 * mItemHeight + moveY);
p.lineTo(centerX + mItemWidth + moveX, 7 * mItemHeight + moveY);
p.lineTo(centerX + moveX, 6 * mItemHeight + moveY);
p.close();
canvas.drawPath(p, mPaintLeft);

//向前移动在X 方向 X方向增加   Y方向增加
p.reset();
p.moveTo(centerX + mItemWidth + moveX, 5 * mItemHeight + moveY);
p.lineTo(centerX + 2 * mItemWidth + moveX, 4 * mItemHeight + moveY);
p.lineTo(centerX + 2 * mItemWidth + moveX, 6 * mItemHeight + moveY);
p.lineTo(centerX + mItemWidth + moveX, 7 * mItemHeight + moveY);
p.close();
canvas.drawPath(p, mPaintRight);

//向后移动在X 方向 减少   Y方向减少
p.reset();
p.moveTo(centerX - mItemWidth - moveX, 5 * mItemHeight - moveY);
p.lineTo(centerX - moveX, 4 * mItemHeight - moveY);
p.lineTo(centerX + mItemWidth - moveX, 5 * mItemHeight - moveY);
p.lineTo(centerX - moveX, 6 * mItemHeight - moveY);
p.close();
canvas.drawPath(p, mPaint);

//向后移动在X 方向 减少   Y方向减少
p.reset();
p.moveTo(centerX - mItemWidth - moveX, 5 * mItemHeight - moveY);
p.lineTo(centerX - moveX, 6 * mItemHeight - moveY);
p.lineTo(centerX - moveX, 8 * mItemHeight - moveY);
p.lineTo(centerX - mItemWidth - moveX, 7 * mItemHeight - moveY);
p.close();
canvas.drawPath(p, mPaintLeft);

//向后移动在X 方向 减少   Y方向减少
p.reset();
p.moveTo(centerX - moveX, 6 * mItemHeight - moveY);
p.lineTo(centerX + mItemWidth - moveX, 5 * mItemHeight - moveY);
p.lineTo(centerX + mItemWidth - moveX, 7 * mItemHeight - moveY);
p.lineTo(centerX - moveX, 8 * mItemHeight - moveY);
p.close();
canvas.drawPath(p, mPaintRight);


在代码中我对每个面的变化都有相应的注释,应该都是可以看懂的。

绘制一个立方体效果图:



能够绘制立方体的变化,阴影层的绘制就非常简单了。

源码地址,如果你喜欢就给我star,再次感谢大家的关注。

自定义LoadingView大全
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: