IReader打开书本,关闭书本动画的自定义控件

一,实现思路

实现的效果:
此控件主要是模仿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;
    }
}


下载地址(4.0以及以下不支持) setX()导致动画无法播放

下载地址(支持到2.2及以上)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值