Android 方向改变后反向共享元素过渡?
Android reverse shared element transition on back after orientation change?
对于共享元素转换,我正在关注 this github 项目。它有 2 个屏幕 - 一个带有 recyclerview,其中包含卡片数量,第二个是详细信息屏幕。正如预期的那样,它展示了 imageview 和 textview 从 recyclerview 项目到详细信息屏幕的共享元素转换以及后退时的反向转换。
但是,如果用户在详细信息屏幕上更改方向,然后按下后退按钮,则反向过渡动画将不起作用。查看 2:49 到 2:57 之间的 this 视频帧,即使在方向改变后似乎也是可能的。对此有什么想法吗?
编辑:
请检查 this video 以便更好地理解。
您必须设置:
requestWindowFeature(Window.FEATURE_CONTENT_TRANSITIONS);
requestWindowFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
在调用和被调用中activity(本例中为MainActivity + NextActivity)。
我假设您通过调用以下方式打开 NextActivity:
ActivityOptions options = ActivityOptions.
makeSceneTransitionAnimation(this, new Pair<View, String>(viewToAnimate, "animationName"));
Intent intent = new Intent(MainActivity.this, NextActivity.class);
startActivity(intent, options.toBundle());
您必须在 NextActivity 中添加:
animatingView.setTransitionName("animationName");
如果您这样做,当您点击后退按钮时,转换将起作用。
但是,如果您转动设备并按下后退按钮,它将无法工作。
为了解决这个问题,我在第一个 activity(本例中为 MainActivity)中添加了这个:
animatingView.setTransitionName("animationName");
系统现在知道屏幕旋转后要制作什么动画。
如果您进入 "Developer options" 并启用 "Don't keep activities",我想您会发现问题也会发生。换句话说,问题不在于你在旋转设备......但更普遍的是第一个 activity 在后台被销毁。
看看你的示例代码,你似乎在用适配器做一些奇怪的事情(即从后台线程每 50 毫秒向回收器视图提供新的网格项目)?我明白为什么这可能会给您带来一些问题......例如,如果调用 activity 被破坏并且需要在用户单击后退按钮并且 return 转换开始后立即重新创建怎么办?如果共享元素 return 过渡开始并且所需的共享元素在第一个 activity 中尚不存在(例如,因为它尚未被适配器添加),则过渡将不起作用正确。
我认为这些信息应该足以帮助您开始解决问题。
最后,我可以通过将单独的主题应用于详细信息屏幕覆盖以下属性值来解决此问题,但不确定为什么此参数会更改动画行为。
<item name="android:windowIsTranslucent">true</item>
我遇到了同样的问题,这就是我解决它的方法。
点击RecyclerView item时,我传递当前位置:
@Override
public void onItemClick(View sharedView, String transitionName, int position) {
viewPosition = position;
Intent intent = new Intent(this, TransitionActivity.class);
intent.putExtra("transition", transitionName);
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(this, sharedView, transitionName);
ActivityCompat.startActivity(this, intent, options.toBundle());
}
我将其保存在 onSaveInstanceState 中以在配置更改时保持不变:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(VIEW_POSITION, viewPosition);
}
然后,在onCreate方法中:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Workaround for orientation change issue
if (savedInstanceState != null) {
viewPosition = savedInstanceState.getInt(VIEW_POSITION);
}
setExitSharedElementCallback(new SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
super.onMapSharedElements(names, sharedElements);
if (sharedElements.isEmpty()) {
View view = recyclerView.getLayoutManager().findViewByPosition(viewPosition);
if (view != null) {
sharedElements.put(names.get(0), view);
}
}
}
});
}
问题原因:方向改变后sharedElements地图为空(我不知道为什么)。
对于共享元素转换,我正在关注 this github 项目。它有 2 个屏幕 - 一个带有 recyclerview,其中包含卡片数量,第二个是详细信息屏幕。正如预期的那样,它展示了 imageview 和 textview 从 recyclerview 项目到详细信息屏幕的共享元素转换以及后退时的反向转换。
但是,如果用户在详细信息屏幕上更改方向,然后按下后退按钮,则反向过渡动画将不起作用。查看 2:49 到 2:57 之间的 this 视频帧,即使在方向改变后似乎也是可能的。对此有什么想法吗?
编辑:
请检查 this video 以便更好地理解。
您必须设置:
requestWindowFeature(Window.FEATURE_CONTENT_TRANSITIONS);
requestWindowFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
在调用和被调用中activity(本例中为MainActivity + NextActivity)。
我假设您通过调用以下方式打开 NextActivity:
ActivityOptions options = ActivityOptions.
makeSceneTransitionAnimation(this, new Pair<View, String>(viewToAnimate, "animationName"));
Intent intent = new Intent(MainActivity.this, NextActivity.class);
startActivity(intent, options.toBundle());
您必须在 NextActivity 中添加:
animatingView.setTransitionName("animationName");
如果您这样做,当您点击后退按钮时,转换将起作用。
但是,如果您转动设备并按下后退按钮,它将无法工作。
为了解决这个问题,我在第一个 activity(本例中为 MainActivity)中添加了这个:
animatingView.setTransitionName("animationName");
系统现在知道屏幕旋转后要制作什么动画。
如果您进入 "Developer options" 并启用 "Don't keep activities",我想您会发现问题也会发生。换句话说,问题不在于你在旋转设备......但更普遍的是第一个 activity 在后台被销毁。
看看你的示例代码,你似乎在用适配器做一些奇怪的事情(即从后台线程每 50 毫秒向回收器视图提供新的网格项目)?我明白为什么这可能会给您带来一些问题......例如,如果调用 activity 被破坏并且需要在用户单击后退按钮并且 return 转换开始后立即重新创建怎么办?如果共享元素 return 过渡开始并且所需的共享元素在第一个 activity 中尚不存在(例如,因为它尚未被适配器添加),则过渡将不起作用正确。
我认为这些信息应该足以帮助您开始解决问题。
最后,我可以通过将单独的主题应用于详细信息屏幕覆盖以下属性值来解决此问题,但不确定为什么此参数会更改动画行为。
<item name="android:windowIsTranslucent">true</item>
我遇到了同样的问题,这就是我解决它的方法。
点击RecyclerView item时,我传递当前位置:
@Override
public void onItemClick(View sharedView, String transitionName, int position) {
viewPosition = position;
Intent intent = new Intent(this, TransitionActivity.class);
intent.putExtra("transition", transitionName);
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(this, sharedView, transitionName);
ActivityCompat.startActivity(this, intent, options.toBundle());
}
我将其保存在 onSaveInstanceState 中以在配置更改时保持不变:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(VIEW_POSITION, viewPosition);
}
然后,在onCreate方法中:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Workaround for orientation change issue
if (savedInstanceState != null) {
viewPosition = savedInstanceState.getInt(VIEW_POSITION);
}
setExitSharedElementCallback(new SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
super.onMapSharedElements(names, sharedElements);
if (sharedElements.isEmpty()) {
View view = recyclerView.getLayoutManager().findViewByPosition(viewPosition);
if (view != null) {
sharedElements.put(names.get(0), view);
}
}
}
});
}
问题原因:方向改变后sharedElements地图为空(我不知道为什么)。