L'utilisation et le principe du clavier logiciel Android windowSoftInputMode (utilisation)

avant-propos

Après avoir lu de nombreux articles sur Internet, ils n'ont pas expliqué très précisément les fonctions de plusieurs modes de windowSoftInputMode, et la plupart des articles n'ont analysé que leur utilisation sans analyse approfondie du code source pour analyser les principes.Aujourd'hui, cet article analysera les fonctions et les principes de chaque mode du clavier logiciel Android windowSoftInputMode.

1. Présentation du modèle

android:windowSoftInputMode=["stateUnspecified",
                                       "stateUnchanged", "stateHidden",
                                       "stateAlwaysHidden", "stateVisible",
                                       "stateAlwaysVisible", "adjustUnspecified",
                                       "adjustResize", "adjustPan"]

Comme ci-dessus, windowSoftInputMode a six valeurs stateXXX et trois valeurs adjustXXX. En termes simples, la valeur préfixée par state contrôle la visibilité de la méthode d'entrée du logiciel lorsque l'activité devient le focus de l'utilisateur, et le préfixe préfixé par adjust contrôle la façon dont elle est affichée dans la fenêtre.
Les deux valeurs peuvent être utilisées en combinaison.
Il existe deux types de visibilité : le masquage et l'affichage.
Il existe deux méthodes d'affichage : lorsque la fenêtre logicielle apparaît, réduisez la partie du contenu ou ajustez la position du contenu de sorte que le contrôle de focus se trouve dans la fenêtre visible.
La signification de chaque valeur est la suivante (officielle)

valeur illustrer
" stateUnspecified" L'état du clavier logiciel (caché ou visible) n'est pas spécifié. Ce sera au système de choisir l'état approprié, ou de se fier au réglage dans le thème.

Il s'agit du paramètre par défaut pour le comportement du clavier logiciel.

" stateUnchanged" Préserve le dernier état dans lequel se trouvait le clavier logiciel lorsque l'activité est passée au premier plan, qu'il soit visible ou masqué.
" stateHidden" Lorsque l'utilisateur sélectionne une activité, c'est-à-dire lorsqu'il navigue réellement vers l'avant dans l'activité, plutôt que de revenir après avoir quitté une autre activité, masquez le clavier logiciel.
" stateAlwaysHidden" Masquez toujours le clavier logiciel lorsque la fenêtre principale de l'activité a le focus de saisie.
" stateVisible" Lorsque l'utilisateur sélectionne une activité, c'est-à-dire lorsqu'il navigue réellement vers l'avant dans l'activité, plutôt que de revenir après avoir quitté une autre activité, affiche le clavier logiciel.
" stateAlwaysVisible" Toujours afficher le clavier logiciel lorsque la fenêtre principale de l'activité a le focus de saisie.
" adjustUnspecified" Ne spécifie pas si la fenêtre principale de l'activité est redimensionnée pour faire de la place au clavier logiciel, ou si le contenu de la fenêtre se déplace pour révéler le focus actuel sur l'écran. Le système sélectionne automatiquement l'un de ces modes selon que le contenu de la fenêtre comporte ou non des vues de mise en page pouvant faire défiler leur contenu. Si une telle vue existe, la fenêtre sera redimensionnée, à condition que tout le contenu de la fenêtre puisse être vu dans une zone plus petite en faisant défiler.

Il s'agit du paramètre par défaut pour le comportement de la fenêtre principale.

" adjustResize" Redimensionnez toujours la fenêtre principale de l'activité pour faire de la place au clavier logiciel à l'écran.
" adjustPan" Au lieu d'ajuster la taille de la fenêtre principale de l'activité pour faire de la place au clavier logiciel, le contenu de la fenêtre est automatiquement panoramique afin que le focus actuel ne soit jamais couvert par le clavier, afin que l'utilisateur puisse toujours voir le contenu qu'il a saisi. Ceci est généralement moins souhaitable que le redimensionnement, car l'utilisateur peut avoir besoin de fermer le clavier logiciel pour atteindre ou interagir avec les parties couvertes de la fenêtre.

2. Utilisation de la visibilité

Le rôle spécifique de chaque attribut ne peut pas être clairement compris à travers l'explication ci-dessus, alors laissez-moi vous présenter le rôle de chaque attribut en détail un par un.
Pour la commodité de l'affichage, je vais créer deux activités : InputActivity1 et InputActivity2, et définir leurs propriétés pour le fonctionnement.

1.stateUnchanged

Préserve le dernier état dans lequel se trouvait le clavier logiciel lorsque l'activité est passée au premier plan, qu'il soit visible ou masqué.
Comment comprendre cette phrase ? Nous définissons le windowSoftInputMode des deux activités sur stateUnchanged. Regardez ensuite un exemple d'opération ci-dessous :
insérez la description de l'image ici

