Android 书本打开和关闭动画

栏目: Android · 发布时间: 7年前

内容简介:我偶尔一次发现掌阅的打开书本动画不错,然后度娘了一下,发现一个链接:一共就是2个类+2个跳转动画
Android 书本打开和关闭动画

Github地址 ,欢迎点赞,fork

我偶尔一次发现掌阅的打开书本动画不错,然后度娘了一下,发现一个链接: download.csdn.net/download/we… , 下载下来学习膜拜了一下,发现有些动画过度和掌阅有点不一样,所以我就拷贝源码并略微修改了下,如果想看原著,上面已经贴了,这个效果是GIF,真机更流畅一些.

一共就是2个类+2个跳转动画

首先,看看 BookOpenView

public class BookOpenView extends FrameLayout implements
        Animator.AnimatorListener {

    private BookOpenViewValue mStartValue;
    private AnimatorSet mAnimatorSet1, mAnimatorSet2;
    private TextView tv_book_name;
    private ImageView iv_book_content;
    private View iv_book_cover;
    private ConstraintLayout cl_book_container;
    // 默认打开书本动画是关闭的
    private AtomicBoolean isOpened = new AtomicBoolean(false);

    public BookOpenView(@NonNull Context context) {
        super(context);
        initView(context);
    }

    public BookOpenView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    public BookOpenView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    public void initView(Context context) {

        LayoutInflater.from(context).inflate(R.layout.book_open_close, this);
        setBackgroundColor(Color.TRANSPARENT);
        tv_book_name = (TextView) findViewById(R.id.tv_book_name);
        iv_book_content = (ImageView) findViewById(R.id.iv_book_content);
        iv_book_cover = (View) findViewById(R.id.iv_book_cover);
        cl_book_container = (ConstraintLayout) findViewById(R.id.cl_book_container);

    }

    /**
     * 开启动画
     */
    public synchronized void startAnim(final BookOpenViewValue startValue, BookOpenViewValue endValue) {
        if (!isOpened.get()) {

            if (!TextUtils.isEmpty(startValue.getBookName())){
                tv_book_name.setText(startValue.getBookName());
            }

            // 如果有图片,可以在此给 iv_book_cover 设置,图解尽量不要太大,10K以内为佳

            mStartValue = startValue;
            System.out.println("startAnim===========mStartValue: " + mStartValue.toString() + " ========startValue: " + startValue.toString());
            LayoutParams layoutParams = (LayoutParams) cl_book_container.getLayoutParams();
            layoutParams.width = startValue.getRight() - startValue.getLeft();
            layoutParams.height = startValue.getBottom() - startValue.getTop();
            cl_book_container.setLayoutParams(layoutParams);
            iv_book_content.setLayoutParams(layoutParams);

            cl_book_container.setTranslationX(startValue.getLeft());
            cl_book_container.setTranslationY(startValue.getTop());

            // 计算缩放的起始位置和缩放中心点
            final int x1 = ((layoutParams.width * (endValue.getRight() - layoutParams.width))
                    - layoutParams.width * (endValue.getRight() - startValue.getRight()))
                    / (endValue.getRight() - layoutParams.width);

            final float sX1 = (layoutParams.width - x1 + endValue.getRight() - startValue.getRight()) * 1.0f / (layoutParams.width - x1);
            final float sX2 = (x1 + startValue.getLeft()) * 1.0f / x1;

            final float sX = Math.max(sX1, sX2);
            final int y1 = ((layoutParams.height * (endValue.getBottom() - layoutParams.height))
                    - layoutParams.height * (endValue.getBottom() - startValue.getBottom()))
                    / (endValue.getBottom() - layoutParams.height);
            final float sY1 = (layoutParams.height - y1 + endValue.getBottom() - startValue.getBottom()) * 1.0f / (layoutParams.height - y1);
            final float sY2 = (y1 + startValue.getTop()) * 1.0f / y1;
            final float sY = Math.max(sY1, sY2);
            mStartValue.setX(x1);
            mStartValue.setsX(sX);
            mStartValue.setY(y1);
            mStartValue.setsY(sY);

            cl_book_container.setPivotX(0);
            cl_book_container.setPivotY(y1);

            // 对 封面进行缩放
            ObjectAnimator scaleX = ObjectAnimator.ofFloat(cl_book_container,
                    "scaleX", 1.0f, sX * 0.8f);
            scaleX.setDuration(1000);
            ObjectAnimator scaleY = ObjectAnimator.ofFloat(cl_book_container,
                    "scaleY", 1.0f, sY);
            scaleY.setDuration(1000);

            // 对 封面进行平移
            ObjectAnimator translationLine = ObjectAnimator.ofFloat(cl_book_container,
                    "translationX", startValue.getLeft(), 0);
            translationLine.setDuration(1000);
            // 对封面进行旋转
            ObjectAnimator rotationY = ObjectAnimator.ofFloat(cl_book_container,
                    "rotationY", 0, -150);
            rotationY.setDuration(600);
            mAnimatorSet1 = new AnimatorSet();
            mAnimatorSet1.playTogether(scaleX, scaleY, translationLine, rotationY);
            mAnimatorSet1.start();

            /* ------------------------------------------------ */
            // 对 内部内容进行缩放,必须和封面保持一致的动作
            iv_book_content.setPivotX(x1);
            iv_book_content.setPivotY(y1);
            iv_book_content.setTranslationX(startValue.getLeft());
            iv_book_content.setTranslationY(startValue.getTop());
            ObjectAnimator scaleX2 = ObjectAnimator.ofFloat(iv_book_content,
                    "scaleX", 1.0f, sX);
            scaleX2.setDuration(1000);
            ObjectAnimator scaleY2 = ObjectAnimator.ofFloat(iv_book_content,
                    "scaleY", 1.0f, sY);
            scaleY2.setDuration(1000);

            mAnimatorSet2 = new AnimatorSet();
            mAnimatorSet2.playTogether(scaleX2, scaleY2);
            mAnimatorSet2.addListener(this);
            mAnimatorSet2.start();
        }
    }

    /**
     * 关闭动画  , 逻辑和开始动画相反
     */
    public synchronized void closeAnim() {
        if (isOpened.get()) {
            setVisibility(VISIBLE);
            setAlpha(1.0f);

            cl_book_container.setScaleX(mStartValue.getsX() * 0.8f);
            cl_book_container.setScaleY(mStartValue.getsY());
            cl_book_container.setRotationY(-150);
            ObjectAnimator scaleX = ObjectAnimator.ofFloat(cl_book_container,
                    "scaleX", mStartValue.getsX() * 0.8f, 1.0f);
            scaleX.setDuration(1000);
            ObjectAnimator scaleY = ObjectAnimator.ofFloat(cl_book_container,
                    "scaleY", mStartValue.getsY(), 1.0f);
            scaleY.setDuration(1000);

            ObjectAnimator translationLine = ObjectAnimator.ofFloat(cl_book_container,
                    "translationX", 0, mStartValue.getLeft());
            translationLine.setDuration(1000);

            ObjectAnimator rotationY = ObjectAnimator.ofFloat(cl_book_container,
                    "rotationY", -150, 0);
            rotationY.setDuration(600);
            rotationY.setStartDelay(400);
            mAnimatorSet1 = new AnimatorSet();
            mAnimatorSet1.playTogether(scaleX, scaleY, translationLine, rotationY);
            mAnimatorSet1.start();

            /* ------------------------------------------------ */

            iv_book_content.setScaleX(mStartValue.getsX());
            iv_book_content.setScaleY(mStartValue.getsY());

            ObjectAnimator scaleX2 = ObjectAnimator.ofFloat(iv_book_content,
                    "scaleX", mStartValue.getsX(), 1.0f);
            scaleX2.setDuration(1000);
            ObjectAnimator scaleY2 = ObjectAnimator.ofFloat(iv_book_content,
                    "scaleY", mStartValue.getsY(), 1.0f);
            scaleY2.setDuration(1000);
            mAnimatorSet2 = new AnimatorSet();
            mAnimatorSet2.playTogether(scaleX2, scaleY2);
            mAnimatorSet2.start();
            mAnimatorSet2.addListener(this);
        }
    }


    @Override
    public void onAnimationStart(Animator animation) {
    }

    @Override
    public void onAnimationEnd(Animator animation) {
        System.out.println("onAnimationEnd========== " + isOpened.get());
        if (isOpened.get()) { // 关闭书本动画执行了
            isOpened.set(false);
            if (null != mEndListener) {
                mEndListener.onRemove();
            }
        } else { // 打开书本动画
            isOpened.set(true);
            if (null != mEndListener) {
                mEndListener.onAnimationEnd();
            }
        }
    }

    @Override
    public void onAnimationCancel(Animator animation) {
    }

    @Override
    public void onAnimationRepeat(Animator animation) {
    }

    public void cancel() {
        mAnimatorSet1.cancel();
        mAnimatorSet2.cancel();
    }


    public interface OnAnimationEndListener {
        void onAnimationEnd();

        void onRemove();
    }

    private OnAnimationEndListener mEndListener;

    public void setEndListener(OnAnimationEndListener endListener) {
        mEndListener = endListener;
    }
}

