问题描述
我正在尝试重新创建与此处示例相同的动作:https://material.io/develop/android/theming/motion
具体来说,MaterialContainerTransform
下的示例2
详细说明提出了一个示例,该示例从RecyclerView
过渡到ViewPager
,但这不适用于我的Fragment
情况。
就目前情况而言,我无法使其正常工作,并且由于这是一个通用搜索词,因此我希望找到的所有可能示例都包含RecyclerView
和Fragment
的通用结果
就我所知,但是只有退出时的Hold
动画有效。
对于这个项目,我正在使用Java中的Navigation Architecture组件
片段A
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setExitTransition(new Hold());
}
// this is the recycler view item click listener
private ItemClickCallback getClickCallback() {
return (view) -> {
FragmentNavigator.Extras extras = new FragmentNavigator.Extras
.Builder()
.addSharedElement(view,view.getTransitionName())
.build();
NavHostFragment
.findNavController(this)
.navigate(R.id.action_navigation,null,extras);
};
}
片段B
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSharedElementEnterTransition(new MaterialContainerTransform());
}
就是这样。单击实现或不实现的项目没有什么区别,除了Hold
动画导致的延迟之外。
这是动画库中的错误还是执行不正确?文档没有明确说明如何针对这种情况具体实现这一点,并且我认为由于缺少文档,因此未正确实施。
解决方法
似乎可用的文档缺少重要的步骤。 在我的情况下,“运动布局”需要知道如何将单击的项目连接到要进行动画处理的目标视图。
我不知道从原始片段和目标片段获得1:1视图关系时,该步骤是否通常是自动化的,但在这种情况下,它是n:1视图关系,因此我必须通过view.getTransitionName()
捆绑在一起(其他方式利用navargs
),这样它就可以告诉您如何连接两个视图。
使用问题中的代码,所需的更改如下:
片段A
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// if hold is not used then the origin fragment might
// disappear too soon before the target fragment is
// fully visible
setExitTransition(new Hold());
}
@Override
public void onViewCreated(
@NonNull View view,@Nullable Bundle savedInstanceState
) {
// this is required to animate correctly when the user returns
// to the origin fragment,gives a chance for the layout
// to be fully laid out before animating it
ViewGroup viewGroup = (ViewGroup) view.getParent();
viewGroup
.getViewTreeObserver()
.addOnPreDrawListener(() -> {
startPostponedEnterTransition();
return true;
});
super.onViewCreated(view,savedInstanceState);
}
// this is the recycler view item click listener
private ItemClickCallback getClickCallback() {
return (view) -> {
FragmentNavigator.Extras extras = new FragmentNavigator.Extras
.Builder()
.addSharedElement(view,view.getTransitionName())
.build();
Bundle bundle = new Bundle();
bundle.putString("itemTransitionName",view.getTransitionName());
NavHostFragment
.findNavController(this)
.navigate(R.id.action_navigation,bundle,null,extras);
};
}
片段B
String sharedViewId = "";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
sharedViewId = getArguments().getString("itemTransitionName");
}
setSharedElementEnterTransition(new MaterialContainerTransform());
postponeEnterTransition();
}
@Override
public void onViewCreated(
@NonNull View view,@Nullable Bundle savedInstanceState
) {
// binding.getRoot() should be whichever view target you want to animate
// in the target fragment
ViewCompat.setTransitionName(binding.getRoot(),sharedViewId);
super.onViewCreated(view,savedInstanceState);
}