EditText multi-baris dengan tombol tindakan Selesai

114

Apakah mungkin memiliki EditTextwidget dengan android:inputType="textMultiLine"set, dan android:imeOptions="actionDone"pada saat yang sama?

Saya ingin kotak edit multi-baris, dengan tombol tindakan di keyboard menjadi Selesai, bukan Enter (Carriage Return), tetapi sepertinya tidak berfungsi ..

Terima kasih sebelumnya

kefs
sumber
Bagaimana jika mencoba widget gabungan dengan EditText multiline dan Tombol digabungkan?
Subin Sebastian

Jawaban:

195

Menggunakan

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
editText.setRawInputType(InputType.TYPE_CLASS_TEXT);

dan dalam XML:

android:inputType="textMultiLine"
alexbtr.dll
sumber
bagi saya kursor masih akan muncul saat keyboard turun, saya perlu menambahkan textField.setCursorVisible(false);di dalamonEditorActionListener
Fonix
Bekerja pada 4.2.2 dan 7.1.1. Terima kasih.
tehcpu
1
Bekerja dengan sangat baik ... Saya kesulitan untuk menemukannya. Jawaban ini harus ditandai sebagai jawaban terbaik
MFAL
7
mengapa ini bekerja sebagai kebalikan dari pengaturan semuanya di xml?
Andrew Steinmetz
1
Berjuang sedikit untuk menemukan info ini. Ini masih berfungsi seperti pesona!
Costin
51

Dari dokumentasi android: ' "textMultiLine" Keyboard teks normal yang memungkinkan pengguna memasukkan string teks panjang yang menyertakan jeda baris (carriage return) . 'Oleh karena itu, atribut textMultiLine tidak sesuai jika Anda ingin memiliki tombol' Selesai 'di keyboard.

Cara sederhana untuk mendapatkan bidang masukan multi-baris (dalam hal ini 3 baris) dengan tombol selesai adalah menggunakan EditText dengan

android:lines="3" 
android:scrollHorizontally="false" 

Namun, untuk beberapa alasan ini hanya berfungsi untuk saya jika saya melakukan pengaturan ini dalam kode dan bukan file tata letak (di onCreate) oleh

TextView tv = (TextView)findViewById(R.id.editText);
if (tv != null) {
    tv.setHorizontallyScrolling(false);
    tv.setLines(3);
}

Saya harap ini membantu seseorang, karena butuh waktu cukup lama untuk mengetahuinya. Jika Anda menemukan cara untuk membuatnya bekerja dari manifes, beri tahu kami.

HYS
sumber
4
Saya juga menyarankan untuk mencoba maxLines()daripada setLines()jika Anda ingin menghindari mengubah ketinggianEditText
Daniel Smith
Saya pikir dalam pertanyaan itu tidak dijelaskan bahwa Anda harus menyetel android: imeOptions dengan nilai seperti actionSend. Melengkapi jawaban ini, saya harus menyetel android: singleLine = "true" bahkan jika setMaxLines semacam menimpanya dengan kode (tidak melakukannya tidak akan memberi Anda kunci enter dengan misalnya "Kirim"). Untuk merekam tindakan <Enter>, periksa jawaban pertama dari stackoverflow.com/questions/5014219/… keluar.
DNax
Maaf, alternatif terbaik yang saya temukan tentang menangkap <Enter> adalah jawaban @earlcasper di sini stackoverflow.com/questions/1489852/…
DNax
1
Ini bekerja dengan sempurna untuk saya (menggunakan setMaxLines(3)) Terima kasih banyak!
laurencevs
1
Berfungsi seperti pesona: cukup tambahkan android: imeOptions = "actionDone" android: inputType = "text" ke XML Anda juga dan hapus android: lines = "3" android: scrollHorizontally = "false" dari XML
HannahCarney
24

Contoh Kerja! Buat kelas EditText kustom di bawah ini yang mendukung fitur ini dan gunakan kelas tersebut dalam file xml. Kode kerja:

package com.example;

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

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

<com.example.ActionEditText
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:imeOptions="actionDone"
       android:inputType="textAutoCorrect|textCapSentences|textMultiLine" />
Anees U
sumber
Ini bekerja untuk saya, kebutuhan saya adalah membuat teks edit yang harus multi baris dan juga harus memiliki tombol berikutnya pada tombol lunak ............... jadi terima kasih banyak atas apa yang saya lakukan dalam edit teks saya menambahkan 2 baris android: inputType = "textMultiLine" android: imeOptions = "actionNext" Dan di kelas kustom di atas saya lakukan: InputConnection conn = super.onCreateInputConnection (outAttrs); //outAttrs.imeOptions & = ~ EditorInfo.IME_FLAG_NO_ENTER_ACTION; outAttrs.imeOptions & = EditorInfo.IME_ACTION_NEXT; koneksi kembali;
yash
Bekerja. Diuji pada Andorid 6.0.1.
AmiguelS
9

