CoordinatorLayout 自定义行为 onDependentViewChanged 在布局更改时被破坏
CoordinatorLayout Custom Behavior onDependentViewChanged is broken when layout is changed
我使用 Custom CoordinatorLayout Behavior 来跟踪 CoordinatorLayout 中的滑动以将两个小部件向上滑动到一起的功能,并且它可以工作(类似于 Custom BottomSheetBehavior + 另一个跟随底部位置的行为 sheet),但是在在某些情况下它会坏掉。
布局结构有点复杂,但是是这样的:
CoordinatorLayout (root tag of activity layout)
- Fragment (DetailFragment)
- CoordinatorLayout (root tag of DetailFragment)
- Fragment (MapFragment - with custom app:layout_behavior)
- CoordinatorLayout (also with another custom app:layout_behavior)
- NestedScrollView
- LinearLayout
- LinearLayout
- Some content
安装在 MapFragment 元素上的自定义行为依赖于以下元素 (CoordinatorLayout) 上的 layoutDependsOn() 方法。下面这个元素有自己的自定义行为,可以用滑动手势向上滑动。在这种情况下,MapFragment 的自定义行为会在其依赖项的每次移动时接收事件 onDependentViewChanged。
但是,如果我在调用某些内容的部分中进行更改,例如我调用 setVisibility 或我将 ListView 放在那里并在其上调用 setAdapter(此方法内部调用 requestLayout 方法 - 这与布局更改相同看起来像 setVisibility)它停止工作,这意味着 MapFragment 的自定义行为停止接收 onDependentViewChanged,即使从属视图位置已更改。
这个问题的发生可能还有其他隐藏条件。所以我需要找到隐藏的原因,或者如何让它工作的解决方法。
因为,如果我在 activity 中使用 Detail 片段,就会出现此问题,但在另一个 activity 中似乎可以正常工作。
我也忘了说,它还显示了另一个额外的问题,即 setVisibility 方法不起作用 - 元素保持隐藏 + CL 的行为被破坏(在有问题的 activity 中。顺便说一句- 当我在我的布局中有 listview 并在其上调用 setAdapter 时,它也不起作用 - 正如我所说,它显然与 setVisibility 方法在某种程度上相似)。
是的,我尝试通过 UI 线程显式调用 setVisibility
getActivity().runOnUiThread(new Runnable(){
@Override
public void run() {
xxx.setVisibility(View.VISIBLE);
}});
但这并没有帮助。谢谢
补充说明:
在有问题的 Activity 中,MapFragment 行为方法 onDependentViewChanged 至少被调用一次(当显示 activity 时 - 这应该表明依赖关系应该被正确链接)我认为它找到了正确的 CoordinatorLayout 作为它的依赖项。但问题是,如果我更改其依赖项的位置,则不再触发此事件。
在我调用 setVisibility 方法的片段代码中,我也尝试在它之后调用 getView().requestLayout() 但它没有帮助。
另请注意,我尝试调用 setVisibility 的元素在那一刻不在屏幕上(因为 MapFragment 之后 CoordinatorLayout 上的自定义行为类似于 BottomSheetBehavior),所以如果它不是'一些问题(在工作中 activity 它显示在屏幕上 - BottomSheet 显示展开,而不是隐藏或折叠,因为有问题 Activity)
编辑:
它一定是半死或懒惰的 UI 事件消息系统之类的东西,因为我发现如果我更改 activity 布局中其他元素的可见性,瞧 - 自定义地图行为又开始起作用了! - 尽管我尝试将 Visibility 设置为可见的元素仍然隐藏..
这是片段中的代码:
getView().findViewById(R.id.info_beer_bdark).setVisibility(View.VISIBLE);
如果我将其更改为:
getView().findViewById(R.id.info_beer_bdark).setVisibility(View.VISIBLE);
getActivity().findViewById(R.id.tabs).setVisibility(View.GONE);
MapFragment 的行为再次起作用 - 尽管正如我所说,我试图使其可见的元素仍然隐藏 - 也许它在该布局级别上也需要一些 "refreshing injection"。 (选项卡与 DetailFragment 元素处于同一布局级别)
问题的原因可能是因为我使用下面显示的代码在其自定义行为中为 CoordinatorLayout(在 MapFragment 之后)设置动画,并且在动画期间更改其子项的可见性。
ViewCompat.postOnAnimation(child, new SettleRunnable(child, state));
伪代码:
startCoordinatorUIAnimation(); // it takes like 300ms
changeVisibilityOfCoordinatorChildren(); // doesn't work while animating + breaks Coordinator Behavior
我仍然不知道如何实现这一点 - 在为父级设置动画时更改子级的可见性。我尝试了 runOnUIThread,也尝试了带有 runOnUIThread 的 AsyncTask,但这不起作用。
我使用 Custom CoordinatorLayout Behavior 来跟踪 CoordinatorLayout 中的滑动以将两个小部件向上滑动到一起的功能,并且它可以工作(类似于 Custom BottomSheetBehavior + 另一个跟随底部位置的行为 sheet),但是在在某些情况下它会坏掉。
布局结构有点复杂,但是是这样的:
CoordinatorLayout (root tag of activity layout)
- Fragment (DetailFragment)
- CoordinatorLayout (root tag of DetailFragment)
- Fragment (MapFragment - with custom app:layout_behavior)
- CoordinatorLayout (also with another custom app:layout_behavior)
- NestedScrollView
- LinearLayout
- LinearLayout
- Some content
安装在 MapFragment 元素上的自定义行为依赖于以下元素 (CoordinatorLayout) 上的 layoutDependsOn() 方法。下面这个元素有自己的自定义行为,可以用滑动手势向上滑动。在这种情况下,MapFragment 的自定义行为会在其依赖项的每次移动时接收事件 onDependentViewChanged。
但是,如果我在调用某些内容的部分中进行更改,例如我调用 setVisibility 或我将 ListView 放在那里并在其上调用 setAdapter(此方法内部调用 requestLayout 方法 - 这与布局更改相同看起来像 setVisibility)它停止工作,这意味着 MapFragment 的自定义行为停止接收 onDependentViewChanged,即使从属视图位置已更改。
这个问题的发生可能还有其他隐藏条件。所以我需要找到隐藏的原因,或者如何让它工作的解决方法。
因为,如果我在 activity 中使用 Detail 片段,就会出现此问题,但在另一个 activity 中似乎可以正常工作。
我也忘了说,它还显示了另一个额外的问题,即 setVisibility 方法不起作用 - 元素保持隐藏 + CL 的行为被破坏(在有问题的 activity 中。顺便说一句- 当我在我的布局中有 listview 并在其上调用 setAdapter 时,它也不起作用 - 正如我所说,它显然与 setVisibility 方法在某种程度上相似)。
是的,我尝试通过 UI 线程显式调用 setVisibility
getActivity().runOnUiThread(new Runnable(){
@Override
public void run() {
xxx.setVisibility(View.VISIBLE);
}});
但这并没有帮助。谢谢
补充说明:
在有问题的 Activity 中,MapFragment 行为方法 onDependentViewChanged 至少被调用一次(当显示 activity 时 - 这应该表明依赖关系应该被正确链接)我认为它找到了正确的 CoordinatorLayout 作为它的依赖项。但问题是,如果我更改其依赖项的位置,则不再触发此事件。
在我调用 setVisibility 方法的片段代码中,我也尝试在它之后调用 getView().requestLayout() 但它没有帮助。
另请注意,我尝试调用 setVisibility 的元素在那一刻不在屏幕上(因为 MapFragment 之后 CoordinatorLayout 上的自定义行为类似于 BottomSheetBehavior),所以如果它不是'一些问题(在工作中 activity 它显示在屏幕上 - BottomSheet 显示展开,而不是隐藏或折叠,因为有问题 Activity)
编辑:
它一定是半死或懒惰的 UI 事件消息系统之类的东西,因为我发现如果我更改 activity 布局中其他元素的可见性,瞧 - 自定义地图行为又开始起作用了! - 尽管我尝试将 Visibility 设置为可见的元素仍然隐藏..
这是片段中的代码:
getView().findViewById(R.id.info_beer_bdark).setVisibility(View.VISIBLE);
如果我将其更改为:
getView().findViewById(R.id.info_beer_bdark).setVisibility(View.VISIBLE);
getActivity().findViewById(R.id.tabs).setVisibility(View.GONE);
MapFragment 的行为再次起作用 - 尽管正如我所说,我试图使其可见的元素仍然隐藏 - 也许它在该布局级别上也需要一些 "refreshing injection"。 (选项卡与 DetailFragment 元素处于同一布局级别)
问题的原因可能是因为我使用下面显示的代码在其自定义行为中为 CoordinatorLayout(在 MapFragment 之后)设置动画,并且在动画期间更改其子项的可见性。
ViewCompat.postOnAnimation(child, new SettleRunnable(child, state));
伪代码:
startCoordinatorUIAnimation(); // it takes like 300ms
changeVisibilityOfCoordinatorChildren(); // doesn't work while animating + breaks Coordinator Behavior
我仍然不知道如何实现这一点 - 在为父级设置动画时更改子级的可见性。我尝试了 runOnUIThread,也尝试了带有 runOnUIThread 的 AsyncTask,但这不起作用。