复制代码

内容略多,主要涉及计算,这个细节调整,大家可根据自己喜欢的效果调整试试

再来看一个类: BookOpenViewValue ,一目了然啊

public class BookOpenViewValue {
    private int left;
    private int top;
    private int right;
    private int bottom;
    private float x;
    private float y;
    private float sX;
    private float sY;
    private String bookName;
    private String bookCover;

    public BookOpenViewValue(){}

    public BookOpenViewValue(int left, int top, int right, int bottom){
        this.left = left;
        this.top = top;
        this.right = right;
        this.bottom = bottom;
    }


    public int getRight() {
        return right;
    }

    public void setRight(int right) {
        this.right = right;
    }

    public int getBottom() {
        return bottom;
    }

    public void setBottom(int bottom) {
        this.bottom = bottom;
    }

    public int getLeft() {
        return left;
    }

    public void setLeft(int left) {
        this.left = left;
    }

    public int getTop() {
        return top;
    }

    public void setTop(int top) {
        this.top = top;
    }

    public float getX() {
        return x;
    }

    public void setX(float x) {
        this.x = x;
    }

    public float getY() {
        return y;
    }

    public void setY(float y) {
        this.y = y;
    }

    public float getsX() {
        return sX;
    }

    public void setsX(float sX) {
        this.sX = sX;
    }

