Bagaimana cara saya menangani klik tombol yang dilakukan ImeOptions?

185

Saya memiliki di EditTextmana saya mengatur properti berikut sehingga saya dapat menampilkan tombol selesai pada keyboard ketika pengguna mengklik EditText.

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

Ketika pengguna mengklik tombol selesai pada keyboard layar (selesai mengetik) saya ingin mengubah RadioButtonkeadaan.

Bagaimana saya bisa melacak tombol selesai ketika ditekan dari keyboard layar?

Cuplikan layar memperlihatkan tombol 'selesai' kanan bawah pada keyboard perangkat lunak

b-man
sumber
1
mungkin OnKeyboardActionListener membantu saya contoh kode apa saja ??
d-man

Jawaban:

210

Saya berakhir dengan kombinasi jawaban Roberts dan chirags:

((EditText)findViewById(R.id.search_field)).setOnEditorActionListener(
        new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        // Identifier of the action. This will be either the identifier you supplied,
        // or EditorInfo.IME_NULL if being called due to the enter key being pressed.
        if (actionId == EditorInfo.IME_ACTION_SEARCH
                || actionId == EditorInfo.IME_ACTION_DONE
                || event.getAction() == KeyEvent.ACTION_DOWN
                && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
            onSearchAction(v);
            return true;
        }
        // Return true if you have consumed the action, else false.
        return false;
    }
});

Pembaruan: Kode di atas beberapa kali akan mengaktifkan panggilan balik dua kali. Alih-alih, saya memilih kode berikut, yang saya dapatkan dari klien obrolan Google:

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    // If triggered by an enter key, this is the event; otherwise, this is null.
    if (event != null) {
        // if shift key is down, then we want to insert the '\n' char in the TextView;
        // otherwise, the default action is to send the message.
        if (!event.isShiftPressed()) {
            if (isPreparedForSending()) {
                confirmSendMessageIfNeeded();
            }
            return true;
        }
        return false;
    }

    if (isPreparedForSending()) {
        confirmSendMessageIfNeeded();
    }
    return true;
}
Thomas Ahle
sumber
4
Saya hanya mencari IME_ACTION_DONE dan saya terkejut bahwa itu tidak memicu. Setelah saya juga mencari ACTION_DOWN dan KEYCODE_ENTER akhirnya dipicu padaEditorAction (). Karena saya tidak melihat perbedaan pada keyboard bawaan (saya berharap tombol Enter akan disorot) Saya bertanya-tanya apa gunanya menggunakan android: imeOptions = "actionSend" untuk tata letak EditText XML.
Seseorang di suatu tempat
mengapa jawaban ini tidak diterima. apakah ini gagal dalam beberapa kasus ??
Archie.bpgc
1
developer.android.com/reference/android/widget/… (Deskripsi tentang apa 'acara' itu menegaskan hal yang sama.)
Darpan
2
Solusi kedua juga dipicu dua kali.
Bagusflyer
1
Apa itu isPreparedForSending()dan mengapa metode kedua kembali true?
CoolMind
122

Coba ini, ini akan bekerja untuk apa yang Anda butuhkan:


editText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    if (actionId == EditorInfo.IME_ACTION_DONE) {
       //do here your stuff f
       return true;
    }
    return false;
    } 
});
chikka.anddev
sumber
10
Ini tidak berfungsi untuk HTC Evo. Sejauh yang saya bisa mengerti, HTC menerapkan soft keyboard mereka sendiri yang mengabaikan imeOptions.
Dan
Ini sudah cukup (tidak perlu melihat aksi acara atau kode kunci, seperti dalam jawaban yang diterima); berfungsi pada perangkat uji Nexus dan Samsung saya.
Jonik
hanya untuk aman, pastikan bahwa tindakan dalam kode dan tampilan cocok <EditText android:imeOptions="actionDone" android:inputType="text"/>
bh_earth0
40
<EditText android:imeOptions="actionDone"
          android:inputType="text"/>

Kode Java adalah:

