ฉันจะจัดการการคลิกปุ่มที่เสร็จสิ้นของ ImeOptions ได้อย่างไร


185

ฉันมีEditTextที่ที่ฉันตั้งค่าคุณสมบัติต่อไปนี้เพื่อให้ฉันสามารถแสดงปุ่มที่เสร็จสิ้นบนแป้นพิมพ์เมื่อผู้ใช้คลิกที่ EditText

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

เมื่อผู้ใช้คลิกปุ่มเสร็จบนแป้นพิมพ์หน้าจอ (พิมพ์เสร็จ) ฉันต้องการเปลี่ยนRadioButtonสถานะ

ฉันจะติดตามปุ่มที่เสร็จสิ้นได้อย่างไรเมื่อมันมาจากแป้นพิมพ์หน้าจอ

สกรีนช็อตแสดงปุ่ม 'เสร็จสิ้น' ที่ด้านล่างขวาบนแป้นพิมพ์ซอฟต์แวร์


1
อาจเป็น OnKeyboardActionListener ช่วยฉันตัวอย่างรหัสใด ๆ ??
d-man

คำตอบ:


210

ฉันลงเอยด้วยการผสมผสานของ Roberts และคำตอบ 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;
    }
});

อัปเดต: บางครั้งรหัสข้างต้นอาจเปิดใช้งานการโทรกลับสองครั้ง แต่ฉันได้เลือกใช้รหัสต่อไปนี้ซึ่งฉันได้รับจากลูกค้าแชทของ 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;
}

4
ฉันแค่มองหา IME_ACTION_DONE และฉันรู้สึกประหลาดใจที่ไม่ได้กระตุ้น หลังจากที่ฉันค้นหา ACTION_DOWN และ KEYCODE_ENTER ในที่สุดมันก็เริ่มทำงานกับ EditorAction () เนื่องจากฉันไม่เห็นความแตกต่างในแป้นพิมพ์ในตัว (ฉันคาดว่าจะมีการเน้นปุ่ม Enter) ฉันสงสัยว่าจุดประสงค์ของการใช้ android: imeOptions = "actionSend" สำหรับเค้าโครง XML ของ EditText
คนอยู่ที่ไหนสักแห่งที่

ทำไมคำตอบนี้ไม่ได้รับการยอมรับ สิ่งนี้จะล้มเหลวในบางกรณีหรือไม่?
Archie.bpgc

1
developer.android.com/reference/android/widget/… (คำอธิบายว่า 'กิจกรรม' เป็นอะไรที่เหมือนกัน)
Darpan

2
โซลูชันที่สองจะถูกเรียกใช้สองครั้ง
Bagusflyer

1
คืออะไรisPreparedForSending()และทำไมวิธีการผลตอบแทนที่สองtrue?
CoolMind

122

ลองสิ่งนี้มันควรจะทำงานในสิ่งที่คุณต้องการ:


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

10
สิ่งนี้ใช้ไม่ได้กับ HTC Evo เท่าที่ฉันเข้าใจได้ HTC ใช้คีย์บอร์ดนุ่มของตัวเองซึ่งไม่สนใจ imeOptions
Dan

พอเพียงนี้ (ไม่จำเป็นต้องดูการกระทำของเหตุการณ์หรือรหัสคีย์ตามคำตอบที่ยอมรับ); ใช้งานได้กับอุปกรณ์ทดสอบ Nexus และ Samsung ของฉัน
Jonik

เพียงเพื่อความปลอดภัยตรวจสอบให้แน่ใจว่าการกระทำในรหัสและมุมมองที่ตรงกัน <EditText android:imeOptions="actionDone" android:inputType="text"/>
bh_earth0

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

รหัส Java คือ:

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

คุณควรกลับมาจริงในประโยคถ้าจะบอกว่าคุณได้จัดการมัน
Tim Kist

26

ฉันรู้ว่าคำถามนี้เก่า แต่ฉันต้องการที่จะชี้ให้เห็นสิ่งที่ได้ผลสำหรับฉัน

ฉันลองใช้โค้ดตัวอย่างจากเว็บไซต์นักพัฒนา Android (แสดงด้านล่าง) แต่มันไม่ทำงาน ดังนั้นฉันจะตรวจสอบระดับ EditorInfo และฉันรู้ว่าคุ้มค่า IME_ACTION_SEND 0x00000004จำนวนเต็มถูกระบุว่าเป็น

โค้ดตัวอย่างจากนักพัฒนา 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;
            }
        });

ดังนั้นฉันจึงเพิ่มค่าจำนวนเต็มในres/values/integers.xmlไฟล์ของฉัน

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

จากนั้นฉันแก้ไขไฟล์เลย์เอาต์ของฉันres/layouts/activity_home.xmlดังนี้

<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"/>

จากนั้นโค้ดตัวอย่างทำงาน


17

รายละเอียดเพิ่มเติมเกี่ยวกับวิธีการตั้งค่า OnKeyListener และให้ฟังปุ่มเสร็จ

ก่อนอื่นให้เพิ่ม OnKeyListener ในส่วนการดำเนินการในชั้นเรียนของคุณ จากนั้นเพิ่มฟังก์ชันที่กำหนดไว้ในอินเทอร์เฟซ 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;
}

