Android SharedElementTransition:如何让新视图从原视图展开至全屏?
问题原因
默认的ChangeBounds转场使用AccelerateDecelerateInterpolator,再加上两个共享元素的布局参数、ScaleType不一致,会导致系统计算的过渡中间帧出现过度缩放,视觉上表现为“先放大再缩小”。
解决步骤
1. 确保共享元素的transitionName完全一致
在Activity1的布局文件中给源视图设置:
<ImageView android:id="@+id/small_image" android:layout_width="150dp" android:layout_height="150dp" android:transitionName="shared_image" android:scaleType="centerCrop" />
在Activity2的布局文件中给全屏视图设置相同的transitionName:
<ImageView android:id="@+id/fullscreen_view" android:layout_width="match_parent" android:layout_height="match_parent" android:transitionName="shared_image" android:scaleType="centerCrop" />
注意:两个视图的ScaleType必须一致,否则会因为绘制区域计算偏差导致过渡异常
2. 自定义ChangeBounds转场,控制动画行为
创建自定义转场类,替换默认的插值器并优化动画逻辑:
public class SmoothScaleTransition extends ChangeBounds { @Override public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) { Animator animator = super.createAnimator(sceneRoot, startValues, endValues); if (animator != null) { // 使用线性插值器,避免默认加速减速带来的视觉波动 animator.setInterpolator(new LinearInterpolator()); // 可根据需求调整动画时长,默认300ms左右比较自然 animator.setDuration(350); } return animator; } }
3. 在Activity2中配置自定义转场
在onCreate方法中替换默认的共享元素转场:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_2); // 设置进入和返回的共享元素转场为自定义实现 getWindow().setSharedElementEnterTransition(new SmoothScaleTransition()); getWindow().setSharedElementReturnTransition(new SmoothScaleTransition()); }
4. 正确启动Activity2
在Activity1中启动Activity2时,正确传入过渡选项:
ImageView smallImageView = findViewById(R.id.small_image); Intent intent = new Intent(this, Activity2.class); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( this, smallImageView, "shared_image"); startActivity(intent, options.toBundle());
额外注意事项
- 确保Activity2的全屏视图没有多余的
padding或margin,否则会影响边界计算 - 如果使用的是自定义View,需要确保
onMeasure和onLayout逻辑正确,避免过渡时的边界偏差
内容的提问来源于stack exchange,提问作者Corey
相关产品推荐
相关产品推荐

