web-dev-qa-db-fra.com

Android - Afficher BottomSheetDialogFragment au-dessus du clavier

J'essaie d'afficher un BottomSheetDialogFragment avec quelques champs EditText pour que l'utilisateur entre des informations. Je veux le montrer directement au-dessus du clavier, mais il continue de couvrir le contenu.

C'est ce qui se passe lorsque j'affiche le BottomSheetDialogFragment, vous pouvez voir qu'il sélectionne Card NumberEditText, mais couvrant l'autre contenu.

BottomSheetDialogFragment covering up content

Idéalement, c'est ce que je recherche, vous pouvez voir à la fois EditTexts et le remplissage de la vue.

BottomSheetDialogFragment not covering up content

J'ai essayé beaucoup de solutions autour de windowSoftInputMode, mais rien ne semble fonctionner. Je l'ai défini sur adjustResize pour le parent Activity et le réel BottomSheetDialogFragment via

dialog.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)

Et j'ai également essayé de modifier ma mise en page, en la changeant de FrameLayout, en ScrollView en CoordinatorLayout pour voir si cela a eu un effet sur la position de la mise en page , mais rien ne semble fonctionner.

Si quelqu'un sait comment y parvenir, ce serait grandement apprécié, merci.

15
Advice-Dog

Peut-être une réponse tardive mais aiderait probablement.

Rien d'autre n'a fonctionné pour moi. Mais cette solution fonctionne

Styles intérieurs:

<style>  // main theme
    <item name="bottomSheetDialogTheme">@style/BottomSheetDialogTheme</item>
    ........ // rest of the code
</style>

<style name="BottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/AppModalStyle</item>
    <item name="Android:windowIsFloating">false</item>
    <item name="Android:windowSoftInputMode">adjustResize</item>
    <item name="Android:statusBarColor">@Android:color/transparent</item> 
</style>

Ici Android:windowIsFloating devrait être faux & Android:windowSoftInputMode doit être adjustResize

<style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal">
    <item name="Android:background">@drawable/rounded_corner_dialog</item>
</style>

Envelopper la mise en page dans NestedScrollView

<androidx.core.widget.NestedScrollView
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content">

     <--Rest of the layout-->
</androidx.core.widget.NestedScrollView>

Sur certains appareils, cette solution n'était pas suffisante. L'ajout de cela au code a résolu mon problème complètement.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    dialog?.setOnShowListener {
        val dialog = it as BottomSheetDialog
        val bottomSheet = dialog.findViewById<View>(R.id.design_bottom_sheet)
        bottomSheet?.let { sheet ->
            dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
            sheet.parent.parent.requestLayout()
        }
    }
}

Essayez ce BottomSheetDialogFragment:

import Android.graphics.Rect; 
import Android.os.Bundle;
import Android.support.annotation.NonNull;
import Android.support.annotation.Nullable;
import Android.support.design.widget.BottomSheetBehavior;
import Android.support.design.widget.BottomSheetDialog;
import Android.support.design.widget.BottomSheetDialogFragment;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.view.WindowManager;

public class TestBottomSheetDialog extends BottomSheetDialogFragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View fragmentView = LayoutInflater.from(getContext()).inflate(R.layout.fragment_bottom_sheet, container, false);
        if (getDialog().getWindow() != null) {
           getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        }
        if (getActivity() != null) {
            View decorView = getActivity().getWindow().getDecorView();
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
                Rect displayFrame = new Rect();
                decorView.getWindowVisibleDisplayFrame(displayFrame);
                int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                int heightDifference = height - displayFrame.bottom;
                if (heightDifference != 0) {
                    if (fragmentView.getPaddingBottom() != heightDifference) {
                        fragmentView.setPadding(0, 0, 0, heightDifference);
                    }
                } else {
                    if (fragmentView.getPaddingBottom() != 0) {
                        fragmentView.setPadding(0, 0, 0, 0);
                    }
                }
            });
        }
        getDialog().setOnShowListener(dialog -> {
            BottomSheetDialog d = (BottomSheetDialog) dialog;
            View bottomSheetInternal = d.findViewById(Android.support.design.R.id.design_bottom_sheet);
            if (bottomSheetInternal == null) return;
             BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
        });
        return fragmentView;
    }
}
1
Vitali

