美文网首页android开发安卓知识安卓开发
低版本实现共享元素动画(二):格瓦拉动画

低版本实现共享元素动画(二):格瓦拉动画

作者: 小武站台 | 来源:发表于2016-09-06 14:13 被阅读569次

    译文的GitHub地址:低版本实现共享元素动画(二):格瓦拉动画

    译者注:好久没折腾动画了,一开始就停不下来了

    最后实现效果

    刚写完低版本实现共享元素动画,ios的同事丢过来手机告诉我格瓦拉app的一个动画很好看,我一看还真不错,就问android版本的实现呢,打开他的香槟金小米5以为是和ios一样的实现,可惜只实现了一半,盯得动画看了一会,发现有点像是android material设计动画,然后他又给我看了好几个app的动画,一看我就发现了,ios好多app动画都是android material设计里面的,而且不少是material的错误示范,哈哈

    像格瓦拉app这个动画,看过google的material设计,会很熟悉,但是这个动画 用户等待内容的时间太长了,体验并不是那么的好,google不推荐。先不讨论对不对了,我们来简单实现一下吧

    主要步骤

    主要流程其实和上一篇动画差不多,只不过B页面多了一个Reveal动画,这个动画我们用一个三方库来实现

     compile ('com.github.ozodrukh:CircularReveal:2.0.1@aar') {
            transitive = true;
        }
    

    我们来分析一下B页面,可以看到有好几层,在android中这个可以用RelativeLayout来实现

    Activity B
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical">
    
        <!--layer 1-->
        <LinearLayout
            android:id="@+id/bg_detail"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/white"
            android:orientation="vertical">
    
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="160dp"
                android:background="@color/gray">
            </ImageView>
        </LinearLayout>
    
    
        <!--layer 2-->
        <io.codetail.widget.RevealFrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <LinearLayout
                android:id="@+id/container_detail"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/blue"
                android:orientation="vertical"
                android:visibility="invisible">
    
                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="160dp"
                    android:background="@color/colorPrimary">
                </ImageView>
    
            </LinearLayout>
        </io.codetail.widget.RevealFrameLayout>
    
    
        <!--layer 3-->
        <ImageView
            android:id="@+id/iv_detail"
            android:layout_width="80dp"
            android:layout_height="120dp"
            android:layout_marginLeft="40dp"
            android:layout_marginTop="100dp"
            android:background="@color/colorAccent"/>
    
    </RelativeLayout>
    

    动画的流程是

    1. layer 2默认不可见
    2. layer 3 共享元素移动
    3. layer 2 开始reveal动画

    也就是在上一篇的基础上再加个动画

      private void runEnterAnimation() {
            destinationView.setVisibility(View.VISIBLE);
            destinationView.animate()
                    .setDuration(DEFAULT_DURATION)
                    .setInterpolator(DEFAULT_INTERPOLATOR)
                    .scaleX(1f)
                    .scaleY(1f)
                    .translationX(0)
                    .translationY(0)
                    .setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            revealOn();//添加reval动画
                        }
                    })
                    .start();
    
        }
    
    
    private void revealOn() {
        int cx = destinationView.getRight() - destinationView.getWidth() / 2;
        int cy = destinationView.getTop() + destinationView.getHeight() / 2;
        float radius = (float) Math.hypot(containerView.getWidth(), containerView.getHeight());
        Animator animator = ViewAnimationUtils.createCircularReveal(containerView, cx, cy, 0, radius);
        animator.setInterpolator(DEFAULT_INTERPOLATOR);
        animator.setDuration(900);
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                containerView.setVisibility(View.VISIBLE);
            }
        });
        animator.start();
    }
    

    退出的话 以进入动画相反顺序执行

     @Override
     public void onBackPressed() {
            revealOff();
     }
    
    public void revealOff() {
        int cx = destinationView.getRight() - destinationView.getWidth() / 2;
        int cy = destinationView.getTop() + destinationView.getHeight() / 2;
        float radius = (float) Math.hypot(containerView.getWidth(), containerView.getHeight());
        Animator animator = ViewAnimationUtils.createCircularReveal(containerView, cx, cy, radius, 0);
        animator.setInterpolator(DEFAULT_INTERPOLATOR);
        animator.setDuration(900);
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                containerView.setVisibility(View.INVISIBLE);
                runExitAnimation();
            }
        });
        animator.start();
    }
    
    
    private void runExitAnimation() {
        destinationView.animate()
                .setDuration(DEFAULT_DURATION)
                .setInterpolator(DEFAULT_INTERPOLATOR)
                .scaleX(scaleX)
                .scaleY(scaleY)
                .translationX(deltaX)
                .translationY(deltaY)
            /*    .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        bgView.setVisibility(View.INVISIBLE);
                        finish();
                        overridePendingTransition(0, R.anim.fade_exit);
                    }
                })*/
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        bgView.setVisibility(View.INVISIBLE);
                        finish();
                        overridePendingTransition(0, R.anim.fade_exit);
                    }
                })
                .start();
    }
    

    最后效果会发现

    1. activity b退出的时候效果还是不理想 这可能也是格瓦拉android不实现退出动画的原因,我觉得这个真想实现的话,通过alpha退出是可以实现和ios一样效果的
    2. 动画差值器尤其重要,上面退出动画其实控制好也可以实现 我全部用的AccelerateDecelerateInterpolator 效果很生硬
    3. RecycleView Item里面获取在屏幕位置好像会有偏差

    当然只是粗糙简单实现一下,细节没有去深究,效果比原版差不少,重要的是看到别人的动画时,培养如何思考的这个过程。

    相关文章

      网友评论

      本文标题:低版本实现共享元素动画(二):格瓦拉动画

      本文链接:https://www.haomeiwen.com/subject/xxsdettx.html