Laissez-moi vous expliquer le phénomène. Tout d'abord, lorsque vous entrez InputActivity1, le clavier logiciel n'est pas affiché. Expirez le clavier logiciel sur InputActivity1, puis passez à InputActivity2. À ce stade, vous constaterez que le clavier logiciel sera également affiché sur InputActivity2. Continuez à voir les exemples d'opération suivants :
insérez la description de l'image ici

Le clavier logiciel n'est pas appelé sur InputActivity 1, puis saute à InputActivity 2. À ce stade, on constatera que le clavier logiciel n'est pas affiché sur InputActivity2.
A travers ces deux exemples, nous concluons que stateUnchanged ne changera pas l'état d'affichage du clavier logiciel. Si le clavier logiciel était affiché auparavant, il sera également affiché dans d'autres activités, et vice versa.

Les exemples de tout à l'heure avancent tous vers une autre activité, que se passe-t-il s'il revient à l'activité précédente ?
insérez la description de l'image ici

Tout d'abord, si InputActivity1 n'affiche pas le clavier logiciel, passez à InputActivity2, activez manuellement le clavier logiciel dans InputActivity2, puis revenez à InputActivity1. On peut constater que le clavier logiciel est également affiché à ce moment-là, on peut donc voir que stateUnchanged est applicable qu'il soit en avant ou en arrière .

2.état caché

Lorsque l'utilisateur sélectionne une activité, c'est-à-dire lorsqu'il navigue réellement vers l'avant dans l'activité, plutôt que de revenir après avoir quitté une autre activité, masquez le clavier logiciel.
De même, nous définissons le windowSoftInputMode des deux activités sur stateHidden. Ensuite, regardez l'exemple d'opération suivant :
insérez la description de l'image ici
premièrement, le clavier logiciel n'est pas affiché lors de la saisie de InputActivity1, puis passe à InputActivity2 après avoir activé manuellement le clavier logiciel. Le clavier logiciel est masqué sur InputActivity2, ce qui signifie que stateHidden fonctionne. Lorsque l'utilisateur navigue vers l'activité, le clavier logiciel est masqué .
Appelez ensuite le clavier logiciel sur InputActivity2 et revenez à InputActivity 1. On peut constater que le clavier logiciel InputActivity1 est affiché à ce moment, de sorte que l'on peut voir que stateUnchanged ne prend effet que lorsqu'il avance.

3.stateAlwaysHidden

Masquez toujours le clavier logiciel lorsque la fenêtre principale de l'activité a le focus de saisie.
Bien que le clavier logiciel soit également masqué, il y a moins de qualificatifs pour stateAlwaysHidden.Comme mentionné précédemment, stateHidden doit naviguer vers l'avant jusqu'à l'activité pour prendre effet, mais stateAlwaysHidden n'a pas cette restriction et il prend effet qu'il soit en avant ou en arrière. De même, nous définissons le windowSoftInputMode des deux activités sur stateAlwaysHidden :
insérez la description de l'image ici
la même opération que le stateHidden ci-dessus, mais lorsque le clavier logiciel est activé sur InputActivity2 et renvoyé à InputActivity1, on peut constater que le clavier logiciel de InputActivity1 est masqué à ce moment-là, on peut donc voir que stateAlwaysHidden est applicable, qu'il soit en avant ou en arrière .

4.étatVisible

Lorsque l'utilisateur sélectionne une activité, c'est-à-dire lorsqu'il navigue réellement vers l'avant dans l'activité, plutôt que de revenir après avoir quitté une autre activité, affiche le clavier logiciel.
Visible et Hidden ont la même signification. Afin de voir sa fonction plus clairement, nous définissons InputActivity1 sur stateVisible et InputActivity2 sur stateHidden cette fois, puis regardons l'exemple d'opération suivant : lors de la saisie de InputActivity1, le clavier logiciel s'affiche automatiquement. Lors de la saisie de InputActivity2, il est masqué en raison de l'état défini. Lorsque vous revenez à InputActivity1, il n'est pas affiché, on peut voir que stateVisible ne prend effet que lorsque vous
insérez la description de l'image ici
avancez .