Cette étape suivante peut être utile pour résoudre vos problèmes.

Ajoutez d'abord la ligne suivante sur votre EditText dans un fichier xml

Android:imeOptions="actionSend|flagNoEnterAction"

Par exemple:

<EditText
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:inputType="number"
    Android:hint="Card number"
    Android:imeOptions="actionSend|flagNoEnterAction"/>

Ajoutez ensuite la ligne suivante sur la balise d'activité dans le fichier AndroidManifest.xml

Android:windowSoftInputMode="stateVisible|adjustResize"

Par exemple:

<activity Android:name=".stack.MainActivity"
    Android:windowSoftInputMode="stateVisible|adjustResize">
    <intent-filter>
        <action Android:name="Android.intent.action.MAIN" />

        <category Android:name="Android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

vous pouvez trouver plus de détails sur la méthode de saisie à l'écran dans ici .

1

J'ai finalement changé la hauteur de la boîte de dialogue lorsque le clavier est ouvert et je l'ai redimensionné à la normale lorsqu'il se ferme.

Bibliothèque KeyboardVisibilityEvent: https://Android-arsenal.com/details/1/2519

  KeyboardVisibilityEvent.setEventListener(activity) { isOpen ->
            setDialogHeight(isOpen)
  }

La version minimale du SDK est 14 pour 2.0.0

Et définissez la hauteur de la boîte de dialogue à 80% lorsque le clavier s'ouvre:

    /**
     * Changes size of dialog based on keyboard visibility state
     */
    private fun setDialogHeight(expanded: Boolean) {
        val dialog = dialog as BottomSheetDialog?
        val bottomSheet =
            dialog!!.findViewById<View>(com.google.Android.material.R.id.design_bottom_sheet) as FrameLayout?
        val behavior = BottomSheetBehavior.from(bottomSheet!!)

        val displayMetrics = activity!!.resources.displayMetrics

        val width = displayMetrics.widthPixels
        val height = displayMetrics.heightPixels

        val maxHeight = (height * 0.88).toInt()

        behavior.peekHeight = if (expanded) maxHeight else -1
    }
1
Morteza Rastgoo

J'ai dû agrandir une hauteur de mise en page. Une méthode de programmation de Comment changer la hauteur par défaut du fragment de dialogue de feuille de fond? n'a pas aidé, j'ai donc simplement changé la disposition.

<Android.support.constraint.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:layout_width="match_parent"
    Android:layout_height="match_parent"
    >

    <View
        Android:id="@+id/top_space"
        Android:layout_width="match_parent"
        Android:layout_height="10dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <!-- Other views -->

    <View
        Android:id="@+id/bottom_space"
        Android:layout_width="match_parent"
        Android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/button"
        app:layout_constraintVertical_weight="1"
        />

</Android.support.constraint.ConstraintLayout>
0
CoolMind

L'ajout de rembourrage au clavier virtuel n'est pas pris en charge par le système d'exploitation Android lui-même, mais il existe des moyens hacky de l'avoir.

Une façon serait d'écouter le focus de l'edittext et de faire défiler le ScrollView un peu plus comme ceci:

edittext.setOnFocusChangeListener(new OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus)
             scrollView.scrollBy(0, 100);

    });

Comme je l'ai dit, cette méthode est hacky et déconseillée.

Une autre façon (qui dépend de votre mise en page et est préférable si vous le faites fonctionner) serait de définir windowSoftInputMode sur adjustPan ou adjustResize (selon votre mise en page) pour votre activité dans AndroidManifest.xml.

0
Adib Faramarzi