Untuk melakukan ini di Kotlin (dan juga secara opsional menerapkan konfigurasi lain seperti textCapSentencesAnda dapat menggunakan fungsi ekstensi ini:

// To use this, do NOT set inputType on the EditText in the layout
fun EditText.setMultiLineCapSentencesAndDoneAction() {
    imeOptions = EditorInfo.IME_ACTION_DONE
    setRawInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or InputType.TYPE_TEXT_FLAG_MULTI_LINE)
}

Pemakaian:

myEditText.setMultiLineCapSentencesAndDoneAction()
Ollie C
sumber
1
Bekerja mulai Juni 2019! Terima kasih :)
Rohan Taneja
Kunci bagi saya adalah untuk menggunakan setRawInputTypebukannyasetInputType
Tamoxin
9

Saya pikir ini adalah cara untuk melakukan sesuatu. Memiliki android:inputType="textMultiLine", android:imeOptions="actionDone"membuat fungsi kunci enter menjadi ambigu. Hanya perlu diingat bahwa Anda dapat menggunakan android:lines="10"dan mungkin menghapus android:inputType="textMultiLine", tetapi tergantung pada apa yang ingin Anda capai terkadang Anda hanya perlu android:inputType="textMultiLine"dan tidak ada penggantinya.

EditText ed=new EditText(this);
ed.setOnKeyListener(new OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if(keyCode == KeyEvent.KEYCODE_ENTER){
                //do your stuff here
            }
            return false;
        }
});
Lukap
sumber
Menggunakan jumlah tetap angka maks dengan android: lines = "10" berhasil untuk saya, mendapatkan tombol ok di keyboard. Trik yang bagus jika seseorang mengetahui berapa banyak baris yang akan ada, misalnya dengan set maxLength yang kecil.
sunadorer
Saya ingin menonaktifkan keyCode # 66 apakah mungkin? Bagaimana saya bisa melakukan itu?
Adil Malik
1
mengapa keyCode == 66 sebagai gantinya keyCode == EditorInfo.IME_ACTION_GO?
tse
5

Ini tampaknya bekerja untuk saya dengan sempurna

int lineNum = 2;
mEditText.setHorizontallyScrolling(false);
mEditText.setLines(3);
yonez
sumber
4

Solusi Kotlin yang Dapat Digunakan Kembali

Menetapkan nilai-nilai ini dalam kode adalah satu-satunya hal yang berhasil bagi saya

edittext.inputType = EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
edittext.setHorizontallyScrolling(false)
edittext.maxLines = Integer.MAX_VALUE // Or your preferred fixed value

Saya sering membutuhkan ini, jadi buatlah ini untuk menjaga kode tetap bersih:

fun EditText.multilineIme(action: Int) {
    imeOptions = action
    inputType = EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
    setHorizontallyScrolling(false)
    maxLines = Integer.MAX_VALUE
}

// Then just call
edittext.multilineIme(EditorInfo.IME_ACTION_DONE)

Jika Anda ingin menambahkan tindakan kustom opsional pada 'Selesai', coba ini:

fun EditText.multilineDone(callback: (() -> Unit)? = null) {
    val action = EditorInfo.IME_ACTION_DONE
    multilineIme(action)
    setOnEditorActionListener { _, actionId, _ ->
            if (action == actionId) {
                callback?.invoke()
                true
            }
            false
        }
    }
}

// Then you can call
edittext.multilineDone { closeKeyboard() }

// or just
edittext.multilineDone()

Perlu mengontrol keyboard dengan mudah dalam panggilan balik? Baca postingan ini

Kemudian tambahkan hideKeyboard()panggilan masukEditText.multilineDone

Gibolt
sumber
1
☝️Ini jawaban yang bagus
Michael
3

Jawaban singkat: Tidak, saya yakin itu tidak mungkin dilakukan sebelum API level 11 (3.0).

Masalah yang sama muncul di sini (dibahas dalam komentar untuk jawaban yang diterima):

Tombol tindakan keyboard Soft Android

Dari komentar terakhir:

Melihat beberapa aplikasi di ponsel saya, tampaknya umum untuk memiliki kotak multiline terakhir, dengan tombol "Selesai" atau "Kirim" yang terlihat di bawahnya (mis. Aplikasi Email).

Martin Stone
sumber
3

Cara sederhana untuk mengatasi situasi ini:

  • pertahankan atribut ini di EditText:

    android:inputType="textMultiLine" 
    android:scrollHorizontally="false"
  • lalu tambahkan kode ini untuk hanya menyembunyikan keyboard saat ENTER ditekan:

    editText.setOnEditorActionListener(new OnEditorActionListener() 
    {
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) 
        {
            editText.setSelection(0);
            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);      
            return true;
         } 
         else 
         {
            return false;
         }
         }
    });
Jean Gonçalves
sumber
2

