Подтвердить что ты не робот

Прозрачная/Прозрачная строка состояния + КоординаторLayout + Панель инструментов + Фрагмент

У меня есть следующая настройка:

  • Я использую AppCompat
  • MainActivity, которая содержит фрагмент и имеет панель инструментов, скрывающуюся при прокрутке вниз
  • Fragment с RecyclerView
  • все представления, которые должны соответствовать экрану, соответствуют android:fitsSystemWindows="true" в макете xml

Проблема в том, что я не могу получить прозрачность в этом случае. Что я делаю:

  • Создайте действие и вызовите setContent
  • Затем я пытаюсь настроить активность, чтобы программно получить полупрозрачную панель инструментов, например:

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public void themeNavAndStatusBar(Activity activity)
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
            return;
    
        Window w = activity.getWindow();
        w.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        w.setFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        w.setFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        w.setNavigationBarColor(activity.getResources().getColor(android.R.color.transparent));
    
        w.setStatusBarColor(activity.getResources().getColor(android.R.color.transparent));
    }
    
  • Замените местозаполнитель в активности (@+id/frame_container) фрагментом

Строка состояния в этом случае сплошная, а под ней не видны... Почему?

Что я хочу

Я хочу панель инструментов, которая прокручивается по экрану и полностью скрывается, а содержимое под этой панелью должно соответствовать экрану и рисоваться за прозрачной панелью навигации.

Макеты

Здесь моя основная деятельность:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/clMain"
    android:fitsSystemWindows="true"
    android:background="?attr/main_background_color"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout"
        android:fitsSystemWindows="true"
        android:background="@null"
        app:elevation="0dp"
        app:contentInsetLeft="0dp"
        app:contentInsetStart="0dp"
        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"
            android:background="?attr/colorPrimary"
            android:elevation="4dp"
            android:theme="?actionBarThemeStyle"
            app:popupTheme="?actionBarPopupThemeStyle"
            app:layout_scrollFlags="scroll|enterAlways">

            <LinearLayout
                android:orientation="vertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <LinearLayout
                    android:orientation="horizontal"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content">

                    <ImageView
                        android:id="@+id/ivToolbarDataSource"
                        android:layout_gravity="center_vertical"
                        android:layout_marginRight="2dp"
                        android:layout_width="24dp"
                        android:layout_height="24dp" />

                    <TextView
                        android:id="@+id/tvToolbarTitle"
                        style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
                        android:theme="?actionBarThemeStyle"
                        android:layout_gravity="center_vertical"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />

                </LinearLayout>

                <TextView
                    android:id="@+id/tvToolbarSubTitle"
                    style="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle"
                    android:theme="?actionBarThemeStyle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />

            </LinearLayout>



        </android.support.v7.widget.Toolbar>

        <!-- BUG: http://stackoverflow.com/info/30541409/coordinatorlayoutappbarlayout-does-not-draw-toolbar-properly -->
        <View
            android:layout_width="fill_parent"
            android:layout_height="1dp"/>

    </android.support.design.widget.AppBarLayout>

    <FrameLayout
        android:id="@+id/frame_container"
        android:fitsSystemWindows="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        android:layout_margin="32dp"
        android:src="@drawable/ic_local_offer_white_24dp"
        app:backgroundTint="?attr/colorPrimary"
        app:borderWidth="0dp"
        app:fabSize="normal"
        app:rippleColor="?attr/colorPrimaryDark"
        app:layout_anchorGravity="bottom|right|end"
        app:layout_behavior="com.test.classes.ScrollAwareFABBehavior"/>

</android.support.design.widget.CoordinatorLayout>

И вот мой фрагмент, который будет помещен в основное действие:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:fitsSystemWindows="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/srlImages"
        android:fitsSystemWindows="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rvImages"
            android:fitsSystemWindows="true"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </android.support.v4.widget.SwipeRefreshLayout>

    <TextView
        android:id="@+id/tvEmpty"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>

РЕДАКТИРОВАТЬ - Скриншоты

