Android 共享元素动画 向下兼容android5.0版本

2020-04-02  本文已影响0人  程序猿峰岑

概述:
最近项目中需要在启动过后弹出倒计时的广告,倒计时结束后跳转到首页并实现类似共享元素动画,实现广告的图片与首页中的某个控件实现共享元素动画。

我刚接受到这个需求的时候,想到的就是android默认的共享元素动画。但在实际的开发中并不容易,主要是首页是由多个fragment实现,测试中共享元素动画就不起作用了,也不太了解这共享元素动画的原理。就在自己没有一点思路的情况下,打开百度搜索了相关文章,还真找到了,先给个链接。之所以写这篇文章是对我看的这篇文章的一个扩展。因为虽然作者写的也比较详细,但对于开发者来说。时间成本还是很宝贵的。看了他的文章 需要自己去理一下。由于作者贴的代码不是很全,所以便有了此篇文章,也同时非常感谢作者提供的宝贵的资料。

原理:
定义页面: B页面-广告倒计时页面(ActivityB),A页面(CFragment)-->寄主(ActivityA)

首先获得B页面控件的宽和高以及控件显示在屏幕中的位置,然后通过Intent传值的方式传递到A页面的碎片CFragment

       Intent intent = new Intent(ActivityB.this, ActivityA.class);
                intent.putExtra(IMAGE_URL_EXTRA, imageUrl);
                intent.putExtra(VIEW_INFO_EXTRA, /* start values */                 captureValues(imageView));
                startActivity(intent);
                overridePendingTransition(0, 0);
                finish();

 private Bundle captureValues(@NonNull View view) {
        Bundle b = new Bundle();
        int[] screenLocation = new int[2];
        view.getLocationOnScreen(screenLocation);
        b.putInt(PROPNAME_SCREENLOCATION_LEFT, screenLocation[0]);
        b.putInt(PROPNAME_SCREENLOCATION_TOP, screenLocation[1]);
        b.putInt(PROPNAME_WIDTH, view.getWidth());
        b.putInt(PROPNAME_HEIGHT, view.getHeight());
        return b;
    }

其实是通过B页面传递的数据,然后进行A页面需要共享元素控件的位移和缩放,重要的事情说一遍。就是对A页面的控件进行位移和缩放的动画 跟B页面没有半毛线关系。B页面主要是提供一些参数。具体实现动画的是在A页面。

接下来我们在看下CFragment
如果是网络图片需要在图片加载完成过后进行动画操作:

 Glide.with(this).asBitmap().load(imageUrl).into(new SimpleTarget<Bitmap>() {
                @Override
                public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                    mDestinationView.setImageBitmap(resource);
                    onUiReady();
                }
            });

把A页面需要共享元素控件的大小设置为B页面的显示图片的大小。也是通过位移和缩放动画 这样就可以给我们错觉,也就是由B页面控件过渡到A页面的控件 从而实现类似于共享元素动画的效果

 private void prepareScene() {

            int[] locations = new int[2];
            mDestinationView.getLocationOnScreen(locations);
            mEndXValues = locations[0];
            mEndYValues = locations[1];
            mEndWidth = mDestinationView.getWidth();
            mEndHeight = mDestinationView.getHeight();
            mDestinationView.setScaleX(getScaleX());
            mDestinationView.setScaleY(getScaleY());
            mDestinationView.setTranslationX(getDeltaX());
            mDestinationView.setTranslationY(getDeltaY());
        }



 private void runEnterAnimation() {
            // We can now make it visible
            mDestinationView.setVisibility(View.VISIBLE);
            // finally, run the animation
            mDestinationView.animate()
                    .setDuration(DEFAULT_DURATION)
                    .setInterpolator(DEFAULT_INTERPOLATOR)
                    .scaleX(1f)
                    .scaleY(1f)
                    .translationX(0)
                    .translationY(0)
                    .start();
        }

        private float getScaleX(){
            return scaleDelta(mStartWidth, mEndWidth);
        }

        private float getScaleY(){
            return scaleDelta(mStartHeight, mEndHeight);
        }

        private int getDeltaX(){
            return translationDelta(mStartXValues, mEndXValues);
        }

        private int getDeltaY(){
            return translationDelta(mStartYValues, mEndYValues);
        }

        private int translationDelta(int startPosition,int endPosition){
            return startPosition - endPosition;
        }

        private float scaleDelta(int startValue,int endValue){
            if (endValue == 0)return 1;
            return startValue/(endValue * 1.0f);
        }

核心代码就是这些,当然了退出页面A页面 进入到B页面也需要退出动画。具体调用是在按返回键或则home键

        private void runExitAnimation() {
            mDestinationView.animate()
                    .setDuration(DEFAULT_DURATION)
                    .setInterpolator(DEFAULT_INTERPOLATOR)
                    .scaleX(getScaleX())
                    .scaleY(getScaleY())
                    .translationX(getDeltaX())
                    .translationY(getDeltaY())
                    .withEndAction(new Runnable() {
                        @Override
                        public void run() {
                            mActivity.finish();
                            mActivity.overridePendingTransition(0, 0);
                        }
                    }).start();
        }

直接复制就可以用了
如有需要 源码链接附上 写的不是很规范还望谅解 :

上一篇下一篇

猜你喜欢

热点阅读