edittext.setOnEditorActionListener(new OnEditorActionListener() { 
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            Log.i(TAG,"Here you can write the code");
            return true;
        }    
        return false;
    }
});
Vinoj Vetha
sumber
Anda harus mengembalikan true dalam klausa if untuk mengatakan Anda sudah menanganinya
Tim Kist
26

Saya tahu pertanyaan ini sudah lama, tetapi saya ingin menunjukkan apa yang berhasil untuk saya.

Saya mencoba menggunakan kode sampel dari situs web Pengembang Android (ditunjukkan di bawah), tetapi tidak berhasil. Jadi saya memeriksa kelas EditorInfo, dan saya menyadari bahwa nilai integer IME_ACTION_SEND ditetapkan sebagai 0x00000004.

Kode contoh dari Pengembang Android:

editTextEmail = (EditText) findViewById(R.id.editTextEmail);
editTextEmail
        .setOnEditorActionListener(new OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId,
                    KeyEvent event) {
                boolean handled = false;
                if (actionId == EditorInfo.IME_ACTION_SEND) {
                    /* handle action here */
                    handled = true;
                }
                return handled;
            }
        });

Jadi, saya menambahkan nilai integer ke res/values/integers.xmlfile saya .

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="send">0x00000004</integer>
</resources>

Kemudian, saya mengedit file layout saya res/layouts/activity_home.xmlsebagai berikut

<EditText android:id="@+id/editTextEmail"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:imeActionId="@integer/send"
  android:imeActionLabel="@+string/send_label"
  android:imeOptions="actionSend"
  android:inputType="textEmailAddress"/>

Dan kemudian, kode sampel berfungsi.

iRuth
sumber
17

Lebih detail tentang cara mengatur OnKeyListener, dan minta dia mendengarkan tombol Done.

Pertama-tama tambahkan OnKeyListener ke bagian mengimplementasikan kelas Anda. Kemudian tambahkan fungsi yang didefinisikan dalam antarmuka OnKeyListener:

/*
 * Respond to soft keyboard events, look for the DONE press on the password field.
 */
public boolean onKey(View v, int keyCode, KeyEvent event)
{
    if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
        (keyCode == KeyEvent.KEYCODE_ENTER))
    {
        // Done pressed!  Do something here.
    }
    // Returning false allows other listeners to react to the press.
    return false;
}

Diberikan objek EditText:

EditText textField = (EditText)findViewById(R.id.MyEditText);
textField.setOnKeyListener(this);
Robert Hawkey
sumber
2
Ini tidak berfungsi lagi pada aplikasi yang menargetkan API level 17+, karena OnKeyListener Anda tidak lagi dipecat untuk acara soft-key: developer.android.com/reference/android/text/method/…
jjb
Apakah mereka menyarankan alternatif sekarang?
Robert Hawkey
2
Saya telah beralih menggunakan setOnEditorActionListener untuk mencari EditorInfo.IME_ACTION_DONE, yang sepertinya berfungsi dengan baik.
jjb
onKey harus mengembalikan true, bukan false.
ralphgabb
16

Sementara kebanyakan orang telah menjawab pertanyaan secara langsung, saya ingin menguraikan lebih lanjut tentang konsep di baliknya. Pertama, saya tertarik pada IME ketika saya membuat Aktivitas Login default. Ini menghasilkan beberapa kode untuk saya yang termasuk yang berikut:

<EditText
  android:id="@+id/password"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:hint="@string/prompt_password"
  android:imeActionId="@+id/login"
  android:imeActionLabel="@string/action_sign_in_short"
  android:imeOptions="actionUnspecified"
  android:inputType="textPassword"
  android:maxLines="1"
  android:singleLine="true"/>

Anda seharusnya sudah terbiasa dengan atribut inputType. Ini hanya memberi tahu Android jenis teks yang diharapkan seperti alamat email, kata sandi, atau nomor telepon. Daftar lengkap nilai yang mungkin dapat ditemukan di sini .