Il y a un point à noter concernant les deux propriétés de Visible :
dans les versions supérieures à Android 9.0, c'est-à-dire API28, les deux propriétés affichées seront invalides, ce qui est expliqué dans les commentaires du code source :

        /**
         * Visibility state for {@link #softInputMode}: please show the soft
         * input area when normally appropriate (when the user is navigating
         * forward to your window).
         *
         * <p>Applications that target {@link android.os.Build.VERSION_CODES#P} and later, this flag
         * is ignored unless there is a focused view that returns {@code true} from
         * {@link View#isInEditMode()} when the window is focused.</p>
         */
        public static final int SOFT_INPUT_STATE_VISIBLE = 4;

        /**
         * Visibility state for {@link #softInputMode}: please always make the
         * soft input area visible when this window receives input focus.
         *
         * <p>Applications that target {@link android.os.Build.VERSION_CODES#P} and later, this flag
         * is ignored unless there is a focused view that returns {@code true} from
         * {@link View#isInEditMode()} when the window is focused.</p>
         */
        public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;

Les applications qui ciblent {@link android.os.Build.VERSION_CODES#P} et versions ultérieures, cet indicateur est ignoré sauf s'il existe une vue focalisée qui renvoie {@code true} à partir de {@link View#isInEditMode()} lorsque la fenêtre est focalisée.

Cet article présente la cause de l'échec en détail : https://blog.csdn.net/weimingjue/article/details/99738271
En termes simples, avant Android 9.0, une activité obtiendra automatiquement le focus après son démarrage, mais cela ne se produira pas par la suite, ce qui entraînera l'échec de l'affichage du clavier logiciel. La solution consiste à obtenir manuellement le focus view.requestFocus() sur le contrôle qui doit être saisi après le démarrage de l' activité

5.stateAlwaysVisible

Toujours afficher le clavier logiciel lorsque la fenêtre principale de l'activité a le focus de saisie.
Pas grand chose à dire à ce sujet, regardez simplement l'exemple d'opération :
insérez la description de l'image ici
Par rapport à stateVisible, le clavier logiciel s'affiche automatiquement lors du retour à InputActivity1. On peut voir que stateAlwaysVisible est applicable qu'il soit en avant ou en arrière.

6.stateUnspecified

L'état du clavier logiciel (caché ou visible) n'est pas spécifié. Ce sera au système de choisir l'état approprié, ou de se fier au réglage dans le thème.
Il s'agit du paramètre par défaut pour le comportement du clavier logiciel.

Je ne rentrerai pas dans les détails de ce paramètre sans préciser une méthode précise (c'est assez compliqué), du moment que vous maîtrisez les autres paramètres ci-dessus, il devrait pouvoir répondre à vos besoins de développement au quotidien.

3. Méthode d'affichage

Analyse simple d'abord :
nous savons que le clavier logiciel est en fait une boîte de dialogue. Lorsque le clavier apparaît, vous pouvez en fait voir deux fenêtres : 1 est la fenêtre de l'activité et 2 est la fenêtre de la boîte de dialogue. Le nœud du problème est que l'affichage de la fenêtre de la boîte de dialogue couvre une partie de la zone de la fenêtre de l'activité. Afin de rendre visible EditText, la mise en page de l'activité est relevée. On suppose que la propriété Window a un paramètre pour contrôler si elle est relevée. En réalité, ce paramètre est WindowManager.LayoutParams.softInputMode.

1.ajusterRedimensionner

Redimensionnez toujours la fenêtre principale de l'activité pour faire de la place au clavier logiciel à l'écran.
AdjustResize ajoute en fait un rembourrage à la disposition racine, et la valeur de rembourrage est la hauteur du clavier logiciel. Vous pouvez ajouter un rembourrage directement à la disposition racine, l'effet est le même.

Nous utilisons le code de mise en page suivant pour les tests :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/myviewgroup"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/iv"
        android:src="@drawable/test"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:layout_width="match_parent"
        android:layout_height="300dp">
    </ImageView>

    <EditText
        android:hint="输入框2"
        android:id="@+id/et2"
        android:layout_gravity="bottom"
        android:layout_marginTop="200dp"
        android:layout_width="100dp"
        android:layout_height="40dp">
    </EditText>

</LinearLayout>

Définissez l'activité sur adjustResize et l'effet après l'exécution est le suivant :
insérez la description de l'image ici
vous pouvez voir que la disposition n'a pas changé et que la zone de saisie est masquée. Cela est dû au fait que la longueur des contrôles dans la disposition est fixe et qu'il n'y a aucun effet même si un rembourrage est ajouté.
Ensuite, nous modifions la mise en page et définissons la hauteur de Imageview sur layout_weight=1 pour remplir l'écran restant.
Le contenu modifié est le suivant :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/myviewgroup"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/iv"
        android:src="@drawable/test"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:scaleType="fitXY"
        android:layout_height="0dp">
    </ImageView>

    <EditText
        android:hint="输入框2"
        android:id="@+id/et2"
        android:layout_width="100dp"
        android:layout_height="40dp">
    </EditText>

</LinearLayout>

insérez la description de l'image ici
On peut voir que le contenu de mise en page qui n'est pas d'une longueur fixe est poussé vers le haut et la hauteur est compressée.

2.réglerPan

Au lieu d'ajuster la taille de la fenêtre principale de l'activité pour faire de la place au clavier logiciel, le contenu de la fenêtre est automatiquement panoramique afin que le focus actuel ne soit jamais couvert par le clavier, afin que l'utilisateur puisse toujours voir le contenu qu'il a saisi. Ceci est généralement moins souhaitable que le redimensionnement, car l'utilisateur peut avoir besoin de fermer le clavier logiciel pour atteindre ou interagir avec les parties couvertes de la fenêtre.
Le AdjustPan fait en fait défiler la mise en page dans son ensemble, quel que soit le type de mise en page ici est un effet, mais il convient de noter que la mise en page de défilement est déterminée en fonction de la position du focus actuel

Testez avec la même mise en page que adjustResize

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/myviewgroup"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center_vertical"
    android:background="@color/white"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:scaleType="fitXY"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:src="@drawable/test"></ImageView>

    <EditText
        android:id="@+id/et2"
        android:layout_width="100dp"
        android:layout_height="40dp"
        android:layout_marginTop="100dp"
        android:hint="输入框2"></EditText>
</LinearLayout>

insérez la description de l'image ici

3.réglerNon spécifié

Ne spécifie pas si la fenêtre principale de l'activité est redimensionnée pour faire de la place au clavier logiciel, ou si le contenu de la fenêtre se déplace pour révéler le focus actuel sur l'écran. Le système sélectionne automatiquement l'un de ces modes selon que le contenu de la fenêtre comporte ou non des vues de mise en page pouvant faire défiler leur contenu. Si une telle vue existe, la fenêtre sera redimensionnée, à condition que tout le contenu de la fenêtre puisse être vu dans une zone plus petite en faisant défiler. Il s'agit du paramètre par défaut pour le comportement de la fenêtre principale.

AdjustUnspecified consiste en fait à choisir l'un des paramètres AdjustResize et AdjustPan. S'il existe une mise en page défilante dans le contenu de la mise en page, choisissez AdjustResize. Sinon, choisissez AdjustPan. Alors, quel type de contenu est un contenu défilable ? En fait, il est principalement défini par l'attribut isScrollContainer Lorsque l'attribut isScrollContainer de la mise en page est défini sur true, cela signifie que la mise en page peut défiler.

Les RecyclerView et ScrollView que nous utilisons habituellement sont tous des contenus défilants, et ils définissent cette propriété lors de leur initialisation

    public RecyclerView(Context context, @android.annotation.Nullable AttributeSet attrs, int defStyle) {
    
    
        ...
        setScrollContainer(true);
        ...
    }

Pour la vue ordinaire, si vous souhaitez définir cette propriété, il existe deux manières :

  1. Dans le code : View.setScrollContainer(true)
  2. xml : android:isScrollContainer="true"

Également testé avec la mise en page ci-dessus

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/myviewgroup"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center_vertical"
    android:background="@color/white"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:scaleType="fitXY"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:src="@drawable/test"></ImageView>

    <EditText
        android:id="@+id/et2"
        android:layout_width="100dp"
        android:layout_height="40dp"
        android:layout_marginTop="100dp"
        android:hint="输入框2"></EditText>
</LinearLayout>

insérez la description de l'image ici
On peut voir que puisqu'il n'y a pas de mise en page coulissante, adjustPan est sélectionné ici pour pousser toute la mise en page vers le haut. Ensuite, nous ajoutons l'attribut isScrollContainer à ImageView :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/myviewgroup"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center_vertical"
    android:background="@color/white"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:scaleType="fitXY"
        android:isScrollContainer="true"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:src="@drawable/test"></ImageView>

    <EditText
        android:id="@+id/et2"
        android:layout_width="100dp"
        android:layout_height="40dp"
        android:layout_marginTop="100dp"
        android:hint="输入框2"></EditText>
</LinearLayout>

insérez la description de l'image ici
Ici, j'ai choisi adjustResize.

4.réglerRien

Ne fais rien.

Résumer

Ce qui précède est l'analyse de la fenêtre contextuelle du clavier logiciel, de la fermeture, de l'affichage, de la hauteur du clavier logiciel, du mode clavier logiciel et d'autres effets.
Si vous voulez comprendre le principe de réalisation des effets ci-dessus, vous pouvez lire l'article suivant, l'utilisation et le principe du clavier logiciel Android windowSoftInputMode (principe)

Je suppose que tu aimes

Origine blog.csdn.net/shanshui911587154/article/details/124462145
conseillé
Classement