Прозрачная/Прозрачная строка состояния + Координатор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>
РЕДАКТИРОВАТЬ - Скриншоты
Я использую светлую/темную базовую тему и тему все вручную (потому что пользователь может выбрать любой цвет в качестве основного/акцентного цвета), поэтому не против, чтобы панель инструментов была белой (это цвет фона основной темы и основной цвет). Я добавил черную рамку, чтобы вы видели, где заканчивается действие.
- Первая скриншот: показывает панель инструментов, ничего не прокручивается
- Вторая скриншот: я только начал прокрутку = > панель инструментов теперь должна прокручиваться.
- Третий скриншот: основное содержание должно теперь прокручиваться под панелью навигации...
В конце концов, я, конечно же, сделаю панель инструментов и навигационную панель полупрозрачной для лучшего визуального эффекта...
![введите описание изображения здесь]()
Ответы
Ответ 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"
.