У меня есть активность с NavHostFragment
. Этот NavHostFragment
будет содержать три фрагмента, два из которых FragmentA
и FragmentB
. Внутри FragmentB
у меня есть ViewPager2
, у которого есть две страницы: PageA
и PageB
, обе фактически построены из одного фрагмента, FragmentC
. Внутри каждого PageA
и PageB
у меня есть один RecyclerView
.
Вот схема XML для FragmentB
.
<?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>
Как видите, я установить root макета фрагмента clipChildren
в false
. Я также установил ViewPager2
clipChildren
на false
. Вот макет XML для PageA
и PageB
(т.е. FragmentC
).
<?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
. Надутая компоновка XML для ViewHolder RV выглядит следующим образом:
<?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>
Отсеченная часть является тенью от elevation
вышеупомянутой ViewHolder
XML компоновки. Поскольку я установил все атрибуты clipChildren
от всех родителей на false
, тень не должна была обрезаться, но она все еще остается. Почему это происходит? Как я могу предотвратить обрезку без изменения отступа / поля ?
Примечание: У меня также есть RecyclerView
внутри FragmentA
, но разница является то, что RecyclerView
внутри FragmentA
не является вложенным в ViewPager2
. Следование методам (установка clipChildren
всех родителей на false
) на FragmentA
позволяет элементам RecyclerView
показывать их тени.
Вот изображение проблемы.

Обновление
Использование инспектора макета, похоже, внутри ViewPager2
, есть больше ViewGroups (отмечены красным прямоугольник). Мой RecyclerView
с обрезанными элементами отмечен зеленым прямоугольником. Вот что показывает Инспектор макетов.

Как видно, внутри ViewPager2
есть ViewPager2$RecyclerViewImpl
, а внутри него есть FrameLayout
(я не создавал эти группы просмотра). Оказывается, для этих двух clipChildren
установлено значение true
, даже если для ViewPager2
'clipChildren
установлено значение false. Я могу нацелиться на ViewPager2$RecyclerViewImpl
внутри моего FragmentB
следующим образом.
(viewPager.getChildAt(0) as ViewGroup).clipChildren = false
Затем я попытался нацелиться на FrameLayout
, используя аналогичный метод.
((viewPager.getChildAt(0) as ViewGroup).getChildAt(0) as ViewGroup).clipChildren = false
Однако я получил ошибка о том, что второй getChildAt(0)
возвращает null
. В моем инспекторе макетов это ясно показывает, что перед моим RecyclerView есть FrameLayout. Этот FrameLayout
имеет clipChildren
, установленный в true. Я почти уверен, что мне нужно установить FrameLayout
clipChildren
на false
, чтобы тени не обрезались, но я могу ошибаться.
Вот скриншоты, показывающие, что я удалось установить clipChildren
из RecyclerViewImpl
в false
и не удалось установить clipChildren
из FrameLayout
в false
соответственно.


Или есть лучший способ отсоединить тени?
Я скрыл предварительный просмотр макета по личным причинам; это приводит к тому, что предварительный просмотр макета становится белым окном.
Обновление 2
Для тех, кто хотел бы просмотреть проблему напрямую, просто запустите приложение, которое я предоставил в это Github ссылка . Используйте Инспектора макетов, чтобы увидеть, что я вижу.