Shared Element Transition on CardView with radius

后端 未结 3 1542
春和景丽
春和景丽 2021-02-01 07:18

I\'ve been working on this problem for weeks and I\'m still unable to solve this problem.

So, I have a CardView that contains a LinearLayout with an ImageView.

3条回答
  •  眼角桃花
    2021-02-01 07:25

    I couldn't get that to work with Fragment Shared Element Transitions. The CardView's corner radius would just be ignored during the animation. Here's something that does work:

    fragment2.setEnterSharedElementCallback(new SharedElementCallback() {
        @Override
        public void onSharedElementStart(List sharedElementNames, List sharedElements, List sharedElementSnapshots) {}
    
        @Override
        public void onSharedElementEnd(List sharedElementNames, List sharedElements, List sharedElementSnapshots) {
            ImageView sharedImageView = null;
    
            for (View view : sharedElements) {
                if (view instanceof ImageView) {
                    sharedImageView = (ImageView) view;
                    break;
                }
            }
    
            if (sharedImageView != null) {
                sharedImageView.setClipToOutline(true);
    
                ObjectAnimator.ofInt(sharedImageView, new Property(Integer.class, "outlineRadius") {
                    @Override
                    public Integer get(ImageView object) {
                        return 0;
                    }
    
                    @Override
                    public void set(ImageView object, final Integer value) {
                        object.setOutlineProvider(new ViewOutlineProvider() {
                            @Override
                            public void getOutline(View view, Outline outline) {
                                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), value);
                            }
                        });
                    }
                }, 150, 0).setDuration(duration).start();
            }
        }
    
        @Override
        public void onRejectSharedElements(List rejectedSharedElements) {}
    
        @Override
        public void onMapSharedElements(List names, Map sharedElements) {}
    });
    

    Basically, instead of animating the rounded corners of the CardView, the ImageView itself has its own rounded corners that are being animated instead.

    The ImageView's corners are rounded with a ViewOutlineProvider, and an ObjectAnimator can be used to animate the corner radius while the shared element transition is playing. Note that calling setClipToOutline(true) on the ImageView is also required, otherwise the corners will not be clipped.

    The onSharedElementEnd method of the callback will be called with a list of all shared elements. Note that my example code handles animating the corners of just one of the ImageViews that are being shared. If your transition shares multiple ImageViews, you will need to take those into account as well.

    Also note that for some reason the same callback is also called when the reverse transition is played.

    With some amount of effort, this could be turned into a regular Transition that you just add to the set of shared element transitions that automatically figure out what to do with the shared elements.

提交回复
热议问题