web-dev-qa-db-fra.com

Comment masquer le clavier BottomNavigationView sous le paramètre adjustResize

Selon le Material Design Spec , lorsque le clavier apparaît, le BottomNavigationView devrait se cacher en dessous. Cependant, si je mets Android:windowSoftInputMode="adjustResize" dans le manifeste de l'activité, puis le BottomNavigationView se déplace au-dessus du clavier.

Je dois définir adjustResize pour activer le défilement vers le bas de l'écran lorsque le clavier est ouvert. Cependant, je ne veux pas que le BottomNavigationView soit visible. Cela peut-il être fait?

À quoi il ressemble actuellement:

enter image description here

La mise en page XML (en réalité, il y aurait un FrameLayout où se trouve le EditText et le EditText à l'intérieur):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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">

    <EditText
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:hint="Input"
        Android:layout_gravity="center"
        Android:layout_centerVertical="true"/>

    <Android.support.design.widget.BottomNavigationView
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_alignParentBottom="true"
        app:itemBackground="@color/colorPrimary"
        app:menu="@menu/menu_bottom_navigation"
        app:itemIconTint="@Android:color/white"
        app:itemTextColor="@Android:color/white"/>

</RelativeLayout>
29
willjgriff

Ajoutez ceci à votre activité dans le manifeste

Android:windowSoftInputMode="adjustPan"

Alors comme

<activity Android:name=".feature.home.HomeActivity" 
 Android:windowSoftInputMode="adjustPan"/>
45
sabbibJAVA

Solution (ou autre façon de faire de même)

J'ai vécu exactement la même situation que OP a déclaré, j'avais un BottomNavigationView évidemment au bas de l'écran et au-dessus il y avait ScrollView.

Maintenant, si nous faisons adjustPan en activité, alors BottomNavigationView reste en bas lorsque le clavier apparaît mais le défilement ne fonctionne pas.

Et si nous faisons adjustResize alors le défilement fonctionne mais BottomNavigationView est poussé au-dessus du clavier.

Je pense que ci-dessous peut être deux approches pour le même.

Approche 1

Réglez simplement la visibilité sur disparu/visible lors de l'affichage/masquage du clavier. C'est un travail rapide pour la même chose. Vous pouvez obtenir un écouteur pour l'événement de masquage/affichage du clavier dans la prochaine approche.

Pour le rendre intéressant, vous pouvez essayer d'afficher/masquer BottomNavigationView avec une sorte d'animation.

Approche 2

Une meilleure façon (la méthode de conception matérielle) serait d'utiliser CoordinatorLayout et le comportement de défilement (comme vous avez pu le voir CollapsingToolBar).

Ci-dessous serait le fichier de mise en page

<?xml version="1.0" encoding="utf-8"?>
<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.support.design.widget.AppBarLayout
        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="@style/ThemeOverlay.AppCompat.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:title="@string/title"
            app:titleTextColor="@Android:color/white" />
    </Android.support.design.widget.AppBarLayout>

    <Android.support.v4.widget.NestedScrollView
        Android:id="@+id/nestedScrollView"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

    ------ Your Contents --------

    </Android.support.v4.widget.NestedScrollView>

    <Android.support.design.widget.BottomNavigationView
        Android:id="@+id/navigation"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_gravity="bottom"
        Android:background="?android:attr/windowBackground"
        app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"
        app:menu="@menu/navigation" />
</Android.support.design.widget.CoordinatorLayout>

Ça y est, vous pouvez maintenant voir le BottomNavigationView se cacher/s'afficher lors du défilement vers le bas et le haut, etc.

Et le problème est que lorsque le clavier s'ouvre et que vous faites défiler vers le bas, ce qui masque le BottomNavigationView, maintenant si vous appuyez sur le bouton de retour, le clavier se cache mais le BottomNavigationView reste toujours masqué. Maintenant, comme le contenu ne peut pas défiler, donc si vous essayez de faire défiler, il n'affiche pas BottomNavigationView. Pour le révéler à nouveau, vous devez à nouveau rendre le clavier visible et faire défiler vers le haut, lorsque BottomNavigationView s'affiche, puis appuyez sur le bouton de retour.

J'ai essayé de résoudre ce problème de cette façon,

Ajoutez un écouteur global pour savoir si le clavier est affiché ou masqué. Le code que j'ai utilisé ici était (il est dans Kotlin, mais vous pouvez facilement le convertir en Java si vous en avez besoin))

private fun addKeyboardDetectListener(){
    val topView = window.decorView.findViewById<View>(Android.R.id.content)
    topView.viewTreeObserver.addOnGlobalLayoutListener {
        val heightDifference = topView.rootView.height - topView.height
        if(heightDifference > dpToPx(this, 200F)){
            // keyboard shown
            Log.d(TAG, "keyboard shown")
        } else {
            // keyboard hidden
            Log.d(TAG, "keyboard hidden")
            val behavior = (navigation.layoutParams as CoordinatorLayout.LayoutParams).behavior as HideBottomViewOnScrollBehavior
            behavior.slideUp(navigation)
        }
    }
}

fun dpToPx(context: Context, valueInDp: Float) : Float{
    val displayMetrics = context.resources.displayMetrics
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, displayMetrics)
}

Et la dernière chose, si vous utilisez la bibliothèque de support version 28.0.0, vous verrez que la méthode behavior.slideUp(navigation) est protégée, vous ne pouvez donc pas l'appeler depuis votre activité, etc.

Cependant, Google Android a déjà rendu ces méthodes publiques dans le nouveau material-components. Cochez ceci il vous suffit donc d'importer des composants matériels dans votre projet et d'utiliser cette classe au lieu.

En dehors de cela, vous pouvez essayer d'autres expériences comme appeler par programmation slideUp ou slideDown sur le clavier masquer/afficher, etc.

P.S. J'ai passé beaucoup de temps à arriver à cette approche pleinement fonctionnelle, alors j'ai pensé à la partager ici, afin qu'elle puisse faire gagner du temps à quelqu'un.

1
gprathour

ajoutez la ligne suivante dans votre manifeste: Android: windowSoftInputMode = "adjustPan"

<activity
   Android:name=".main.MainActivity"
   Android:screenOrientation="portrait"
   Android:windowSoftInputMode="adjustPan" />
0

Il existe une autre solution, qui ne nécessite pas adjustSpan, mais elle ne fonctionne que pour API >= 21. Vous pouvez détecter si le clavier est affiché/masqué en suivant les encarts du système. Supposons que vous ayez BottomNavigationView, qui est l'enfant de LinearLayout et que vous devez le masquer lorsque le clavier est affiché:

> LinearLayout
  > ContentView
  > BottomNavigationView

Tout ce que vous devez faire est d'étendre LinearLayout de la manière suivante:

public class KeyboardAwareLinearLayout extends LinearLayout {
    public KeyboardAwareLinearLayout(Context context) {
        super(context);
    }

    public KeyboardAwareLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public KeyboardAwareLinearLayout(Context context,
                                     @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public KeyboardAwareLinearLayout(Context context, AttributeSet attrs,
                                     int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
        int childCount = getChildCount();
        for (int index = 0; index < childCount; index++) {
            View view = getChildAt(index);
            if (view instanceof BottomNavigationView) {
                int bottom = insets.getSystemWindowInsetBottom();
                if (bottom >= ViewUtils.dpToPx(200)) {
                    view.setVisibility(GONE);
                } else {
                    view.setVisibility(VISIBLE);
                }
            }
        }
        return insets;
    }
}

L'idée est que lorsque le clavier est affiché, les insertions système sont modifiées avec un assez gros .bottom valeur.

0
nikis