Ric*_*ard 1 android android-layout android-view android-recyclerview android-viewpager2
我有一个活动,其中有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>
Run Code Online (Sandbox Code Playgroud)
如您所见,我已将片段的根布局设置clipChildren为false. 我也将ViewPager2's设置clipChildren为false。PageA这是和PageB(即)的布局 XML 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>
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它只有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>
Run Code Online (Sandbox Code Playgroud)
elevation被剪掉的部分是上面ViewHolderXML 布局的阴影。由于我已将clipChildren所有父级的所有属性设置为false,因此阴影不应该被剪切,但它仍然如此。为什么会发生这种情况?如何在不更改填充/边距的情况下防止它被剪裁?
注意:我也有一个RecyclerViewinside FragmentA,但不同的是RecyclerViewinsideFragmentA没有嵌套在 a 内ViewPager2。遵循方法(将所有父级设置clipChildren为false)FragmentA允许RecyclerView的项目显示其阴影。
这是问题的图像。
使用布局检查器,看起来内部ViewPager2有更多的 ViewGroup(用红色矩形标记)。我的RecyclerView项目被剪掉后用绿色矩形标记。这是布局检查器显示的内容。
可以看到,里面ViewPager2有一个ViewPager2$RecyclerViewImpl,里面有一个FrameLayout(我没有创建这些ViewGroups)。事实证明,当s设置为 false 时,这两个clipChildren设置true为Even 。我可以像这样瞄准内部。ViewPager2clipChildrenViewPager2$RecyclerViewImplFragmentB
(viewPager.getChildAt(0) as ViewGroup).clipChildren = false
Run Code Online (Sandbox Code Playgroud)
然后我尝试FrameLayout使用类似的方法来瞄准。
((viewPager.getChildAt(0) as ViewGroup).getChildAt(0) as ViewGroup).clipChildren = false
Run Code Online (Sandbox Code Playgroud)
但是,我收到一条错误消息,指出第二个getChildAt(0)返回null. 在我的布局检查器中,它清楚地显示在我的 RecyclerView 之前有一个 FrameLayout。这FrameLayout已clipChildren设置为 true。我很确定我必须将FrameLayout'设置clipChildren为false才能使阴影不被剪切,但我可能是错的。
以下是分别显示我成功设置 ofclipChildren和失败设置ofRecyclerViewImpl的屏幕截图。falseclipChildrenFrameLayoutfalse
或者有没有更好的方法来消除阴影?
我出于私人原因遮盖了布局预览;这会导致布局预览成为一个白框。
对于那些想直接查看问题的人,只需运行我在此Github 链接中提供的应用程序即可。使用布局检查器来查看我所看到的内容。
更详细地查看您的问题后,我认为问题是 ViewHolder XML 使用 Drawable 作为背景试图模拟投影。
事实证明,Android 上的阴影不是“真正的阴影”,而是框架伪造的绘制元素。在某些情况下,这些阴影使用框架添加的额外填充;再次。
CardViews 有一个内部机制来处理这个问题(特别是在没有海拔概念的平台上)。
因此,我建议您更改 ViewHOlder 以包含 CardView。在这种情况下,它看起来像:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/component_course_container"
android:layout_width="match_parent"
android:layout_height="200dp"
android:backgroundTint="#efefef">
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="0dp"
app:cardCornerRadius="8dp"
app:cardUseCompatPadding="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="0dp"
android:layout_height="0dp"
android:text="Your Content Goes Here"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)
然后...删除所有的clipChildren/CliptoPadding等。这些会给你带来比解决方案更令人头痛的问题,并且会造成性能损失(框架现在需要绘制额外的东西,否则这些东西不会被渲染,因为它被覆盖了)。
我希望这可以帮助你。
关于 FrameLayout,这是一个 VP“东西”,我希望 Google 在最新的 AppCompat 实现中用新的“FragmentContainer”替换它。
祝你好运。
现在的样子是这样的:
| 归档时间: |
|
| 查看次数: |
2176 次 |
| 最近记录: |