web-dev-qa-db-fra.com

Prevent BottomSheetDialogFragment couvrant la barre de navigation

J'utilise un code vraiment naïf pour afficher un fragment de dialogue de fond:

class LogoutBottomSheetFragment : BottomSheetDialogFragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.view_image_source_chooser, container, false)
        return view
    }
}

Voici comment j'ai appelé cette boîte de dialogue:

LogoutBottomSheetFragment().show(supportFragmentManager, "logout")

Mais je reçois cet horrible montré dans l'image ci-dessous. Comment puis-je garder la barre de navigation blanche (la barre du bas où se trouvent les boutons du logiciel Précédent/Accueil)?

Thème de l'application que j'utilise:

 <!-- Base application theme. -->
<style name="BaseAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
</style

<style name="AppTheme" parent="BaseAppTheme">
    <item name="Android:windowNoTitle">true</item>
    <item name="windowActionBar">false</item>

    <!-- Main theme colors -->
    <!--   your app branding color for the app bar -->
    <item name="Android:colorPrimary">@color/colorPrimary</item>
    <!--   darker variant for the status bar and contextual app bars -->
    <item name="Android:colorPrimaryDark">@Android:color/white</item>
    <!--   theme UI controls like checkboxes and text fields -->
    <item name="Android:colorAccent">@color/charcoal_grey</item>

    <item name="colorControlNormal">@color/charcoal_grey</item>
    <item name="colorControlActivated">@color/charcoal_grey</item>
    <item name="colorControlHighlight">@color/charcoal_grey</item>

    <item name="Android:textColorPrimary">@color/charcoal_grey</item>
    <item name="Android:textColor">@color/charcoal_grey</item>

    <item name="Android:windowBackground">@color/white</item>
</style>

J'ai également essayé de remplacer le setupDialog au lieu de onCreateView, mais cela se produit toujours:

    @SuppressLint("RestrictedApi")
override fun setupDialog(dialog: Dialog, style: Int) {
    super.setupDialog(dialog, style)
    val view = View.inflate(context, R.layout. view_image_source_chooser,null)
    dialog.setContentView(view)
}
16
oferiko

J'ai eu le même problème et j'ai finalement trouvé une solution qui ne soit pas bidon ou qui nécessite une quantité de code orbitante.

Cette méthode a remplacé l’arrière-plan de la fenêtre par un LayerDrawable composé de deux éléments: l’arrière-plan atténué et l’arrière-plan de la barre de navigation.

@RequiresApi(api = Build.VERSION_CODES.M)
private void setWhiteNavigationBar(@NonNull Dialog dialog) {
    Window window = dialog.getWindow();
    if (window != null) {
        DisplayMetrics metrics = new DisplayMetrics();
        window.getWindowManager().getDefaultDisplay().getMetrics(metrics);

        GradientDrawable dimDrawable = new GradientDrawable();
        // ...customize your dim effect here

        GradientDrawable navigationBarDrawable = new GradientDrawable();
        navigationBarDrawable.setShape(GradientDrawable.RECTANGLE);
        navigationBarDrawable.setColor(Color.WHITE);

        Drawable[] layers = {dimDrawable, navigationBarDrawable};

        LayerDrawable windowBackground = new LayerDrawable(layers);
        windowBackground.setLayerInsetTop(1, metrics.heightPixels);

        window.setBackgroundDrawable(windowBackground);
    }
}

La méthode "setLayerInsetTop" requiert l'API 23, mais cela convient car des icônes de barre de navigation sombres ont été introduites dans Android O (API 26).

La dernière partie de la solution consiste donc à appeler cette méthode à partir de la dernière méthode onCreate telle que décrite ci-dessous.

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = super.onCreateDialog(savedInstanceState);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
        setWhiteNavigationBar(dialog);
    }

    return dialog;
}

J'espère que cela vous aidera et s'il vous plaît, faites-moi savoir si vous trouvez un dispositif ou un boîtier dans lequel cette solution ne fonctionne pas.

before and after

5
Denis Schura

Dans BottomSheetDialogFragment, la seule chose à faire est de définir le conteneur de CoordinatorLayoutfitSystemWindows sous-jacent sur false.

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    (view!!.parent.parent.parent as View).fitsSystemWindows = false
}
  • view est votre mise en page
  • view.parent est un FrameLayout contenant votre vue
  • view.parent.parent est la CoordinatorLayout
  • view.parent.parent.parent est le conteneur de CoordinatorLayout dont la valeur fitsSystemWindow est définie sur true par défaut.

Cela garantit que toute la BottomSheetDialogFragment est dessinée sous la barre de navigation. Ensuite, vous pouvez définir la fitsSystemWindows dans vos propres conteneurs en conséquence.

Ce dont vous n'avez pas besoin des autres réponses en particulier est:

  • hacky findViewById en référence aux identifiants du système, qui sont sujets à changement,
  • référence à getWindow() ou getDialog(),
  • pas de tirables à placer à la place de la barre de navigation.

Cette solution fonctionne avec BottomSheetDialogFragment créé avec onCreateView, je n'ai pas coché onCreateDialog.

1
Michał K

La réponse de j2esu fonctionne plutôt bien. Cependant, si vous insistez sur une barre de navigation «complètement blanche», vous devez en omettre une partie.

Veuillez noter que cette solution est applicable à partir d'Android O (API 26) depuis que des icônes de barre de navigation sombres ont été introduites dans cette version. Sur les anciennes versions, vous obtenez des icônes blanches sur un fond blanc.

Tu dois:

  1. Ajoutez Android:fitsSystemWindows="true" à la racine de votre structure de dialogue.
  2. Modifiez Window de votre Dialog correctement.

Placez ce code sur onStart de votre enfant de BottomSheetDialogFragment. Si vous utilisez une bibliothèque de conception au lieu de la bibliothèque de matériaux, utilisez Android.support.design.R.id.container.

@Override
public void onStart() {
    super.onStart();
    if (getDialog() != null && getDialog().getWindow() != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        Window window = getDialog().getWindow();
        window.findViewById(com.google.Android.material.R.id.container).setFitsSystemWindows(false);
        // dark navigation bar icons
        View decorView = window.getDecorView();
        decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
    }
}

Le résultat pourrait ressembler à ceci:

 White navigation bar on Android P in dialog

1
mroczis

BottomSheetDialogFragment étend DialogFragment. Dans BottomSheetDialog, il crée un dialogue dans onCreateDialog 

public class BottomSheetDialogFragment extends AppCompatDialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new BottomSheetDialog(getContext(), getTheme());
    }

}

La couche dim est une propriété de dialogue qui s'applique à toute la fenêtre. Alors seulement, il couvrira la barre d'état. Si vous avez besoin d'un calque de dimensionnement sans boutons du bas, vous devez le faire manuellement en affichant un calque dans la présentation et en modifiant la couleur de la barre d'état en conséquence.

Appliquez le thème pour dialogfragment comme indiqué ci-dessous

class LogoutBottomSheetFragment : BottomSheetDialogFragment() {
    init {
        setStyle(DialogFragment.STYLE_NORMAL,R.style.dialog);
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.view_image_source_chooser, container, false)
        return view
    }


}

Avec des styles comme 

 <style name="dialog" parent="Base.Theme.AppCompat.Dialog">
        <item name="Android:windowBackground">@Android:color/transparent</item>
        <item name="Android:backgroundDimEnabled">false</item>
</style>
0
Sangeet Suresh