Я использую светлую/темную базовую тему и тему все вручную (потому что пользователь может выбрать любой цвет в качестве основного/акцентного цвета), поэтому не против, чтобы панель инструментов была белой (это цвет фона основной темы и основной цвет). Я добавил черную рамку, чтобы вы видели, где заканчивается действие.

  • Первая скриншот: показывает панель инструментов, ничего не прокручивается
  • Вторая скриншот: я только начал прокрутку = > панель инструментов теперь должна прокручиваться.
  • Третий скриншот: основное содержание должно теперь прокручиваться под панелью навигации...

В конце концов, я, конечно же, сделаю панель инструментов и навигационную панель полупрозрачной для лучшего визуального эффекта...

введите описание изображения здесь введите описание изображения здесь введите описание изображения здесь

4b9b3361

Ответ 1

Для меня причина заключалась не в том, что она не работала сама по себе, но я использую библиотеку ящиков материалов от Майка Пенза, и эта библиотека использует полноэкранный + смещение + пользовательский фон за панелью инструментов, поэтому мне пришлось решить проблему соблюдая эту специальную настройку...

Я вознагражу очки, на мой взгляд, самый информативный ответ, хотя...

Ответ 2

tl; dr Установите android:fitsSystemWindows="false" как минимум в корневой каталог CoordinatorLayout и во внутренний контейнер фрагмента @frame_container.

Это может быть не окончательное решение (т.е. может быть другое изменение fitsSystemWindows), так что скажите мне, есть ли у вас какие-либо проблемы.

почему

Когда дело доходит до строки состояния, я думаю о fitsSystemWindows так:

  • fitsSystemWindows="false": обычно рисует представление в в строке состояния из-за установленных флажков окна.
  • fitsSystemWindows="true": обычно рисует представление, под в строке состояния из-за установленных флажков окна, но добавляет верхнее дополнение, чтобы содержимое рисовалось ниже строка состояния, и они не перекрываются.

На самом деле, на мой взгляд, белый цвет, который вы видите, это не цвет панели состояния, а ваш фон CoordinatorLayout. Это связано с fitsSystemWindows="true" на координаторе: он рисует фон во всем окне, но добавляет верхнее дополнение к содержимому, поэтому внутренние представления не покрываются статусной строкой.

Это не то, что вы хотите. Ваш внутренний контент должен быть включен в строку состояния, поэтому вам нужно установить fitsSystemWindows="false" координатору (чтобы он не применял верхнее дополнение) и, возможно, к самому содержимому.

Как только вы узнаете, как это работает, легко отлаживается и достигается эффект, который вы ищете. На самом деле, это не. Проходят годы, но я все еще трачу часы, пытаясь понять правильную комбинацию fitsSystemWindows, потому что большинство Views (по крайней мере, в библиотеках поддержки) переопределяют поведение по умолчанию, указанное выше, способами, которые в основном не интуитивно понятны. См. этот пост для небольшого руководства о том, как его использовать.

Ответ 3

Измените свои styles.xml(v21), добавьте следующий стиль

 <style name="AppTheme.Home" parent="AppTheme.Base">
    <!-- Customize your theme here. -->
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:windowTranslucentNavigation">true</item>

</style>

Вы можете изменить родительскую тему по своему вкусу, но теперь объявите эту тему в своем файле AndroidManifest.xml для определенного действия вроде этого:

 <activity
        android:theme="@style/AppTheme.Home"
        android:name=".HomeActivity"
        android:launchMode="singleTop"
        android:screenOrientation="portrait" />

Это позволит вашему содержимому видеть прозрачную панель действий.

Теперь примените следующее, чтобы правильно подобрать свою панель инструментов ниже StatusBar, назовите это в своем oncreate:

 toolbar.setPadding(0, getStatusBarHeight(), 0, 0);

Получить высоту статусной панели, используя следующую команду:

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

Удалите из тегов компоновщика координаты:

    android:fitsSystemWindows="true"

Теперь, чтобы свернуть панель инструментов или скрыть ее, вы можете обратиться к следующему руководству:

