Wielowierszowy tekst edycji z etykietą Done SoftInput Action w wersji 2.3

82

Czy istnieje sposób na EditTextprezentację wielu wierszy i użycie etykiety działania IME „Gotowe” w systemie Android 2.3?

W systemie Android 2.2 nie stanowi to problemu, przycisk Enter wyświetla etykietę czynności IME „Gotowe” ( android:imeActionLabel="actionDone") i odrzuca wprowadzanie programowe po kliknięciu.

Podczas konfigurowania EditTextwieloliniowego systemu Android 2.3 usuwa możliwość wyświetlania czynności „Gotowe” dla klawiatury programowej.

Udało mi się zmienić zachowanie przycisku wprowadzania miękkiego wprowadzania danych za pomocą a KeyListener, jednak przycisk enter nadal wygląda jak klawisz Enter.


Oto deklaracja 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 -->

Kiedy sprawdzam inputTypewartość po wczytaniu ustawienia widoku treści w działaniu, to pokazuje się jako:

inputType = 0x20001

Który jest:

  • class = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_NORMAL
  • flagi = InputType.TYPE_TEXT_FLAG_MULTI_LINE
ohhorob
źródło

Odpowiedzi:

163

Cóż, po ponownym przeczytaniu dokumentów TextViewi EditorInfostało się jasne, że platforma będzie wymuszać IME_FLAG_NO_ENTER_ACTIONwyświetlanie tekstu w wielu wierszach.

Zwróć uwagę, że TextViewautomatycznie ustawi tę flagę w widokach tekstu wielowierszowego.

Moim rozwiązaniem jest podklasa EditTexti dostosowanie opcji IME po umożliwieniu platformie ich skonfigurowania:

@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;
}

W powyższym też wymuszam IME_ACTION_DONE, chociaż można to osiągnąć poprzez żmudną konfigurację układu.

ohhorob
źródło
24
Zwykle nie udzielam ogólnych komentarzy, takich jak „dziękuję”, ale ta odpowiedź była na tyle pomocna i niedoceniona, że ​​uznałam, że zasługuje na uznanie. Podsumowując, dzięki. :-)
oracz
3
+1 dla odpowiedzi, ale jeśli ustawisz typ wejścia edittext z kodu w tym przypadku. Usuwa przewijanie w pionie i dodaje przewijanie w poziomie. Aby rozwiązać ten problem, użyj poniższego kodu. editTextObj.setInputType (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE); Zwykle może się zdarzyć, jeśli ponownie używasz widoku, umieszczając go w wielu układach. @ohhorob wielkie dzięki za rozwiązanie.
Jayshil Dave
2
To działa jak urok! Ale tak naprawdę nie rozumiem kodu. Masz miejsce, w którym mogę przeczytać o całym mechanizmie flagi?
vanleeuwenbram
Dzięki, jestem początkującym, umieściłem to w mojej aktywności, która używa okna dialogowego EditText, więc nie ma tego w moim pliku XML aktywności. Próbowałem wprowadzenie tego kodu w mojej działalności, ale mam błąd: The method onCreateInputConnection(EditorInfo) of type SMSMain must override or implement a supertype method. Dzwonisz superna początku, więc nie wiesz, w czym jest problem. Masz jakieś sugestie? Dzięki.
Azurespot
@NoniA. musisz stworzyć podklasę EditText. iw tej klasie musisz wywołać tę metodę. utwórz klasę, która rozszerza się do EditText. i umieść tę metodę w tej klasie.
Shah
104

Odpowiedź Ohhoroba jest w zasadzie poprawna, ale jego kod jest naprawdę zbędny! Jest to w zasadzie odpowiednik tej znacznie prostszej wersji (pełny kod dla leniwych czytelników):

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;
    }
}

Zwróć uwagę, że niektóre inputTypeopcje, takie jak textShortMessagesprawiają, że to nie działa! Proponuję zacząć od inputType="text". Oto, jak możesz go użyć w swoim XML.

<com.example.views.ActionEditText
    android:id=...
    android:layout_stuff=...
    android:imeOptions="actionDone"
    android:inputType="textAutoCorrect|textCapSentences|textMultiLine"
    android:maxLines="3" />
Timmmm
źródło
Timmmm, czy to jest testowane na 2.3?
ohhorob
1
Jeśli twój kod działa na 2.3, to powinienem być mój. Są prawie takie same, a ja bazuję na swoim lub twoim kodzie, więc dzięki! Czy istnieją cechy charakterystyczne wersji 2.3, których nie ma w wersji 4.0? Standardowe „brak działań w przypadku edycji wielowierszowej” to celowe zachowanie dodane przez Google.
Timmmm,
5
Wypróbowałem to na 2.3 (i 4.x) i zadziałało w mojej aplikacji.
mlc
2
@ matej.smitala Tak, nie możesz mieć obu.
Timmmm
1
Po wielu godzinach poszukiwania najlepszego rozwiązania wydaje się to najlepszym i najprostszym sposobem na uzyskanie wielowierszowego tekstu edycji bez klawisza Enter.
micnguyen
56