Jika ini bukan tentang tampilan keyboard di layar, Anda cukup meletakkan pendengar masukan di keyboard dan mengaktifkan status "selesai" jika pengguna memasukkan baris baru.

twall
sumber
2

jika Anda menggunakan opsi input textImeMultiline dengan imeoptions flagnext dan actionnext Anda mendapatkan tombol berikutnya daripada cariage kembali

Marcusdev
sumber
2

Meskipun tidak ada solusi lain yang berhasil untuk saya, berikut ini yang berhasil baik dan menyelamatkan saya berhari-hari untuk lebih googling, dengan beberapa tikungan saya sendiri tentunya. Sayangnya tidak ingat persisnya dari mana saya mendapatkan kodenya sehingga tidak dapat memberikan kredit yang layak diterimanya kepada penulis.

Dalam kode Java Anda:

////////////Code to Hide SoftKeyboard on Enter (DONE) Press///////////////
editText.setRawInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
editText.setImeActionLabel("DONE",EditorInfo.IME_ACTION_DONE);              //Set Return Carriage as "DONE"
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) 
    {
                if (event == null) {
                    if (actionId == EditorInfo.IME_ACTION_DONE) {
                        // Capture soft enters in a singleLine EditText that is the last EditText
                        // This one is useful for the new list case, when there are no existing ListItems
                        editText.clearFocus();
                        InputMethodManager inputMethodManager = (InputMethodManager)  getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
                        inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
                    }

                    else if (actionId == EditorInfo.IME_ACTION_NEXT) {
                        // Capture soft enters in other singleLine EditTexts
                    } else if (actionId == EditorInfo.IME_ACTION_GO) {
                    } else {
                        // Let the system handle all other null KeyEvents
                        return false;
                    }
                } 
        else if (actionId == EditorInfo.IME_NULL) {
                    // Capture most soft enters in multi-line EditTexts and all hard enters;
                    // They supply a zero actionId and a valid keyEvent rather than
                    // a non-zero actionId and a null event like the previous cases.
                    if (event.getAction() == KeyEvent.ACTION_DOWN) {
                        // We capture the event when the key is first pressed.
                    } else {
                        // We consume the event when the key is released.
                        return true;
                    }
                } 
        else {
                    // We let the system handle it when the listener is triggered by something that
                    // wasn't an enter.
                    return false;
                }
                return true;
        }
});
Kaushik NP
sumber
1

Saya menggunakan 4.x dan mencoba memanggil setHorizontallyScrolling () (dengan atau tanpa setLine () atau setMaxLines ()), serta banyak konfigurasi XML yang berbeda untuk menampilkan tombol Selesai. Tak satu pun dari mereka berhasil. Intinya adalah jika EditText Anda multi-baris, Android akan selalu ingin menampilkan carriage return alih-alih tombol "Selesai", kecuali Anda melakukan peretasan seputar ini.

Solusi paling rumit yang saya temukan yang tidak melibatkan pemetaan ulang perilaku kembalinya kereta ada di sini: https://stackoverflow.com/a/12570003/3268329 . Solusi ini akan meniadakan keinginan tanpa henti Android untuk memaksa pengaturan bendera IME_FLAG_NO_ENTER_ACTION untuk tampilan multi-garis, yang menyebabkan tombol Selesai menghilang.

Steve B
sumber
0

Saya berjuang juga selama beberapa waktu, tetapi akhirnya saya menemukan solusi!

Buat saja kelas EditText kustom seperti:

public class EditTextImeMultiline extends EditText {

    public void init() {
        addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                for (int i = s.length(); i > 0; i--)
                    if (s.subSequence(i - 1, i).toString().equals("\n"))
                        s.replace(i - 1, i, "");
            }
        });
        setSingleLine();
        setHorizontallyScrolling(false);
        this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                EditTextImeMultiline.this.setLines(EditTextImeMultiline.this.getLineCount());
            }
        });
    }

    public EditTextImeMultiline(Context context) {
        super(context);
        init();
    }

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

    public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }
}

Kelas ini menghapus lineBreaks (\ n), membungkus teks seperti yang akan dilakukan textMultiline, DAN memungkinkan Anda untuk mengganti tombol Enter dengan ImeAction;).

Anda hanya perlu memanggilnya dalam XML Anda, bukan dalam kelas EditText klasik.

Untuk menjelaskan logikanya di sini:

  • Setel EditText sebagai singleLine agar dapat menampilkan tombol ImeAction alih-alih Enter.
  • Hapus pengguliran horizontal untuk membuat teks pindah ke baris berikutnya saat mencapai akhir tampilan.
  • Perhatikan perubahan tata letak dengan onGlobalLayoutListener, dan setel parameter "line" ke "lineCount" dari teks saat ini yang dipegang oleh editText. Inilah yang menyegarkan ketinggiannya.
Gabriel Morin
sumber