视图位于父级的最后位置,但仍被阻止

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了视图位于父级的最后位置,但仍被阻止相关的知识,希望对你有一定的参考价值。

What I want to do

BottomSheetDialogFragment中,我想要一个始终坚持在屏幕底部的视图,无论state (collapsed / expanded)是什么BottomSheetBehavior

What I have done

BottomSheetDialogFragment的子类中,我从XML中扩展了一个视图,并将其添加为CoordinatorLayout的子项(这是BottomSheetDialogFragment的父项的父项):

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setupBottomBar(getView());
}

private void setupBottomBar (View rootView) {
    CoordinatorLayout parentView = (CoordinatorLayout) ((FrameLayout)rootView.getParent()).getParent();
    parentView.addView(LayoutInflater.from(getContext()).inflate(R.layout.item_selection_bar, parentView, false), -1);
}

代码运行没有错误。 当我使用Layout Inspector查看View层次结构时,视图结构也是正确的:

Layout Inspector Screenshot

您还可以下载布局检查器结果here,并使用您自己的android Studio打开它。

The problem

然而,即使它被插入作为CoordinatorLayout的最后一个孩子,它仍然被BottomSheetDialogFragment阻止。 当我慢慢向下滚动BottomSheetDialogFragemnt(从折叠状态到隐藏状态)时,我终于可以看到我想要在片段后面膨胀的视图。

View blocked

为什么会这样?

答案

正如@GoodDev正确指出的那样,这是因为根视图(design_bottom_sheet)已被BottomSheetDialog设置为Z翻译。 这提供了一个重要信息 - 不仅View层次结构中的序列将决定其可见性,还会确定其Z转换。

最好的方法是获取design_bottom_sheet的Z值并将其设置为底栏设置。

private void setupBottomBar (View rootView) {
    CoordinatorLayout parentView = (CoordinatorLayout) (rootView.getParent().getParent());
    View barView = LayoutInflater.from(getContext()).inflate(R.layout.item_selection_bar, parentView, false);
    ViewCompat.setTranslationZ(barView, ViewCompat.getZ((View)rootView.getParent()));
    parentView.addView(barView, -1);
}
答案

编辑2

好的,现在我看到你的要求,试试这个:

private void setupBottomBar (View rootView) {
    CoordinatorLayout parentView = (CoordinatorLayout) ((FrameLayout)rootView.getParent()).getParent();
    View view = LayoutInflater.from(getContext()).inflate(R.layout.item_selection_bar, parentView, false);
    // using TranslationZ to put the view on top of bottom sheet layout
    view.setTranslationZ(100);
    parentView.addView(view, -1);
}

编辑:

好的,我检查你的布局并检查BottomSheetDialogFragment源代码,找到原因:

在使用BottomSheetDialogFragment对话框的BottomSheetDialog中,setContentView中使用BottomSheetDialog的方法wrapInBottomSheet将内容视图放在R.id.design_bottom_sheet布局中。所以你需要覆盖BottomSheetDialogFragmentpublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)来解决你的问题。

或者,将您的setupBottomBar方法更改为:

private void setupBottomBar (View rootView) {
    FrameLayout frame = (FrameLayout)rootView.getParent();
    frame.addView(LayoutInflater.from(getContext()).inflate(R.layout.item_selection_bar, frame, false), -1);
}

并在您的item_selection_bar布局文件中,更改高度和layout_gravity:

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_gravity="bottom"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

BottomSheetDialogFragment doc说:模态底页。这是DialogFragment的一个版本,它使用BottomSheetDialog而不是浮动对话框显示底部工作表。

所以BottomSheetDialogFragmentDialogDialog是浮动视图,所以当BottomSheetDialogFragment显示时将覆盖活动内容。

另一答案

@goodev给出了一个很好的答案。

Your problem

查看的Z位置导致此问题。虽然TextView是最后一个位置,但您仍然无法看到它。

How to solve

您可以将design_sheet_bottom's Z设置为TextView。

 private void setupBottomBar (View rootView) {
    CoordinatorLayout parentView = (CoordinatorLayout) ((FrameLayout)rootView.getParent()).getParent();
    View view = LayoutInflater.from(getContext()).inflate(R.layout.item_selection_bar, parentView, false);
    view.setZ(((View)rootView.getParent()).getZ());
    parentView.addView(view, -1);
}

而且我认为上面的方式很无聊,你能把你的两个视图RecyclerViewTextView放到一个布局中吗?然后你可以用onCreateView()方法一起膨胀主题。

以上是关于视图位于父级的最后位置,但仍被阻止的主要内容,如果未能解决你的问题,请参考以下文章

从应用程序中删除了核心位置,但仍被要求提供用户位置

RecyclerView 内容未使用片段父级的全宽

将绑定传递回父级的父级视图

如何在鼠标位置打开具有 Windows 窗体父级的 WPF 窗口?

嵌套视图不遵守旋转父级的约束(变换)

停止:从传播到父级的活动状态