在CoordinatorLayout+AppBarLayout中避免RecyclerView与底部EditText重叠
问题描述
在包含AppBarLayout的CoordinatorLayout中使用RecyclerView,AppBarLayout下方放置RecyclerView,同时将包含EditText的LinearLayout固定在屏幕底部。目前滚动RecyclerView时,列表项会与底部EditText重叠,需要调整布局让RecyclerView内容位于EditText上方。
界面截图:
原XML代码:
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:fab="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start" android:id="@+id/drawerLayout_channel_chat" tools:context=".view.MyActivity"> <com.google.android.material.navigation.NavigationView android:id="@+id/nav_view_channel_chat" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="#0E66B9" android:layout_gravity="start" app:headerLayout="@layout/nav_header" app:menu="@menu/my_menu" app:itemIconTint="#fff" app:itemHorizontalPadding="40dp" app:itemTextAppearance="@style/TextViewStyle" app:itemBackground="@drawable/menu_item_padding"/> <androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.appbar.AppBarLayout android:id="@+id/channel_chat_app_bar_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <com.google.android.material.appbar.CollapsingToolbarLayout android:layout_width="match_parent" android:layout_height="300dp" app:layout_scrollFlags="scroll|exitUntilCollapsed" app:contentScrim="@color/colorPrimary" app:toolbarId="@id/toolbar_channel_chat"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/img_theme_channel_chat" android:layout_width="match_parent" android:layout_height="170dp" android:src="@drawable/ic_baseline_image_24" android:scaleType="centerCrop" android:fitsSystemWindows="true" app:layout_collapseMode="parallax" /> <TextView android:id="@+id/txt_theme_channel_chat" android:layout_below="@+id/img_theme_channel_chat" android:layout_width="match_parent" android:layout_height="60dp" android:padding="1dp" android:text="@string/channel_chat_txt" android:textColor="#FFFFFF" android:textStyle="bold" android:textSize="15sp" android:background="@drawable/text_view_border" /> <View android:layout_below="@+id/txt_theme_channel_chat" android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="1dp" android:layout_marginStart="2dp" android:layout_marginEnd="2dp" android:layout_marginBottom="1dp" android:background="#FFFFFF"/> </RelativeLayout> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar_channel_chat" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_collapseMode="pin" /> </com.google.android.material.appbar.CollapsingToolbarLayout> </com.google.android.material.appbar.AppBarLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" > <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_channel_chat" android:padding="1dp" android:layout_marginTop="6dp" app:stackFromEnd="true" android:layout_width="match_parent" android:layout_height="wrap_content"> </androidx.recyclerview.widget.RecyclerView> </LinearLayout> </ScrollView> <LinearLayout android:id="@+id/channel_chat_layout" android:layout_gravity="bottom" app:layout_insetEdge="bottom" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" android:orientation="vertical"> <ImageView android:id="@+id/img_preview_channel_chat" android:layout_width="290dp" android:layout_height="220dp" android:layout_centerInParent="true" android:layout_marginStart="4dp" android:layout_marginEnd="4dp" android:src="@drawable/ic_baseline_image_24" android:visibility="gone" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginStart="2dp" android:layout_marginEnd="60dp" android:layout_marginBottom="10dp" android:background="@drawable/input_background"> <ImageView android:id="@+id/img_send_channel_chat" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginTop="1dp" android:layout_marginStart="10dp" android:layout_marginBottom="4dp" android:layout_gravity="bottom" android:background="@drawable/send_btn_rounded" android:src="@drawable/ic_send" /> <androidx.appcompat.widget.AppCompatEditText android:id="@+id/edt_channel_chat" android:hint="Votre message ..." android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="1dp" android:paddingStart="10dp" android:paddingEnd="17dp" android:paddingTop="10dp" android:paddingBottom="10dp" android:background="@android:color/transparent" /> </LinearLayout> </LinearLayout> <com.github.clans.fab.FloatingActionMenu android:id="@+id/channel_chat_floating_action_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentBottom="true" android:layout_gravity="bottom|end" fab:menu_animationDelayPerItem="55" fab:menu_backgroundColor="@android:color/transparent" fab:menu_buttonSpacing="0dp" fab:menu_colorNormal="@color/colorPrimary" fab:menu_colorPressed="#dc4b3f" fab:menu_colorRipple="#99d4d4d4" fab:menu_fab_size="normal" fab:menu_icon="@drawable/fab_add" fab:menu_labels_colorNormal="#333" fab:menu_labels_colorPressed="#444" fab:menu_labels_colorRipple="#66efecec" fab:menu_labels_cornerRadius="3dp" fab:menu_labels_ellipsize="none" fab:menu_labels_hideAnimation="@anim/fab_slide_out_to_right" fab:menu_labels_margin="0dp" fab:menu_labels_maxLines="-1" fab:menu_labels_padding="4dp" fab:menu_labels_position="left" fab:menu_labels_showAnimation="@anim/fab_slide_in_from_right" fab:menu_labels_showShadow="true" fab:menu_labels_singleLine="false" fab:menu_labels_textColor="#f2f1f1" fab:menu_labels_textSize="15sp" fab:menu_openDirection="up" fab:menu_shadowColor="#66aff198" fab:menu_shadowRadius="4dp" fab:menu_shadowXOffset="1dp" fab:menu_shadowYOffset="4dp" fab:menu_showShadow="true"> <com.github.clans.fab.FloatingActionButton android:id="@+id/btn_parametre_channel_chat_floatingActionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_settings" fab:fab_label="Paramètres" fab:fab_size="mini" /> <com.github.clans.fab.FloatingActionButton android:id="@+id/btn_camera_channel_chat_floatingActionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_baseline_photo_camera_24" fab:fab_label="Camera" fab:fab_size="mini" /> <com.github.clans.fab.FloatingActionButton android:id="@+id/btn_pick_image_channel_chat_floatingActionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_baseline_image_24" fab:fab_label="Gallerie" fab:fab_size="mini" /> </com.github.clans.fab.FloatingActionMenu> </androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.drawerlayout.widget.DrawerLayout>
解决方案
问题根源在于两点:一是RecyclerView嵌套在ScrollView中导致布局计算异常;二是RecyclerView的布局范围覆盖了底部输入栏区域。调整步骤如下:
移除嵌套的ScrollView
RecyclerView本身具备滚动能力,嵌套ScrollView会引发滚动冲突,同时让RecyclerView无法正确计算可显示区域,直接将RecyclerView作为CoordinatorLayout的子View即可。调整RecyclerView的布局属性
- 设置
android:layout_height="match_parent",让RecyclerView填充AppBarLayout下方的剩余空间; - 保留
app:layout_behavior="@string/appbar_scrolling_view_behavior",确保RecyclerView能随AppBarLayout的折叠/展开同步滚动; - 添加
app:layout_dodgeInsetEdges="bottom",让RecyclerView自动避开底部设置了app:layout_insetEdge="bottom"的输入栏区域; - 移除多余的外层LinearLayout,简化布局结构。
- 确认底部输入栏的属性
保持输入栏的android:layout_gravity="bottom"和app:layout_insetEdge="bottom",确保它固定在屏幕底部并标记为底部inset区域。
修改后的核心布局代码:
<androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- AppBarLayout 部分保持不变 --> <com.google.android.material.appbar.AppBarLayout android:id="@+id/channel_chat_app_bar_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <!-- ... 原有内容不变 ... --> </com.google.android.material.appbar.AppBarLayout> <!-- 修改后的RecyclerView --> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_channel_chat" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="1dp" android:layout_marginTop="6dp" app:stackFromEnd="true" app:layout_behavior="@string/appbar_scrolling_view_behavior" app:layout_dodgeInsetEdges="bottom"/> <!-- 底部输入栏保持不变 --> <LinearLayout android:id="@+id/channel_chat_layout" android:layout_gravity="bottom" app:layout_insetEdge="bottom" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" android:orientation="vertical"> <!-- ... 原有内容不变 ... --> </LinearLayout> <!-- FloatingActionMenu 部分保持不变 --> <com.github.clans.fab.FloatingActionMenu <!-- ... 原有内容不变 ... --> </com.github.clans.fab.FloatingActionMenu> </androidx.coordinatorlayout.widget.CoordinatorLayout>
如果app:layout_dodgeInsetEdges不生效,也可以手动给RecyclerView设置底部内边距,值等于输入栏的高度(比如输入栏高度约为60dp,就设置android:paddingBottom="60dp"),但推荐使用inset机制,适配不同屏幕和输入栏动态变化的场景(比如预览图片显示时输入栏高度改变)。
内容的提问来源于stack exchange,提问作者user10659018
相关产品推荐
相关产品推荐

