标签:界面设计 android 自定义控件 ui animation
一,实现思路
实现的效果:
此控件主要是模仿IReader打开书本翻转以及放大特效,在看文章之前可以找本书来翻转加深理解,呵呵,开个玩笑,进入正题。
实现的效果:
打开书本:
上层为cover,下层为content。cover播放放大翻转动画,content播放放大动画。
几个注意点:
1,动画的播放只能局限在父ViewGroup内部,放大到全屏该怎么进行?
A:使用克隆体添加到WindowManager中,然后去播放动画。
2,不能直接对WindowManager中的子控件播放动画,该怎么解决?
A:在WindowManger铺满一个AbsoluteLayout,然后再将克隆体cover添加到WindowManger中。
3,如果对任意位置的一张图片,放大到全屏,让位置刚好合适?
A:需要寻找到一个合适的缩放点。
二,具体实现
1,ContentScaleAnimation类,实现下层图片的缩放。如何寻找缩放点?
上图中
这里只演示怎么计算缩放点横坐标
x为缩放点横坐标
pw为parentWidth
ml为marginLeft
w为控件宽度
找到如下关系
缩放点到自身左边距离/缩放点到父控件左边的距离=缩放点自身右侧距离/缩放点到父控件右边的距离
(x-ml)/x=(w-(x-ml))/(pw-x)
计算得到x=ml*pw/(pw-w)
这里提供方法:
private float resolvePivotX(float margingLeft, int parentWidth, int width) { return (margingLeft * parentWidth) / (parentWidth - width); }
package huwei.com.bookviewdemo; import android.view.animation.Animation; import android.view.animation.Transformation; /** * Created by jayce on 15-2-4. */ public class ContentScaleAnimation extends Animation { private final float mFromX; private final float mToX; private final float mFromY; private final float mToY; private float mPivotX; private float mPivotY; private float mPivotXValue; private float mPivotYValue; private boolean mReverse; public ContentScaleAnimation(float mFromX, float mToX, float mFromY, float mToY, float mPivotXValue, float mPivotYValue, boolean mReverse) { this.mFromX = mFromX; this.mToX = mToX; this.mFromY = mFromY; this.mToY = mToY; this.mPivotXValue = mPivotXValue; this.mPivotYValue = mPivotYValue; this.mReverse = mReverse; } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { float sx = 1.0f; float sy = 1.0f; if (mFromX != 1.0f || mToX != 1.0f) { sx = mReverse ? mToX + (mFromX - mToX) * interpolatedTime : mFromX + (mToX - mFromX) * interpolatedTime; } if (mFromY != 1.0f || mToY != 1.0f) { sy = mReverse ? mToY + (mFromY - mToY) * interpolatedTime : mFromY + (mToY - mFromY) * interpolatedTime; } if (mPivotX == 0 && mPivotY == 0) { t.getMatrix().setScale(sx, sy); } else { t.getMatrix().setScale(sx, sy, mPivotX, mPivotY); } } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mPivotX = resolvePivotX(mPivotXValue, parentWidth, width); mPivotY = resolvePivoY(mPivotYValue, parentHeight, height); } private float resolvePivotX(float margingLeft, int parentWidth, int width) { return (margingLeft * parentWidth) / (parentWidth - width); } private float resolvePivoY(float marginTop, int parentHeight, int height) { return (marginTop * parentHeight) / (parentHeight - height); } public void reverse() { mReverse = !mReverse; } public boolean getMReverse() { return mReverse; } }
,2,Rotate3DAnimation类,实现参考apiDemo中的Rotate3dAnimation,在此基础上进行修改,实现翻转和缩放动画。
这里需要绕Y轴旋转180度,在翻转前需要将物体移动到y轴上,然后再移回去。
matrix.preTranslate(-mPivotXValue, 0); //在进行rotateY之前需要移动物体,让物体左边与Y轴对齐 matrix.postTranslate(mPivotXValue, 0); //还原物体位置
package huwei.com.bookviewdemo; import android.graphics.Camera; import android.graphics.Matrix; import android.view.animation.Animation; import android.view.animation.Transformation; /** * @author jayce * @date 2015/2/3 */ public class Rotate3DAnimation extends Animation { private Camera mCamera; private final float mFromDegrees; private final float mToDegrees; private final float mPivotXValue; private final float mPivotYValue; //private final float mDepthZ; //不需要用到此参数 private final float scaleTimes; private boolean mReverse; private float mPivotX; //缩放点X private float mPivotY; //缩放点Y /** * cover 动画构造方法,一边放大,一边翻转 * @param mFromDegrees * @param mToDegrees * @param mPivotXValue 控件左上角X * @param mPivotYValue 控件左上角Y * @param scaleTimes 缩放比例 * @param mReverse 动画是否逆向进行 */ public Rotate3DAnimation(float mFromDegrees, float mToDegrees, float mPivotXValue, float mPivotYValue, float scaleTimes, boolean mReverse) { this.mFromDegrees = mFromDegrees; this.mToDegrees = mToDegrees; this.mPivotXValue = mPivotXValue; this.mPivotYValue = mPivotYValue; this.scaleTimes = scaleTimes; this.mReverse = mReverse; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); mPivotX = resolvePivotX(mPivotXValue, parentWidth, width); //计算缩放点X mPivotY = resolvePivoY(mPivotYValue, parentHeight, height); //计算缩放点Y } /** * 执行顺序 matrix.preTranslate() --> camera.rotateY(degrees) --> matrix.postTranslate() --> matrix.postScale() * @param interpolatedTime * @param t */ @Override protected void applyTransformation(float interpolatedTime, Transformation t) { float degrees = mReverse ? mToDegrees + (mFromDegrees - mToDegrees) * interpolatedTime : mFromDegrees + (mToDegrees - mFromDegrees) * interpolatedTime; final Matrix matrix = t.getMatrix(); final Camera camera = mCamera; camera.save(); camera.rotateY(degrees); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-mPivotXValue, 0); //在进行rotateY之前需要移动物体,让物体左边与Y轴对齐 matrix.postTranslate(mPivotXValue, 0); //还原物体位置 if (mReverse) { matrix.postScale(1 + (scaleTimes - 1) * (1.0f - interpolatedTime), 1 + (scaleTimes - 1) * (1.0f - interpolatedTime), mPivotX, mPivotY); } else { matrix.postScale(1 + (scaleTimes - 1) * interpolatedTime, 1 + (scaleTimes - 1) * interpolatedTime, mPivotX, mPivotY); } } private float resolvePivotX(float margingLeft, int parentWidth, int width) { return (margingLeft * parentWidth) / (parentWidth - width); } private float resolvePivoY(float marginTop, int parentHeight, int height) { return (marginTop * parentHeight) / (parentHeight - height); } public void reverse() { mReverse = !mReverse; } public boolean getMReverse() { return mReverse; } }
标签:界面设计 android 自定义控件 ui animation
原文地址:http://blog.csdn.net/huweigoodboy/article/details/43671011