124 votes

EditText Focusable dans ListView

J'ai passé environ 6 heures, jusqu'à présent, et frappe, mais rien de barrages routiers. Le principe général est qu'il y a un certain nombre de lignes dans une liste (si elle est générée par la carte, ou ajouté comme une vue d'en-tête) qui contient un EditText un widget et un Bouton. Tout ce que je veux faire est d'être en mesure d'utiliser le jogball/flèches pour naviguer dans le sélecteur d'éléments individuels comme d'habitude, mais quand j'arrive à une ligne particulière, même si j'ai à l'identification explicite de la ligne-qui a un enfant peut recevoir le focus, je veux que l'enfant à prendre le focus au lieu d'indiquer la position du sélecteur.

J'ai essayé beaucoup de possibilités, et n'ont jusqu'à présent pas eu de chance.

mise en page:

<ListView
    android:id="@android:id/list" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent"
    />

Vue d'en-tête:

EditText view = new EditText(this);
listView.addHeaderView(view, null, true);

En supposant que les autres éléments de la carte, à l'aide de la flèche touches permettent de déplacer la sélection vers le haut/vers le bas dans la liste, comme prévu, mais quand arriver à la ligne d'en-tête, il est également affiché avec le sélecteur, et pas moyen de se concentrer dans l'EditText à l'aide de la jogball. Remarque: en appuyant sur le EditText va se concentrer à ce point, cependant, qui s'appuie sur un écran tactile, ce qui ne devrait pas être une exigence.

ListView, apparemment, a deux modes dans ce sujet:
1. setItemsCanFocus(true): sélecteur n'est jamais affiché, mais l'EditText pouvez obtenir le focus lorsque l'aide des flèches. L'accent de l'algorithme de recherche est difficile à prévoir, et pas de retour visuel (sur toutes les lignes: avoir focusable enfants ou pas) sur l'élément sélectionné, ce qui peut donner à l'utilisateur une expérience inattendue.
2. setItemsCanFocus(false): sélecteur est toujours attiré par les non-touch-mode, et EditText n'arrive pas à se concentrer, même si vous appuyez sur elle.

Pour aggraver les choses, appelant editTextView.requestFocus() retourne vrai, mais en fait, ne donne pas l'EditText focus.

Ce que je suis en envisageant est en fait un hybride de 1 & 2, où, plutôt que la configuration de la liste si tous les éléments sont focusable ou pas, je veux mettre focalisation pour un seul élément dans la liste, de sorte que le sélecteur de manière transparente les transitions à partir de la sélection de l'ensemble de la ligne de non-focusable éléments, et en parcourant la focalisation de l'arbre pour les articles qui contiennent focusable enfants.

Les élèves?

103voto

logan Points 515

Cela m’a aidé.

101voto

Joe Points 20463

Désolé, d'avoir répondu à ma propre question. Il peut ne pas être la plus correcte ou solution plus élégante, mais cela fonctionne pour moi, et donne une assez solide expérience de l'utilisateur. J'ai regardé dans le code de ListView de voir pourquoi les deux comportements sont si différents, et suis tombé sur ce de ListView.java:

    public void setItemsCanFocus(boolean itemsCanFocus) {
        mItemsCanFocus = itemsCanFocus;
        if (!itemsCanFocus) {
            setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
        }
    }

Ainsi, lors de l'appel d' setItemsCanFocus(false), c'est également la mise en descendant de la focalisation à ce qu'aucun enfant peut recevoir le focus. C'est ce qui explique pourquoi je ne pourrais pas simplement basculer mItemsCanFocus dans la ListView est OnItemSelectedListener -- parce que la liste a ensuite été le blocage de tous les enfants.

Ce que j'ai maintenant:

<ListView
    android:id="@android:id/list" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent"
    android:descendantFocusability="beforeDescendants"
    />

J'utilise beforeDescendants parce que le sélecteur ne pouvant être utilisée lorsque la liste elle-même (l'enfant) a le focus, de sorte que le comportement par défaut doit être que le ListView faut se concentrer d'abord et attire des sélecteurs.

Puis, dans la OnItemSelectedListener, depuis que je sais qui, vue d'en-tête, je veux remplacer le sélecteur (qui prendra plus de travail pour déterminer dynamiquement si une position donnée contient un focusable vue), je peux changer descendant focalisation, et mis l'accent sur l'EditText. Et quand je navigue de cet en-tête, le modifier à nouveau.

