如何使用共享元素转换缩放文本视图?

rla*_*ay3 22 android android-5.0-lollipop activity-transition shared-element-transition

我能够使TextViews在两个活动之间完美地过渡ActivityOptions.makeSceneTransitionAnimation.但是我希望在文本转换时使文本向上扩展.我可以看到材料设计示例在联系卡过渡中放大文本"Alphonso Engelking".

我已尝试在目标TextView上设置scale属性并使用changeTransform共享元素转换,但它不会缩放,并且文本最终会在转换时被截断.

如何使用共享元素转换来缩放TextView?

Ale*_*ood 28

编辑:

正如Kiryl Tkach在下面的评论中所指出的,这个Google I/O谈话中描述了一个更好的解决方案.


您可以创建一个自定义过渡,以动画TextView文本大小,如下所示:

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<TextView, Float> TEXT_SIZE_PROPERTY =
            new Property<TextView, Float>(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);
    }
}
Run Code Online (Sandbox Code Playgroud)

由于更改TextView文本大小会导致其布局边界在动画过程中发生变化,因此过渡到正常工作将比仅仅ChangeBounds过渡到相同的过程需要更多的努力TransitionSet.您需要做的是手动测量/布局视图的最终状态SharedElementCallback.

我在GitHub上发布了一个示例项目来说明这个概念(注意项目定义了两个Gradle产品风格......一个使用Activity Transitions,另一个使用Fragment Transitions).

  • @Ted可以在XML文件中引用上面的自定义转换,因为它会覆盖`TextSizeTransition(Context,AttributeSet)`构造函数.例如,您可以像这样引用上面的自定义转换:`<transition class ="com.package.name.TextSizeTransition"/>` (4认同)
  • 使用`SharedElementCallback` 功能的不错的解决方案。添加一些有用的内容是,如果您的共享元素实际上是一个 ViewGroup 并且您的 TextView 在其中居中,则除了 `SharedElementCallback.onSharedElementEnd` 之外,您还必须在 `SharedElementCallback.onSharedElementStart` 中重新布局 TextView。请参阅@AlexLockwood 的“EnterSharedElementCallback”示例。 (2认同)