J'essaie de créer un lanceur Android. Je souhaite obtenir une barre d'état et une barre de navigation complètement transparentes, voici mon fichier XML de thème.
<resources>
<style name="Theme" parent="Android:Theme.Material.Wallpaper.NoTitleBar">
<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>
</style>
</resources>
les deux derniers éléments ne fonctionnent pas, il y a toujours une ombre sur Lollipop.
Voici à quoi cela ressemble (notez qu'il y a réellement une ombre sur la barre d'état et la barre de navigation):
ce que je veux réaliser (nova launcher):
comment rendre la barre d'état et la barre de navigation "transparentes" au lieu de "translucides"?
Vous pouvez obtenir le même effet par programme sur KitKat et après en définissant la valeur FLAG_LAYOUT_NO_LIMITS
drapeau à l'intérieur du Window
.
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);
}
Si vous définissez une ressource d'arrière-plan ( telle qu'une couleur ou une image ) dans votre mise en page, vous verrez la couleur ou l'image "sous" la barre d'état.
<item name="Android:windowDrawsSystemBarBackgrounds">true</item>
<item name="Android:statusBarColor">@color/primary_dark</item>
Ça ressemble à Android:windowTranslucentStatus
et Android:windowTranslucentNavigation
devrait être true
au lieu de false
<resources>
<style name="Theme" parent="Android:Theme.Material.Wallpaper.NoTitleBar">
<item name="Android:statusBarColor">@Android:color/transparent</item>
<item name="Android:navigationBarColor">@Android:color/transparent</item>
<item name="Android:windowTranslucentStatus">true</item>
<item name="Android:windowTranslucentNavigation">true</item>
</style>
</resources>
En outre, votre structure d'activité/conteneur transparente a besoin de cet ensemble de propriétés:
Android:fitsSystemWindows="true"
J'utilise ceci car il garde la hauteur de la barre d'état et de la barre de navigation
<!-- Base application theme. -->
<style name="theme" parent="Android:Theme.Material.Wallpaper.NoTitleBar">
<item name="Android:navigationBarColor">#00000000</item>
<item name="Android:statusBarColor">#00000000</item>
</style>
Cela nécessite toutefois API 21+
Le code suivant est un exemple de ce que j'utilise dans mon projet:
styles.xml
<style name="FadingActionBarTheme" parent="@Android:style/Theme.Holo.Light.DarkActionBar">
<item name="Android:actionBarStyle">@style/FadingActionBarWidget</item>
</style>
<style name="FadingActionBarWidget.Transparent">
<item name="Android:background">@Android:color/transparent</item>
</style>
<style name="FadingActionBarTheme.TranslucentActionBar">
<item name="Android:icon">@drawable/ic_ab_icon</item>
<item name="Android:actionBarStyle">@style/FadingActionBarWidget.Transparent</item>
<item name="Android:windowActionBarOverlay">true</item>
<item name="Android:windowContentOverlay">@null</item>
</style>
AndroidManifest.xml
<activity
Android:name=".MyActivity"
Android:label="@string/app_name"
Android:theme="@style/FadingActionBarTheme.TranslucentActionBar">
</activity>
Vous devez ajouter Android:windowDrawsSystemBarBackgrounds
drapeau à votre thème
<item name="Android:windowDrawsSystemBarBackgrounds">true</item>
Ou appelez ceci dans onCreate ()
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
@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);
}
Pour dessiner votre mise en page sous la barre d'état:
valeurs/styles.xml
<item name="Android:windowTranslucentStatus">true</item>
values-v21/styles.xml
<item name="Android:windowDrawsSystemBarBackgrounds">true</item>
<item name="Android:statusBarColor">@color/colorPrimaryDark</item>
Utilisez CoordinatorLayout/DrawerLayout qui prend déjà en charge le paramètre fitsSystemWindows ou créez votre propre présentation de la manière suivante:
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>
Résultat :
Pour ceux qui veulent une barre d’état et une barre de navigation complètement transparentes sur KitKat et dans les versions supérieures, il existe un petit conflit qui consiste à utiliser windowTranslucentNavigation
avec @Machado answer pour Lollipop et pour éviter ce conflit, séparez les styles.
styles.xml
<style name="LockScreenStyle" parent="@Android:style/Theme.Wallpaper.NoTitleBar">
<item name="Android:windowTranslucentStatus" tools:targetApi="KitKat">true</item>
<item name="Android:windowTranslucentNavigation" tools:targetApi="KitKat">true</item>
</style>
styles.xml (v21)
<style name="LockScreenStyle" parent="@Android:style/Theme.Wallpaper.NoTitleBar">
<item name="Android:windowDrawsSystemBarBackgrounds">true</item>
</style>
MyClass.Java
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);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
w.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
}
}