【发布时间】:2020-04-23 10:03:44
【问题描述】:
我有一个具有NavHostFragment 的活动。这个NavHostFragment 将承载三个片段,其中两个是FragmentA 和FragmentB。在FragmentB 内部,我有一个ViewPager2,它有两个页面:PageA 和PageB,它们实际上都是由一个片段FragmentC 构建的。在每个PageA 和PageB 中,我都有一个RecyclerView。
这是FragmentB 的布局 XML。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/keyline_4"
android:clipChildren="false"
android:clipToPadding="false"
tools:context=".ui.NavigationActivity">
...
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/frag_course_view_pager"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="@dimen/keyline_4"
android:clipChildren="false"
... />
<com.google.android.material.tabs.TabLayout
android:id="@+id/frag_course_tablayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyline_4"
... />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
如您所见,我已将片段的根布局的clipChildren 设置为false。我还将ViewPager2 的clipChildren 设置为false。这是PageA 和PageB(即FragmentC)的布局XML。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewmodel"
type="com.mobile.tugasakhir.viewmodels.course.CourseTabViewModel" />
</data>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/frag_course_tab_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/offset_bottom_nav_bar_padding"
android:clipChildren="false"
android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
</layout>
如您所见,它只有RecyclerView,而我已将clipChildren 设置为false。 RV 的 ViewHolder 的扩展 XML 布局如下。
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
...
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/component_course_container"
android:layout_width="match_parent"
android:layout_height="@dimen/course_card_height"
android:background="@drawable/drawable_rounded_rect"
android:backgroundTint="?attr/colorSurface"
android:elevation="@dimen/elevation_0">
...
...
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
剪辑部分是来自上述ViewHolder 的XML 布局的elevation 的阴影。因为我已经将所有父母的所有clipChildren 属性设置为false,所以不应该剪掉阴影,但它仍然是。为什么会这样?如何在不更改填充/边距的情况下防止它被剪裁?
注意: 我在FragmentA 中也有一个RecyclerView,但不同的是FragmentA 中的RecyclerView 没有嵌套在ViewPager2 中。按照FragmentA上的方法(将所有父母的clipChildren设置为false)允许RecyclerView的项目显示阴影。
这是问题的图像。
更新
使用 Layout Inspector,似乎在 ViewPager2 内部,有更多的 ViewGroups(用红色矩形标记)。我的RecyclerView 的项目被剪裁了,用绿色矩形标记。这是布局检查器显示的内容。
可以看出,在ViewPager2 内部有一个ViewPager2$RecyclerViewImpl,在其中有一个FrameLayout(我没有创建这些视图组)。事实证明,即使ViewPager2 的clipChildren 设置为false,这两个clipChildren 设置为true。我可以像这样在FragmentB 中定位ViewPager2$RecyclerViewImpl。
(viewPager.getChildAt(0) as ViewGroup).clipChildren = false
然后我尝试使用类似的方法定位FrameLayout。
((viewPager.getChildAt(0) as ViewGroup).getChildAt(0) as ViewGroup).clipChildren = false
但是,我收到一条错误消息,提示第二个 getChildAt(0) 返回 null。在我的 Layout Inspector 中,它清楚地表明在我的 RecyclerView 之前有一个 FrameLayout。这个FrameLayout 的clipChildren 设置为true。我很确定我必须将FrameLayout 的clipChildren 设置为false 才能不剪裁阴影,但我可能错了。
这里的屏幕截图显示我设法将RecyclerViewImpl 的clipChildren 设置为false,但未能分别将FrameLayout 的clipChildren 设置为false。
或者有没有更好的方法来解开阴影?
我出于私人原因隐藏了布局预览;这会导致布局预览变成一个白框。
更新 2
对于那些想直接查看问题的人,只需运行我在此Github link 中提供的应用程序。使用 Layout Inspector 查看我看到的内容。
【问题讨论】:
-
自下而上是否被截断。?
-
@AtifAbbAsi 从底部是什么意思?如果你的意思是影子,那么没有。它从左侧、右侧和顶部被切断。
-
请附上参考图片。@Richard
-
尝试添加边距。?
-
@AtifAbbAsi 我的布局已经结构良好。我知道添加它可以解决问题,但它引入了一个新问题:项目视图的布局与页面上其他元素的左侧和右侧不对齐。
标签: android android-layout android-recyclerview android-view android-viewpager2