Android - высота макета кадра не соответствует макету координатора

У меня проблема с моим FrameLayout (Контейнер в макете ящика). Высота 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>

«Превышение


person Okn    schedule 18.09.2015    source источник
comment
У меня такая же проблема, это ошибка координатора Android или какой-либо обходной путь для этого. (Без указания нижнего края поля в качестве размера высоты панели действий)   -  person DeepakPanwar    schedule 23.10.2016


Ответы (2)


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

Однако это исправление marginBotton создает новую проблему для фрагментов, чье корневое представление можно прокручивать (например, 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>

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

person Capricorn    schedule 18.11.2015
comment
Это хорошо сработало для меня! В качестве примечания: если один из ваших фрагментов имеет прокручиваемый корень, который скрывает панель приложения, он останется скрытым при переходе к предыдущему (непрокручиваемому) фрагменту без возможности показать его снова. Обходной путь для этой проблемы доступен здесь. - person rmorrin; 19.02.2016

Если вы используете разные 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);
    }
}
person artkoenig    schedule 13.07.2017