web-dev-qa-db-fra.com

Texte multiligne EditText avec le libellé Action SoftInput Done sur 2.3

Existe-t-il un moyen d'avoir une EditText à plusieurs lignes présente et d'utiliser le libellé Action IME "Terminé" sur Android 2.3?

Dans Android 2.2, ce n’est pas un problème, le bouton Entrée affiche l’étiquette d’action IME "Terminé" (Android:imeActionLabel="actionDone") et supprime la saisie logicielle lorsque vous cliquez dessus.

Lors de la configuration d'une EditText pour plusieurs lignes, Android 2.3 supprime la possibilité d'afficher l'action "Terminé" pour le clavier de saisie logicielle.

J'ai réussi à modifier le comportement du bouton Entrée de saisie logicielle en utilisant une variable KeyListener, mais le bouton Entrée ressemble toujours à une touche Entrée.


Voici la déclaration du EditText

<EditText
        Android:id="@+id/Comment"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="10dp"
        Android:layout_marginBottom="0dp"
        Android:lines="3"
        Android:maxLines="3"
        Android:minLines="3"
        Android:maxLength="60"
        Android:scrollHorizontally="false"
        Android:hint="hint"
        Android:gravity="top|left"
        Android:textColor="#888"
        Android:textSize="14dp"
        />
<!-- Android:inputType="text" will kill the multiline on 2.3! -->
<!-- Android:imeOptions="actionDone" switches to a "t9" like soft input -->

Lorsque je vérifie la valeur inputType après le chargement de la définition du contenu dans l'activité, elle s'affiche comme suit:

inputType = 0x20001

Lequel est:

  • classe = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_NORMAL
  • drapeaux = InputType.TYPE_TEXT_FLAG_MULTI_LINE
79
ohhorob

Après avoir relu les documents TextView et EditorInfo, il est désormais clair que la plate-forme va forcer IME_FLAG_NO_ENTER_ACTION pour les affichages de texte multiligne.

Notez que TextView sera automatiquement régler ce drapeau pour vous sur plusieurs lignes vues de texte.

Ma solution consiste à sous-classer EditText et à ajuster les options IME après avoir laissé la plate-forme les configurer:

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    InputConnection connection = super.onCreateInputConnection(outAttrs);
    int imeActions = outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION;
    if ((imeActions&EditorInfo.IME_ACTION_DONE) != 0) {
        // clear the existing action
        outAttrs.imeOptions ^= imeActions;
        // set the DONE action
        outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
    }
    if ((outAttrs.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
        outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
    }
    return connection;
}

Dans ce qui précède, je force aussi IME_ACTION_DONE, même si cela peut être réalisé grâce à une configuration de mise en page fastidieuse.

159
ohhorob

La réponse d'Ohhorob est fondamentalement correcte, mais son code est vraiment redondant! C'est fondamentalement l'équivalent de cette version beaucoup plus simple (code complet pour les lecteurs paresseux):

package com.example.views;

import Android.content.Context;
import Android.util.AttributeSet;
import Android.view.inputmethod.EditorInfo;
import Android.view.inputmethod.InputConnection;
import Android.widget.EditText;

// An EditText that lets you use actions ("Done", "Go", etc.) on multi-line edits.
public class ActionEditText extends EditText
{
    public ActionEditText(Context context)
    {
        super(context);
    }

    public ActionEditText(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public ActionEditText(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs)
    {
        InputConnection conn = super.onCreateInputConnection(outAttrs);
        outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
        return conn;
    }
}

Notez que certaines options inputType telles que textShortMessage font que cela ne fonctionne pas! Je vous suggère de commencer par inputType="text". Voici comment vous pouvez l'utiliser dans votre XML.

<com.example.views.ActionEditText
    Android:id=...
    Android:layout_stuff=...
    Android:imeOptions="actionDone"
    Android:inputType="textAutoCorrect|textCapSentences|textMultiLine"
    Android:maxLines="3" />
100
Timmmm

Une autre solution pour sous-classer la classe EditText consiste à configurer votre instance EditText avec ceci:

editText.setHorizontallyScrolling(false);
editText.setMaxLines(Integer.MAX_VALUE);

Au moins, cela fonctionne pour moi sur Android 4.0. Il configure l'instance EditText de sorte que l'utilisateur modifie une chaîne à une ligne affichée avec un ajustement progressif sur plusieurs lignes, même si une action IME est définie.

55
Futzilogik

Suite de la réponse précédente

public class MultiLineText extends EditText {

    public MultiLineText(Context context) {
        super(context);
    }

    public MultiLineText(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public MultiLineText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        InputConnection connection = super.onCreateInputConnection(outAttrs);
        int imeActions = outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION;
        if ((imeActions&EditorInfo.IME_ACTION_DONE) != 0) {
            // clear the existing action
            outAttrs.imeOptions ^= imeActions;
            // set the DONE action
            outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
        }
        if ((outAttrs.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
            outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
        }
        return connection;
    }
}

Utilisez ceci comme

<myapp.commun.MultiLineText
  Android:id="@+id/textNotes"
  Android:layout_height="wrap_content"
  Android:minHeight="100dp"
  Android:layout_width="wrap_content"
  Android:hint="Notes"
  Android:textSize="20sp"
  Android:padding="7dp"
  Android:maxLines="4"/> 
6
user3525689

pour mettre l'action terminée, vous pouvez utiliser:

XML

Android:inputType="text|textCapSentences"    

Java

editText.setHorizontallyScrolling(false);
editText.setMaxLines(Integer.MAX_VALUE);

J'espère que ça marchera pour vous.

4
Alex Zaraos

Apparemment, la réponse à la question initiale est Oui, mais je pense que l’équipe Android essaie de faire réfléchir les développeurs à la façon dont ils utilisent le multi-ligne EditText. Ils veulent que la touche Entrée ajoute des nouvelles lignes et s'attendent probablement à ce que vous fournissiez un bouton ou un autre moyen de saisie pour déclencher l'événement que vous avez terminé de modifier.

J'ai le même problème et ma solution évidente consistait simplement à ajouter un bouton Terminé et à laisser le bouton Entrée ajouter les nouvelles lignes.

1
Mullins

Utilisez ces attributs dans votre XML.

Android: inputType = "textImeMultiLine"

Android: imeOptions = "actionDone"

0
Gaurav