http://antonioleiva.com/collapsing-toolbar-layout/

Убедитесь, что вы используете следующую версию библиотеки поддержки дизайна, так как она без ошибок:

    compile 'com.android.support:design:23.1.0'

Ответ 4

После прочтения ваших описаний по вашему вопросу, я думал, что стили Google Фото соответствуют вашему требованию.

ОК, есть только несколько советов по вашему вопросу. После моего теста он работает.

  • Если вы хотите показывать контент по строке состояния, вам нужно добавить <item name="android:windowTranslucentStatus">true</item> в свой стиль, когда уровень версии Android больше 19 (а именно KitKat)
  • Если вы хотите показывать контент за панель навигации, вам нужно добавить <item name="android:windowTranslucentNavigation">true</item> в ваш стиль, когда уровень версии Android больше 19 (а именно KitKat)
  • Если вы хотите скрыть Toolbar плавно при прокрутке содержимого и чтобы показать Toolbar гладко, когда контент прокручивается вниз, вы нужно добавить app:layout_collapseMode="parallax" в свой Toolbar на основе ваших текущих кодов. Конечно, вы нужна координата Toolbar с CollapsingToolbarLayout CoordinatorLayout и AppBarLayout.

Ответ 5

У меня была такая же проблема, и мое решение добавило android: fitsSystemWindows = "true" к DrawerLayout

<android.support.v4.widget.DrawerLayout 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"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"> 

....

</android.support.v4.widget.DrawerLayout>

Ответ 6

У меня были проблемы, связанные с настройкой android: fitsSystemWindows. Как только ложь: Закуски были сделаны под панелью навигации Как только true: Строка состояния не имела прозрачного фона

Решение было действительно простым... Просто добавьте android: layout_marginBottom = "48dp". to CoordinatorLayout:

just to add <android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:map="http://schemas.android.com/apk/res-auto"
tools:context=".MapsActivity"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"

android:fitsSystemWindows="false"
android:layout_marginBottom="48dp">

Теоретически панель навигации должна иметь фиксированный размер "48dp", но в будущих версиях потенциально это может измениться (например, строка состояния стала более тонкой на 1dp в Marshmallow), поэтому я не буду полагаться на фиксированный размер. Лучше дополнительно получить его и применить во время выполнения.

Если вы используете Google Map, например, меня, вы можете узнать размер ActionBar/Toolbar и панель навигации во время выполнения:

в onCreate используйте этот код:

            final TypedArray styledAttributes = MapsActivity.this.getTheme().obtainStyledAttributes(
                new int[]{android.R.attr.actionBarSize});
        mToolbarHeight = (int) styledAttributes.getDimension(0, 0);
        styledAttributes.recycle();
        // translucent bars code. Will not fire below Lollipop
        // Ask NavigationBar Height
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.coordinatorLayout),
                new OnApplyWindowInsetsListener() { // setContentView() must be fired already
                    @Override
                    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                        statusBar = insets.getSystemWindowInsetTop(); // You may also need this value
                        mNavBarHeight = insets.getSystemWindowInsetBottom();
                        if (mMap != null)
                            mMap.setPadding(0, mToolbarHeight, 0, mNavBarHeight);
                        // else will be set in onMapReady()
                        SharedPreferences.Editor editor = mSharedPref.edit();
                        editor
                                .putInt(NAVBAR_HEIGHT_KEY, mNavBarHeight)
                                .commit(); // Save the results in flash memory and run the code just once on app first run instead of doing it every run
                        return insets;
                    }
                }
        );

И что важно. Если у вас есть дополнительные слои, такие как ящик и т.д., Поместите их в инкапсуляцию CoordinatorLayout внутри, а не снаружи, так как в противном случае другие представления будут короче, чем marginBottom

Ответ 7

как утверждают некоторые пользователи, установив android:fitsSystemWindows="false", макет перекрывается ниже statusbar.

Я решил это, установив android:fitsSystemWindows="true" и в настройку тега CoordinatorLayout app:statusBarBackground="@android:color/transparent".