Alternatywnym rozwiązaniem do tworzenia podklas klasy EditText jest skonfigurowanie instancji EditText w następujący sposób:

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

Przynajmniej działa to dla mnie na Androida 4.0. Konfiguruje instancję EditText tak, aby użytkownik edytował jednowierszowy ciąg, który jest wyświetlany z miękkim zawijaniem w wielu wierszach, nawet jeśli jest ustawiona akcja IME.

Futzilogik
źródło
2
@Futzilogik: Ty, panie, zasługujesz na znacznie więcej pochwał! Ta odpowiedź uratowała życie i była też prosta. Mam na myśli, omg wow. Chciałbym móc zagłosować za więcej niż raz. Wielkie dzięki!
Swayam
3
Używam 4.4.2 i to nie zadziałało dla mnie lub przynajmniej mojego sposobu na zrobienie tego. Zrobiłem to tylko w XML, więc może to jest problem. Skonfigurowałem inputType na „textEmailAddress | textMultiLine”, scrollHorizontally na false, maxLines na 500 (plik xml), singleLine na false i imeOptions na actionNext. Próbowałem usunąć „textMultiLine” z inputtype. Dzięki textMultiLine dostaję klawisz ENTER na klawiaturze, a bez niego wszystko pozostaje w jednej linii i nadal przewija się w poziomie. Wydawało się, że to najłatwiejsze rozwiązanie, ale powyższe działa dla mnie, więc na razie z nim korzystam.
reaktywny rdzeń
6
Jeśli chodzi o mój poprzedni komentarz (nie mogłem go edytować), podejrzewając, że był to problem z ustawieniem MAX_VALUE lub po prostu zmienianiem ich po utworzeniu edittext, wypróbowałem kod, jak wskazano tutaj, i działa! Chciałem tylko pisać dla innych, nie możesz tego zrobić w XML (albo i tak nie mogłem). Inne ustawienia, które mam: singleLine = false, imeOptions = actionNext, inputType = textEmailAddress (bez multiline).
reaktywny rdzeń
działa bardzo dobrze. To jest dobry przykład ulepszenia starej odpowiedzi !!
nPn
Pracuje dla mnie na Galaxy S5 z systemem Lollipop. Świetne rozwiązanie. Dziwne, że ustawienie przewijania w poziomie w
formacie
7

Po poprzedniej odpowiedzi

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;
    }
}

Użyj tego jak

<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"/> 
user3525689
źródło
5

aby umieścić akcję Gotowe, możesz użyć:

XML

android:inputType="text|textCapSentences"    

JAWA

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

Mam nadzieję, że to zadziała dla Ciebie.

Alex Zaraos
źródło
1

Najwyraźniej odpowiedź na pierwotne pytanie brzmi: tak, ale wydaje mi się, że zespół Androida stara się skłonić programistów do zastanowienia się nad tym, jak używają wielowierszowego tekstu edycji. Chcą, aby klawisz Enter dodawał nowe linie i prawdopodobnie spodziewają się, że podasz przycisk lub inny środek wejściowy, aby wywołać zdarzenie, które skończyłeś edytować.

Mam ten sam problem i moim oczywistym rozwiązaniem było po prostu dodanie przycisku Gotowe i pozwolenie klawiszowi Enter na dodanie nowych linii.

Mullins
źródło
Przepraszam, moje pytanie mogło nie być wystarczająco jasne. Wiele linii służy do miękkiego zawijania jednowierszowych danych wejściowych. tzn. znaki nowego wiersza nie są dozwolone.
ohhorob
@Mullins: Czy dodałeś własny przycisk „gotowe” do klawiatury SoftInput? Jak to zrobiłeś, zachowując „Enter”?
alex.veprik
Nie. Utworzyłem przycisk „Gotowe” w interfejsie użytkownika oddzielnie od klawiatury.
Mullins,
1
Cóż, może zespół Androida powinien postępować zgodnie z własną radą i ustawić przycisk akcji wielowierszowego TextEdit w aplikacji do obsługi wiadomości, aby zamiast wysyłać wiadomość, tworzyć nowe linie.
Timmmm,
0

Użyj tego atrybutu w swoim pliku XML.

android: inputType = "textImeMultiLine"

android: imeOptions = "actionDone"

Gaurav
źródło