Namun, atribut imeOptions="actionUnspecified"itulah yang saya tidak mengerti tujuannya. Android memungkinkan Anda untuk berinteraksi dengan keyboard yang muncul dari bawah layar saat teks dipilih menggunakan InputMethodManager. Di sudut bawah keyboard, ada tombol, biasanya tertulis "Next" atau "Done", tergantung pada bidang teks saat ini. Android memungkinkan Anda untuk menyesuaikan ini menggunakan android:imeOptions. Anda dapat menentukan tombol "Kirim" atau tombol "Berikutnya". Daftar lengkapnya dapat ditemukan di sini .

Dengan itu, Anda dapat mendengarkan penekanan pada tombol tindakan dengan menentukan a TextView.OnEditorActionListeneruntuk EditTextelemen. Seperti dalam contoh Anda:

editText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(EditText v, int actionId, KeyEvent event) {
    if (actionId == EditorInfo.IME_ACTION_DONE) {
       //do here your stuff f
       return true;
    }
    return false;
    } 
});

Sekarang dalam contoh saya, saya memiliki android:imeOptions="actionUnspecified"atribut. Ini berguna ketika Anda ingin mencoba masuk pengguna ketika mereka menekan tombol enter. Di Aktivitas Anda, Anda dapat mendeteksi tag ini dan kemudian mencoba login:

    mPasswordView = (EditText) findViewById(R.id.password);
    mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
            if (id == R.id.login || id == EditorInfo.IME_NULL) {
                attemptLogin();
                return true;
            }
            return false;
        }
    });
Donato
sumber
6

Berkat chikka.anddev dan Alex Cohn di Kotlin itu adalah:

text.setOnEditorActionListener { v, actionId, event ->
    if (actionId == EditorInfo.IME_ACTION_DONE ||
        event?.action == KeyEvent.ACTION_DOWN && event.keyCode == KeyEvent.KEYCODE_ENTER) {
        doSomething()
        true
    } else {
        false
    }
}

Di sini saya memeriksa Enterkunci, karena itu mengembalikan EditorInfo.IME_NULLbukan IME_ACTION_DONE.

Lihat juga Android imeOptions = "actionDone" tidak berfungsi . Menambahkan android:singleLine="true"dalam EditText.

CoolMind
sumber
6

Solusi Kotlin

Cara dasar untuk menanganinya di Kotlin adalah:

edittext.setOnEditorActionListener { _, actionId, _ ->
    if (actionId == EditorInfo.IME_ACTION_DONE) {
        callback.invoke()
        true
    }
    false
}

Perpanjangan Kotlin

Gunakan ini untuk hanya memanggil edittext.onDone{/*action*/}kode utama Anda. Membuat kode Anda jauh lebih mudah dibaca dan dipelihara

fun EditText.onDone(callback: () -> Unit) {
    setOnEditorActionListener { _, actionId, _ ->
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            callback.invoke()
            true
        }
        false
    }
}

Jangan lupa untuk menambahkan opsi ini ke edittext Anda

<EditText ...
    android:imeOptions="actionDone"
    android:inputType="text"/>

Jika Anda memerlukan inputType="textMultiLine"dukungan, baca posting ini

Gibolt
sumber
1
Jawaban yang bagus, terima kasih sudah berbagi! Saya tampaknya terus mendapatkan peringatan serat tentang nilai pengembalian setOnEditorActionListener, meskipun. Mungkin itu hanya masalah pengaturan konfigurasi lokal, tetapi linter saya benar- benar ingin saya menambahkan elsecabang juga untuk menerima "true" sebagai pernyataan kembali dari pendengar (sebagai lawan dari if-block).
dbm
0

Jika Anda menggunakan Android Annotations https://github.com/androidannotations/androidannotations

Anda dapat menggunakan anotasi @EditorAction

@EditorAction(R.id.your_component_id)
void onDoneAction(EditText view, int actionId){
    if(actionId == EditorInfo.IME_ACTION_DONE){
        //Todo: Do your work or call a method
    }
}
Rafael Rocha
sumber