public void onItemSelected(AdapterView<?> listView, View view, int position, long id)
{
    if (position == 1)
    {
        // listView.setItemsCanFocus(true);

        // Use afterDescendants, because I don't want the ListView to steal focus
        listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        myEditText.requestFocus();
    }
    else
    {
        if (!listView.isFocused())
        {
            // listView.setItemsCanFocus(false);

            // Use beforeDescendants so that the EditText doesn't re-take focus
            listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
            listView.requestFocus();
        }
    }
}

public void onNothingSelected(AdapterView<?> listView)
{
    // This happens when you start scrolling, so we need to prevent it from staying
    // in the afterDescendants mode if the EditText was focused 
    listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
}

Remarque l'commenté setItemsCanFocus des appels. Avec ces appels, j'ai eu le bon comportement, mais setItemsCanFocus(false) causée concentrer pour saut à partir d'un EditText, à un autre widget à l'extérieur de la ListView, retour à la liste et affiche le sélecteur sur le prochain élément sélectionné, et que le saut à l'accent était distrayant. Retrait de la ItemsCanFocus changement, et juste basculement descendant focalisation m'a le comportement souhaité. Tous les éléments de tirage le sélecteur normal, mais quand arriver à la ligne avec l'EditText, il s'est concentré sur le champ de texte à la place. Ensuite, en cas de poursuite de cette EditText, il a commencé à dessiner le sélecteur de nouveau.

18voto

AndroidGecko Points 2216

Ma tâche était de mettre en œuvre ListView qui se dilate lorsqu'il est cliqué. L'espace supplémentaire montre EditText où vous pouvez saisir du texte. Application devrait être fonctionnel sur 2.2+ (jusqu'à 4.2.2 au moment de l'écriture de cette page)

J'ai essayé de nombreuses solutions de ce post et d'autres que j'ai pu trouver; testé sur 2.2 jusqu'à 4.2.2 appareils. Aucune des solutions a été satisfactionary sur tous les appareils 2.2+, chaque solution présentée à des problèmes différents.

Je voulais partager ma solution finale :

  1. ensemble listview android:descendantFocusability="afterDescendants"
  2. ensemble listview setItemsCanFocus(true);
  3. définissez votre activité android:windowSoftInputMode="adjustResize" Beaucoup de gens suggèrent adjustPan mais adjustResize donne beaucoup mieux ux à mon humble avis, juste de tester cela dans votre cas. Avec adjustPan , vous obtiendrez bas listitems obscurci par exemple. Docs suggèrent que ("C'est moins souhaitable que le redimensionnement"). Également sur 4.0.4 après que l'utilisateur commence à taper sur le clavier virtuel de l'écran panoramique vers le haut.
  4. sur 4.2.2 avec adjustResize il y a quelques problèmes avec EditText focus. La solution est d'appliquer rjrjr solution de ce fil. Il semble grudge mais il ne l'est pas. Et il fonctionne. Il suffit de l'essayer.

5. En raison de l'adaptateur en cours d'actualisation (en raison de redimensionner vue) lors de l' EditText des gains concentrer sur l'avant en Nid d'abeille versions, j'ai trouvé un problème avec inversée points de vue: l'obtention de Vue de l'élément ListView / ordre inverse 2.2; 4.0.3

Si vous faites des animations, vous pouvez modifier le comportement d' adjustPan pour les pré-nid d'abeille versions afin que les redimensionner ne marche pas, le feu et l'adaptateur n'a pas de rafraîchissement de la vue. Vous avez juste besoin d'ajouter quelque chose comme ceci

if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

Tout cela donne acceptable ux 2.2 - 4.2.2 appareils. Espérons qu'il permettra de sauver des gens, quelque temps qu'il m'a fallu au moins plusieurs heures pour arriver à cette conclusion.

7voto

rjrjr Points 281

Nous essayons cela sur une liste restreinte qui ne fait pas n’importe quel affichage de recyclage. Pour l'instant ça va.

XML :

Java :

4voto

Rafael Sanches Points 926

ce message a été correspondant exactement à mes mots clés. J’ai un en-tête ListView avec une recherche EditText et une bouton de recherche.

Afin de donner le focus à l’EditText après avoir perdu le focus initial le seul HACK que j’ai trouvé est :

Perdu beaucoup d’heures et il n’est pas une réelle Difficulté. Espère que cela aide quelqu'un de difficile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X