    public float getsY() {
        return sY;
    }

    public void setsY(float sY) {
        this.sY = sY;
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getBookCover() {
        return bookCover;
    }

    public void setBookCover(String bookCover) {
        this.bookCover = bookCover;
    }
}
复制代码

最后来看看在 Activity 中用法,其实和一般普通 EditText 用法一致啦!

class MainActivity : AppCompatActivity() {
    private var mBookOpenView: BookOpenView? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        ll_contain.setOnClickListener {
            val window = window.decorView as ViewGroup
            val location = IntArray(2)
            ll_contain.getLocationInWindow(location)

            val startValue = BookOpenViewValue(location[0], location[1],
                    location[0] + (ll_contain.right - ll_contain.left),
                    location[1] + (ll_contain.bottom - ll_contain.top))


            val endValue = BookOpenViewValue(window.left,
                    window.top,
                    window.right,
                    window.bottom)

            mBookOpenView = BookOpenView(this@MainActivity)
            window.addView(mBookOpenView)
            mBookOpenView?.startAnim(startValue, endValue)

            mBookOpenView?.setEndListener(object : BookOpenView.OnAnimationEndListener {
                override fun onAnimationEnd() {
                    println("onAnimationEnd========== onAnimationEnd")
                    startActivity(Intent(this@MainActivity, ReadActivity::class.java))
                    overridePendingTransition(R.anim.read_fade_in, R.anim.read_fade_out)
                }

                override fun onRemove() {
                    println("onAnimationEnd========== onRemove")
                    window.removeView(mBookOpenView)
                }
            })
        }

    }

    override fun onResume() {
        super.onResume()
        println("onAnimationEnd========== onResume")
        mBookOpenView?.closeAnim()
    }
}

复制代码

跳转的 Activity 更简单了:

class ReadActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_read)
    }

  // 重写主要是去掉系统默认跳转动画,方便那边执行closeAnim
    override fun finish() {
        super.finish()
        overridePendingTransition(0, 0)
    }
}
复制代码

最后贴上2个跳转动画: res/anim/

read_fade_in.xml

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="200"
    android:fromAlpha="1.0"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toAlpha="1.0" >

</alpha>
复制代码

read_fade_out.xml

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="200"
    android:fromAlpha="1.0"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toAlpha="0.0" >

</alpha>
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Pro Git

Pro Git

Scott Chacon / Apress / 2009-8-27 / USD 34.99

Git is the version control system developed by Linus Torvalds for Linux kernel development. It took the open source world by storm since its inception in 2005, and is used by small development shops a......一起来看看 《Pro Git》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码