รับวัตถุ EditText:

EditText textField = (EditText)findViewById(R.id.MyEditText);
textField.setOnKeyListener(this);

2
สิ่งนี้ไม่สามารถใช้งานได้กับแอปพลิเคชันที่กำหนดเป้าหมายระดับ API 17+ เนื่องจาก OnKeyListener ของคุณไม่ได้ถูกเรียกใช้สำหรับเหตุการณ์ซอฟต์คีย์: developer.android.com/reference/android/text/method/
......

พวกเขาแนะนำทางเลือกตอนนี้หรือไม่?
Robert Hawkey เมื่อ

2
ฉันเปลี่ยนไปใช้ setOnEditorActionListener เพื่อค้นหา EditorInfo.IME_ACTION_DONE ซึ่งดูเหมือนว่าจะทำงานได้ดี
jjb

onKey ควรกลับมาจริงไม่ใช่เท็จ
ralphgabb

16

ในขณะที่คนส่วนใหญ่ตอบคำถามโดยตรงฉันต้องการอธิบายเพิ่มเติมเกี่ยวกับแนวคิดเบื้องหลัง ก่อนอื่นฉันรู้สึกเป็นที่สนใจของ IME เมื่อฉันสร้างกิจกรรมการเข้าสู่ระบบเริ่มต้น มันสร้างรหัสสำหรับฉันซึ่งรวมถึงต่อไปนี้:

<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"/>

คุณควรคุ้นเคยกับแอตทริบิวต์ inputType แล้ว นี่เป็นการแจ้งประเภทข้อความที่คาดหวังเช่น Android เช่นที่อยู่อีเมลรหัสผ่านหรือหมายเลขโทรศัพท์ รายการทั้งหมดของค่าที่เป็นไปได้อยู่ที่นี่ที่นี่

อย่างไรก็ตามมันเป็นคุณลักษณะimeOptions="actionUnspecified"ที่ฉันไม่เข้าใจวัตถุประสงค์ของมัน Android InputMethodManagerช่วยให้คุณสามารถโต้ตอบกับแป้นพิมพ์ที่ปรากฏขึ้นจากด้านล่างของหน้าจอเมื่อข้อความถูกเลือกใช้ ที่มุมด้านล่างของแป้นพิมพ์จะมีปุ่มโดยทั่วไปจะมีคำว่า "ถัดไป" หรือ "เสร็จสิ้น" ขึ้นอยู่กับช่องข้อความปัจจุบัน Android android:imeOptionsช่วยให้คุณสามารถปรับแต่งโดยใช้ คุณสามารถระบุปุ่ม "ส่ง" หรือปุ่ม "ถัดไป" รายการเต็มสามารถพบได้ที่นี่ที่นี่

เมื่อถึงตอนนั้นคุณสามารถฟังการกดบนปุ่มการกระทำได้โดยการกำหนดTextView.OnEditorActionListenerสำหรับEditTextองค์ประกอบ ดังตัวอย่างของคุณ:

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

ตอนนี้ในตัวอย่างของฉันฉันมีandroid:imeOptions="actionUnspecified"คุณลักษณะ สิ่งนี้มีประโยชน์เมื่อคุณต้องการเข้าสู่ระบบผู้ใช้เมื่อพวกเขากดปุ่ม Enter ในกิจกรรมของคุณคุณสามารถตรวจหาแท็กนี้แล้วลองลงชื่อเข้าใช้:

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

6

ขอบคุณchikka.anddevและAlex Cohnใน Kotlin คือ:

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

นี่ฉันตรวจสอบEnterที่สำคัญเพราะมันจะกลับแทนEditorInfo.IME_NULLIME_ACTION_DONE

ดูเพิ่มเติมAndroid imeOptions = "actionDone" ไม่ทำงาน เพิ่มในandroid:singleLine="true"EditText


6

โซลูชั่น Kotlin

วิธีการพื้นฐานในการจัดการใน Kotlin คือ:

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

Kotlin Extension

ใช้สิ่งนี้เพื่อโทรedittext.onDone{/*action*/}ในรหัสหลักของคุณ ทำให้โค้ดของคุณอ่านและดูแลได้ง่ายขึ้น

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

อย่าลืมเพิ่มตัวเลือกเหล่านี้ใน edittext ของคุณ

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

หากคุณต้องการinputType="textMultiLine"การสนับสนุนอ่านโพสต์นี้


1
คำตอบที่ดีขอบคุณสำหรับการแบ่งปัน! ฉันดูเหมือนจะให้ได้รับการแจ้งเตือนผ้าสำลีเกี่ยวกับค่าตอบแทนของsetOnEditorActionListenerแต่ บางทีมันอาจจะเป็นเพียงเรื่องของการตั้งค่าท้องถิ่น แต่ linter ของฉันจริงๆจริงๆอยากให้ผมเพิ่มelseสาขามากเกินไปในการสั่งซื้อที่จะยอมรับ "ความจริง" เป็นคำสั่งกลับของผู้ฟัง (เมื่อเทียบกับif-block)
dbm

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.