Android Полностью прозрачная строка состояния?
Я искал документацию, но нашел только это: Ссылка. Что используется, чтобы сделать бар прозрачным? Я пытаюсь сделать строку состояния полностью прозрачной (как показано на рисунке ниже) и сделать ее обратно совместимой для APK<19:
Мой styles.xml:
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="android:actionBarStyle">@style/ThemeActionBar</item>
<item name="android:windowActionBarOverlay">true</item>
<!-- Support library compatibility -->
<item name="actionBarStyle">@style/ThemeActionBar</item>
<item name="windowActionBarOverlay">true</item>
</style>
<style name="ThemeActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid">
<item name="android:background"> @null </item>
<!-- Support library compatibility -->
<item name="background">@null</item>
<item name="android:displayOptions"> showHome | useLogo</item>
<item name="displayOptions">showHome|useLogo</item>
</style>
</resources>
Что я смог сделать:
43 ответа
Все, что вам нужно сделать, это установить эти свойства в вашей теме:
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
Для вашей деятельности / макета контейнера, для которого вы хотите иметь прозрачную строку состояния, необходимо установить следующее свойство:
android:fitsSystemWindows="true"
Как правило, это невозможно выполнить на pre-kitkat, похоже, что вы можете это сделать, но какой-то странный код делает это так.
РЕДАКТИРОВАТЬ: Я бы порекомендовал эту библиотеку: https://github.com/jgilfelt/SystemBarTint для многих элементов управления цветом строки состояния перед леденцом на палочке.
После долгих размышлений я узнал, что ответом на полное отключение полупрозрачности или любого цвета, помещенного в строку состояния и панель навигации для леденца на палочке, является установка этого флага в окне:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window w = getWindow(); // in Activity's onCreate() for instance
w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}
Никакая другая тема не нужна, она производит что-то вроде этого:
Просто добавьте эту строку кода в ваш основной файл Java:
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
);
Вы можете использовать приведенный ниже код, чтобы сделать строку состояния прозрачной.См. Изображения с красным выделением, которое поможет вам определить использование кода ниже
Фрагмент кода Kotlin для вашего приложения для Android
Шаг:1 Запишите код в методе создания
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
setWindowFlag(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, true)
}
if (Build.VERSION.SDK_INT >= 19) {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
}
if (Build.VERSION.SDK_INT >= 21) {
setWindowFlag(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false)
window.statusBarColor = Color.TRANSPARENT
}
Шаг 2: Вам нужен метод SetWindowFlag, описанный в коде ниже.
private fun setWindowFlag(bits: Int, on: Boolean) {
val win = window
val winParams = win.attributes
if (on) {
winParams.flags = winParams.flags or bits
} else {
winParams.flags = winParams.flags and bits.inv()
}
win.attributes = winParams
}
Фрагмент кода Java для вашего приложения для Android:
Шаг 1. Код основной деятельности
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, true);
}
if (Build.VERSION.SDK_INT >= 19) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
if (Build.VERSION.SDK_INT >= 21) {
setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
Шаг 2: Метод SetWindowFlag
public static void setWindowFlag(Activity activity, final int bits, boolean on) {
Window win = activity.getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
if (on) {
winParams.flags |= bits;
} else {
winParams.flags &= ~bits;
}
win.setAttributes(winParams);
}
Работает для Android KitKat и выше (для тех, кто хочет прозрачно отображать строку состояния и не манипулирует навигационной панелью, потому что все эти ответы также будут прозрачной навигационной панелью!)
Самый простой способ добиться этого:
Поместите эти 3 строки кода в styles.xml (v19)
-> если вы не знаете, как это сделать (v19), просто напишите их по умолчанию styles.xml
и затем используйте alt+enter, чтобы автоматически создать его:
<item name="android:windowFullscreen">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:fitsSystemWindows">false</item>
А теперь иди в свой MainActivity
Класс и поместите этот метод из onCreate в классе:
public static void setWindowFlag(Activity activity, final int bits, boolean on) {
Window win = activity.getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
if (on) {
winParams.flags |= bits;
} else {
winParams.flags &= ~bits;
}
win.setAttributes(winParams);
}
Затем поместите этот код в onCreate
Метод деятельности:
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, true);
}
if (Build.VERSION.SDK_INT >= 19) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
//make fully Android Transparent Status bar
if (Build.VERSION.SDK_INT >= 21) {
setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
Это оно!
Вы можете использовать внешнюю библиотеку StatusBarUtil:
Добавить на свой уровень модуля build.gradle
:
compile 'com.jaeger.statusbarutil:library:1.4.0'
Затем вы можете использовать следующую утилиту для действия, чтобы сделать строку состояния прозрачной:
StatusBarUtil.setTransparent(Activity activity)
Пример:
Полностью прозрачная панель состояния и панель навигации
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
transparentStatusAndNavigation();
}
private void transparentStatusAndNavigation() {
//make full transparent statusBar
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
setWindowFlag(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, true);
}
if (Build.VERSION.SDK_INT >= 19) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
);
}
if (Build.VERSION.SDK_INT >= 21) {
setWindowFlag(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, false);
getWindow().setStatusBarColor(Color.TRANSPARENT);
getWindow().setNavigationBarColor(Color.TRANSPARENT);
}
}
private void setWindowFlag(final int bits, boolean on) {
Window win = getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
if (on) {
winParams.flags |= bits;
} else {
winParams.flags &= ~bits;
}
win.setAttributes(winParams);
}
Я только что нашел это здесь
Потому что уже прошло 6 лет, а minSDKAPI по умолчанию — 21 (Lollipop) *CMIIW. Вот мой способ сделать прозрачную строку состояния и не перекрывать кнопку навигации:
fun setStatusBarTransparent(activity: Activity, view: View) {
activity.apply {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.statusBarColor = ContextCompat.getColor(this, R.color.transparent)
WindowCompat.setDecorFitsSystemWindows(window, false)
ViewCompat.setOnApplyWindowInsetsListener(view) { root, windowInset ->
val inset = windowInset.getInsets(WindowInsetsCompat.Type.systemBars())
root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
leftMargin = inset.left
bottomMargin = inset.bottom
rightMargin = inset.right
}
WindowInsetsCompat.CONSUMED
}
}
}
Я поместил эту функцию внутрь
Object
класс называется
UiUtils
поэтому, когда я вызываю эту функцию в своей деятельности (я тоже использую View Binding). Это будет выглядеть так:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
UiUtils.setStatusBarTransparent(this, bind.root)
...
}
Надеюсь, мой ответ поможет вам, ребята :)
Для API> 23 с поддержкой дня / ночи вы можете использовать расширение ниже. Важно понять, что
android:fitsSystemWindows="true"
использует отступы для перемещения внутри вставок (как в случае с панелью инструментов). Поэтому не имеет смысла размещать его в корневом макете (кроме DrawerLayout, CoordinatorLayout, ... они используют свою собственную реализацию).
<style name="Theme.YourApp.DayNight" parent="Theme.MaterialComponents.DayNight.NoActionBar">
...
<item name="android:windowLightStatusBar">@bool/isDayMode</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<androidx.constraintlayout.widget.ConstraintLayout
...>
<com.google.android.material.appbar.MaterialToolbar
...
android:fitsSystemWindows="true">
</androidx.constraintlayout.widget.ConstraintLayout
fun Activity.transparentStatusBar() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
} else {
window.setDecorFitsSystemWindows(false)
}
}
Тогда назовите это так:
class YourActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
transparentStatusBar()
}
}
Посмотрите эти слайды Криса Бэйнса: « Стать мастером по монтажу окон»
Изменить: если у вас есть проблемы с контентом, плавающим за панелью навигации, используйте
// using Insetter
binding.yourViewHere.applySystemWindowInsetsToPadding(bottom = true)
Чтобы нарисовать макет под строкой состояния:
Значения /styles.xml
<item name="android:windowTranslucentStatus">true</item>
Значения-V21/styles.xml
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@color/colorPrimaryDark</item>
Используйте CoordinatorLayout/DrawerLayout, который уже позаботится о параметре fitsSystemWindows, или создайте свой собственный макет так:
public class FitsSystemWindowConstraintLayout extends ConstraintLayout {
private Drawable mStatusBarBackground;
private boolean mDrawStatusBarBackground;
private WindowInsetsCompat mLastInsets;
private Map<View, int[]> childsMargins = new HashMap<>();
public FitsSystemWindowConstraintLayout(Context context) {
this(context, null);
}
public FitsSystemWindowConstraintLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FitsSystemWindowConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (ViewCompat.getFitsSystemWindows(this)) {
ViewCompat.setOnApplyWindowInsetsListener(this, new android.support.v4.view.OnApplyWindowInsetsListener() {
@Override
public WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat insets) {
FitsSystemWindowConstraintLayout layout = (FitsSystemWindowConstraintLayout) view;
layout.setChildInsets(insets, insets.getSystemWindowInsetTop() > 0);
return insets.consumeSystemWindowInsets();
}
});
setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
TypedArray typedArray = context.obtainStyledAttributes(new int[]{android.R.attr.colorPrimaryDark});
try {
mStatusBarBackground = typedArray.getDrawable(0);
} finally {
typedArray.recycle();
}
} else {
mStatusBarBackground = null;
}
}
public void setChildInsets(WindowInsetsCompat insets, boolean draw) {
mLastInsets = insets;
mDrawStatusBarBackground = draw;
setWillNotDraw(!draw && getBackground() == null);
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
if (ViewCompat.getFitsSystemWindows(this)) {
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) child.getLayoutParams();
if (ViewCompat.getFitsSystemWindows(child)) {
ViewCompat.dispatchApplyWindowInsets(child, insets);
} else {
int[] childMargins = childsMargins.get(child);
if (childMargins == null) {
childMargins = new int[]{layoutParams.leftMargin, layoutParams.topMargin, layoutParams.rightMargin, layoutParams.bottomMargin};
childsMargins.put(child, childMargins);
}
if (layoutParams.leftToLeft == LayoutParams.PARENT_ID) {
layoutParams.leftMargin = childMargins[0] + insets.getSystemWindowInsetLeft();
}
if (layoutParams.topToTop == LayoutParams.PARENT_ID) {
layoutParams.topMargin = childMargins[1] + insets.getSystemWindowInsetTop();
}
if (layoutParams.rightToRight == LayoutParams.PARENT_ID) {
layoutParams.rightMargin = childMargins[2] + insets.getSystemWindowInsetRight();
}
if (layoutParams.bottomToBottom == LayoutParams.PARENT_ID) {
layoutParams.bottomMargin = childMargins[3] + insets.getSystemWindowInsetBottom();
}
}
}
}
}
requestLayout();
}
public void setStatusBarBackground(Drawable bg) {
mStatusBarBackground = bg;
invalidate();
}
public Drawable getStatusBarBackgroundDrawable() {
return mStatusBarBackground;
}
public void setStatusBarBackground(int resId) {
mStatusBarBackground = resId != 0 ? ContextCompat.getDrawable(getContext(), resId) : null;
invalidate();
}
public void setStatusBarBackgroundColor(@ColorInt int color) {
mStatusBarBackground = new ColorDrawable(color);
invalidate();
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDrawStatusBarBackground && mStatusBarBackground != null) {
int inset = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0;
if (inset > 0) {
mStatusBarBackground.setBounds(0, 0, getWidth(), inset);
mStatusBarBackground.draw(canvas);
}
}
}
}
main_activity.xml
<FitsSystemWindowConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@drawable/toolbar_background"
app:layout_constraintBottom_toBottomOf="@id/toolbar"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="0dp"
android:layout_height="?attr/actionBarSize"
android:background="@android:color/transparent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Content"
android:textSize="48sp" />
</LinearLayout>
</FitsSystemWindowConstraintLayout>
Результат:
Просто и четко, работает практически со всеми вариантами использования (для уровня API 16 и выше):
Используйте следующий тег в своей теме приложения, чтобы сделать строку состояния прозрачной:
<item name="android:statusBarColor">@android:color/transparent</item>
А затем используйте этот код в методе onCreate вашей активности.
View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
Это все, что вам нужно сделать;)
Вы можете узнать больше из документации для разработчиков.Я также рекомендую прочитать этот пост в блоге.
КОТЛИН КОД:
val decorView = window.decorView
decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
Проверьте мой другой ответ здесь
Вот расширение в kotlin, которое делает свое дело:
fun Activity.setTransparentStatusBar() {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.statusBarColor = Color.TRANSPARENT
}
}
Это простой способ, который я нашел после долгих поисков.
Шаг 1
в вашей теме поместите этот пункт
<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
Шаг 2
В основной деятельности
WindowCompat.setDecorFitsSystemWindows(window, false)
Очень важно, если вы использовали BottomNavigationBar
на некоторых устройствах с API 30+ вы обнаружите, что системная панель навигации перекрывается нижней панелью навигации, если вы используете ее в своем приложении.
это решает эту проблему.
if (Build.VERSION.SDK_INT >= 30) {
// Root ViewGroup of my activity
val root = findViewById<ConstraintLayout>(R.id.root)
ViewCompat.setOnApplyWindowInsetsListener(root) { view, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
// Apply the insets as a margin to the view. Here the system is setting
// only the bottom, left, and right dimensions, but apply whichever insets are
// appropriate to your layout. You can also update the view padding
// if that's more appropriate.
view.layoutParams = (view.layoutParams as FrameLayout.LayoutParams).apply {
leftMargin = insets.left
bottomMargin = insets.bottom
rightMargin = insets.right
}
// Return CONSUMED if you don't want want the window insets to keep being
// passed down to descendant views.
WindowInsetsCompat.CONSUMED
}
}
Я обнаружил, что возиться со styles.xml и активностью слишком громоздко, поэтому я создал общий служебный метод, для которого установлены следующие параметры
Ява
Window window = getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
window.setStatusBarColor(Color.TRANSPARENT);
Котлин DSL
activity.window.apply {
clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
statusBarColor = Color.TRANSPARENT
}
И это все, что нужно для прозрачной строки состояния. Надеюсь это поможет.
ЕСТЬ ТРИ ШАГА:
1) Просто используйте этот сегмент кода в своем методе OnCreate
// FullScreen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
Если вы работаете над фрагментом, вам следует поместить этот сегмент кода в метод OnCreate своей операции.
2) Не забудьте также установить прозрачность в /res/values-v21/styles.xml:
<item name="android:statusBarColor">@android:color/transparent</item>
Или вы можете программно установить прозрачность:
getWindow().setStatusBarColor(Color.TRANSPARENT);
3) В любом случае вам следует добавить сегмент кода в styles.xml
<item name="android:windowTranslucentStatus">true</item>
ПРИМЕЧАНИЕ. Этот метод работает только с API 21 и выше.
Использование android:fitsSystemWindows="false"
в вашем топ-макете
<style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
Используя этот код в ur xml, вы сможете увидеть временную шкалу в вашей активности:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
Не берите в голову, что я нашел ответ здесь: полностью прозрачная строка состояния и панель навигации на леденце на палочке
Надеюсь, это поможет кому-то:).
Теперь мне нужно только сделать его обратно сопоставимым.
Вы можете попробовать это.
private static void setStatusBarTransparent(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
он просто удаляет цвет statusBar!
window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
window?.statusBarColor = Color.TRANSPARENT
Это сработало для меня, надеюсь, что это сработает и для вас
Чтобы добиться полностью прозрачной строки состояния: сначала создайте пользовательскую тему в файле themes.xml как
<style name="QuiloThemeLight" parent="Theme.AppCompat.Light.NoActionBar">
Джава:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
getWindow().setStatusBarColor(Color.TRANSPARENT);
Котлин:
activity.window.apply {
clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
statusBarColor = Color.TRANSPARENT
}
Это сработало для меня:
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
Хотя все приведенные выше ответы основываются на одной и той же фундаментальной идее, и вы можете заставить ее работать с простыми макетами, используя один из приведенных выше примеров. Однако я хотел изменить цвет фона при использовании скользящей "полноэкранной" (в сторону панели вкладок) фрагментной навигации и сохранить обычную навигацию, панели вкладок и действий.
Внимательно прочитав статью Антона Хадуцкого, я лучше понял, что происходит.
я имею DrawerLayout
с ConstraintLayout
(т.е. контейнер), который имеет Toolbar
, включить для основного фрагмента и BottomNavigationView
.
Настройка DrawerLayout
имея fitsSystemWindows
к истине недостаточно, вам нужно установить оба DrawerLayout
а также ConstraintLayout
. Предполагая прозрачную строку состояния, цвет строки состояния теперь такой же, как цвет фонаConstraintLayout
.
Однако включенный фрагмент по-прежнему имеет вставку в строке состояния, поэтому анимация другого "полноэкранного" фрагмента поверх не меняет цвет строки состояния.
Немного кода из упомянутой статьи в Activity
с onCreate
:
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.container)) { view, insets ->
insets.replaceSystemWindowInsets(
insets.systemWindowInsetLeft,
0,
insets.systemWindowInsetRight,
insets.systemWindowInsetBottom
)
}
И все хорошо, кроме Toolbar
не учитывает высоту строки состояния. Еще несколько ссылок на статью, и у нас есть полностью рабочее решение:
val toolbar = findViewById<Toolbar>(R.id.my_toolbar)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.container)) { view, insets ->
val params = toolbar.layoutParams as ViewGroup.MarginLayoutParams
params.topMargin = insets.systemWindowInsetTop
toolbar.layoutParams = params
insets.replaceSystemWindowInsets(
insets.systemWindowInsetLeft,
0,
insets.systemWindowInsetRight,
insets.systemWindowInsetBottom
)
}
Main_activity.xml (обратите внимание, что marginTop в Toolbar
предназначен для предварительного просмотра, он будет заменен кодом):
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
>
<androidx.constraintlayout.widget.ConstraintLayout 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/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/green"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintTop_toTopOf="@id/container"
android:layout_marginTop="26dp"
android:background="@android:color/transparent"
...>
...
</androidx.appcompat.widget.Toolbar>
<include layout="@layout/content_main" />
...
</androidx.constraintlayout.widget.ConstraintLayout>
...
</androidx.drawerlayout.widget.DrawerLayout>
просто вызовите эту функцию, она работает в новых/старых API-интерфейсах Android:
private fun changeScreenSystemUiController(isFullScreen: Boolean) {
window?.also {
WindowCompat.setDecorFitsSystemWindows(it, !isFullScreen)
WindowCompat.getInsetsController(it, it.decorView).apply {
systemBarsBehavior =
if (isFullScreen)
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
else
WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH
if (isFullScreen)
hide(WindowInsetsCompat.Type.systemBars())
else
show(WindowInsetsCompat.Type.systemBars())
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
it.attributes.layoutInDisplayCutoutMode =
if (isFullScreen)
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
else
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
}
}
}
В моем случае я вообще не вызываю "onCreate" (это собственное приложение для реагирования, и это можно исправить также с помощью компонента StatusBar для реагирования), можно также использовать это:
override fun onStart() {
super.onStart()
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.statusBarColor = Color.TRANSPARENT
}
Все, что нужно, это пойти в MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Window g = getWindow();
g.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
setContentView(R.layout.activity_main);
}
Вот расширение Kotlin:
fun Activity.transparentStatusBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
window.statusBarColor = Color.TRANSPARENT
} else
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}
Для последнего обновления от google. Это мой код. Это будет прозрачно для панели состояния и панели навигации: измените тему на эту:
<style name="Theme.Pink"
parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/pink_primary</item>
<item name="colorPrimaryVariant">@color/pink_dark</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/pink_light</item>
<item name="colorSecondaryVariant">@color/pink_primary</item>
<item name="colorOnSecondary">@color/black</item>
<item name="android:textColor">?attr/colorOnPrimary</item>
<!-- Status bar color. -->
<!-- Customize your theme here. -->
//transparent statusbar
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowIsTranslucent">true</item>
//transparent navigationbar
<item name="android:windowTranslucentNavigation">true</item>
</style>
Затем в макете (файл xml): добавьте 2 свойства point_top и point_bottom, чтобы определить положение значения поля других компонентов приложения:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_activity">
<TextView
android:id="@+id/point_top"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/point_bottom"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<.....>
</androidx.constraintlayout.widget.ConstraintLayout>
Затем в baseActivity или yourActivity: добавьте этот код в onCreate:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = setLayout()
//set inset for view
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, insets ->
val paramsTop =
findViewById<TextView>(R.id.point_top).layoutParams as MarginLayoutParams
paramsTop.setMargins(0, insets.getInsets(WindowInsetsCompat.Type.systemBars()).top, 0, 0)
findViewById<TextView>(R.id.point_top).layoutParams = paramsTop
val paramsBottom =
findViewById<TextView>(R.id.point_bottom).layoutParams as MarginLayoutParams
paramsBottom.setMargins(0, 0, 0, insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom)
findViewById<TextView>(R.id.point_bottom).layoutParams = paramsBottom
insets.consumeSystemWindowInsets()
}
setContentView(binding.root)
}
Надеюсь, это поможет всем.
Это решение предназначено для тех, кто хочет иметь полностью прозрачный StatusBar и не затрагивать NavigationBar . Невероятно, но это звучит настолько просто, что вызвало головную боль у многих, в том числе и у меня.
Это окончательный результат, о котором я говорю
Нам понадобятся только две функции, которые я рекомендую вызывать в OnCreate нашей Activity, первая - это setStatusBar(), которая отвечает за прозрачность для той же самой.
private fun setStatusBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.apply {
clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
}
statusBarColor = Color.TRANSPARENT
}
}
Второй, setMargins (), отвечает за установку полей, соответствующих представлениям, которые ограничены верхним пределом, поскольку в противном случае эти представления были бы видны под StatusBar.
private fun setMargins() {
ViewCompat.setOnApplyWindowInsetsListener(
findViewById(R.id.your_parent_view)
) { _, insets ->
val view = findViewById<FrameLayout>(R.id.your_child_view)
val params = view.layoutParams as ViewGroup.MarginLayoutParams
params.setMargins(
0,
insets.systemWindowInsetTop,
0,
0
)
view.layoutParams = params
insets.consumeSystemWindowInsets()
}
}
Окончательный код будет выглядеть так:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.your_layout))
setStatusBar()
setMargins()
}
private fun setStatusBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.apply {
clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
}
statusBarColor = Color.TRANSPARENT
}
}
private fun setMargins() {
ViewCompat.setOnApplyWindowInsetsListener(
findViewById(R.id.your_parent_view)
) { _, insets ->
val view = findViewById<FrameLayout>(R.id.your_child_view)
val params = view.layoutParams as ViewGroup.MarginLayoutParams
params.setMargins(
0,
insets.systemWindowInsetTop,
0,
0
)
view.layoutParams = params
insets.consumeSystemWindowInsets()
}
}
Вы можете найти более подробное объяснение всего этого в следующем посте.
Я также оставляю тестовый проект, где эти концепции работают.
Я только что разместил здесь ответ:Прозрачная строка состояния (с видимой панелью навигации)
Я работал, но не знаю почему. Итак, надеюсь, что кто-то сможет объяснить, почему это работает :) :)
Спасибо.