How can I scale textviews using shared element transitions?

后端 未结 5 1282
广开言路
广开言路 2020-12-07 17:58

I am able to get TextViews to transition perfectly between two activities using ActivityOptions.makeSceneTransitionAnimation. However I want to make the text sc

5条回答
  •  情歌与酒
    2020-12-07 18:46

    Edit:

    As pointed out by Kiryl Tkach in the comments below, there is a better solution described in this Google I/O talk.


    You can create a custom transition that animates a TextView's text size as follows:

    public class TextSizeTransition extends Transition {
        private static final String PROPNAME_TEXT_SIZE = "alexjlockwood:transition:textsize";
        private static final String[] TRANSITION_PROPERTIES = { PROPNAME_TEXT_SIZE };
    
        private static final Property TEXT_SIZE_PROPERTY =
                new Property(Float.class, "textSize") {
                    @Override
                    public Float get(TextView textView) {
                        return textView.getTextSize();
                    }
    
                    @Override
                    public void set(TextView textView, Float textSizePixels) {
                        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePixels);
                    }
                };
    
        public TextSizeTransition() {
        }
    
        public TextSizeTransition(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        public String[] getTransitionProperties() {
            return TRANSITION_PROPERTIES;
        }
    
        @Override
        public void captureStartValues(TransitionValues transitionValues) {
            captureValues(transitionValues);
        }
    
        @Override
        public void captureEndValues(TransitionValues transitionValues) {
            captureValues(transitionValues);
        }
    
        private void captureValues(TransitionValues transitionValues) {
            if (transitionValues.view instanceof TextView) {
                TextView textView = (TextView) transitionValues.view;
                transitionValues.values.put(PROPNAME_TEXT_SIZE, textView.getTextSize());
            }
        }
    
        @Override
        public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, 
                                       TransitionValues endValues) {
            if (startValues == null || endValues == null) {
                return null;
            }
    
            Float startSize = (Float) startValues.values.get(PROPNAME_TEXT_SIZE);
            Float endSize = (Float) endValues.values.get(PROPNAME_TEXT_SIZE);
            if (startSize == null || endSize == null || 
                startSize.floatValue() == endSize.floatValue()) {
                return null;
            }
    
            TextView view = (TextView) endValues.view;
            view.setTextSize(TypedValue.COMPLEX_UNIT_PX, startSize);
            return ObjectAnimator.ofFloat(view, TEXT_SIZE_PROPERTY, startSize, endSize);
        }
    }
    

    Since changing the TextView's text size will cause its layout bounds to change during the course of the animation, getting the transition to work properly will take a little more effort than simply throwing a ChangeBounds transition into the same TransitionSet. What you will need to do instead is manually measure/layout the view in its end state in a SharedElementCallback.

    I've published an example project on GitHub that illustrates the concept (note that the project defines two Gradle product flavors... one uses Activity Transitions and the other uses Fragment Transitions).

提交回复
热议问题