Android – высота макета кадра, не соответствующая компоновке координатора

У меня проблема с моим FrameLayout (Container in Layer Layout). Высота FrameLayout превышает высоту экрана (ниже кнопок меню по умолчанию для Android по умолчанию).

<android.support.design.widget.CoordinatorLayout android:id="@+id/main_content" android:layout_width="fill_parent" android:layout_height="fill_parent"> <android.support.design.widget.AppBarLayout android:id="@+id/navContainer" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways" /> </android.support.design.widget.AppBarLayout> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </android.support.design.widget.CoordinatorLayout> 

Высота выше, чем в Android Studio Designer

Solutions Collecting From Web of "Android – высота макета кадра, не соответствующая компоновке координатора"

Моя первая попытка состояла в том, чтобы установить android:layout_marginBottom="?attr/actionBarSize" в FrameLayout. Это решило решение для прокручиваемых представлений, имеющих «фиксированную» высоту в терминах без вертикально прокручиваемого содержимого (например, обычный RelativeLayout с высотой match_parent ). Выравнивание компонента с нижней частью родителя ( android:layout_alignParentBottom="true" ) приводит к тому, что все еще видимый элемент. В Previewer Android Studio невидимое превышение высоты.

Однако этот marginBotton-fix представляет новую проблему для фрагментов, корневой вид которых прокручивается (например, RecyclerView). Для этих просмотров, когда прокрутка вниз по нижнему краю станет видимой в белой полосе (в случае белого цвета фона). Это швы разумные, так как для этих представлений вложенная функция прокрутки выводит панель инструментов ListView с последним разрезом

Tl; dr Я работал над этой проблемой, применяя параметр ?attr/actionBarSize как нижний край для прокручиваемых фрагментов, которые отображаются внутри Framelayout. До этого я устанавливал высоту панели инструментов ?attr/actionBarSize .

Схема работы:

  <android.support.design.widget.AppBarLayout android:id="@+id/navContainer" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways" /> </android.support.design.widget.AppBarLayout> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </android.support.design.widget.CoordinatorLayout> 

Макет фрагмента:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="?attr/actionBarSize" android:orientation="vertical"> <!-- Further stuff here --> <TextView android:id="@+id/label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" /> </LinearLayout> 

Единственный недостаток, с которым я столкнулся сейчас, – это пробел, который будет показан в Previewer Android Studio при создании макета фрагмента.

Если вы используете разные Fragments внутри вашего CoordinatorLayout вы столкнетесь с проблемой, что некоторые Fragments имеют прокручиваемое содержимое, а некоторые не должны прокручиваться. На Toolbar есть флажки прокрутки « scroll|enterAlways », что подходит для прежних макетов, но не подходит для последних. Мое решение – это пользовательское приложение AppBarLayout.Behavior которое переключает флажки прокрутки в зависимости от пользовательского тега (contentShouldNotScrollTag). Установите этот тег для макетов, который не должен прокручиваться так:

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:tag="@string/contentShouldNotScrollTag"> <!-- my non-scrollable Fragment layout --> </FrameLayout> 

В результате высота этого фрагмента не будет превышать высоту экрана. Ниже приведен пользовательский класс поведения для AppBarLayout :

 public class MyScrollBehavior extends AppBarLayout.Behavior { private View content; public MyScrollBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onMeasureChild(CoordinatorLayout parent, AppBarLayout appBarLayout, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { if(content == null) { content = parent.findViewById(R.id.container); } if(content != null) { boolean shouldNotScroll = content.findViewWithTag(parent.getContext().getString(R.string.contentShouldNotScrollTag)) != null; Toolbar toolbar = (Toolbar) appBarLayout.findViewById(R.id.toolbar); AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) toolbar.getLayoutParams(); if (shouldNotScroll) { params.setScrollFlags(0); appBarLayout.setExpanded(true, true); } else { params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); } } return super.onMeasureChild(parent, appBarLayout, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); } }