EditText หลายบรรทัดพร้อมปุ่มดำเนินการเสร็จสิ้น


114

เป็นไปได้ไหมที่จะมีEditTextวิดเจ็ตพร้อมandroid:inputType="textMultiLine"ชุดและandroid:imeOptions="actionDone"ในเวลาเดียวกัน

ฉันต้องการกล่องแก้ไขหลายบรรทัดโดยให้ปุ่มการทำงานบนแป้นพิมพ์เป็นเสร็จสิ้นไม่ใช่ Enter (Carriage Return) แต่ดูเหมือนจะใช้งานไม่ได้ ..

ขอบคุณล่วงหน้า


สิ่งที่เกี่ยวกับการลองใช้วิดเจ็ตผสมกับ EditText หลายบรรทัดและปุ่มรวมกัน?
Subin Sebastian

คำตอบ:


195

ใช้

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

และใน XML:

android:inputType="textMultiLine"

สำหรับฉันเคอร์เซอร์จะยังคงแสดงเมื่อแป้นพิมพ์ลงไปฉันต้องเพิ่มtextField.setCursorVisible(false);ภายในonEditorActionListener
Fonix

ทำงานบน 4.2.2 และ 7.1.1 ขอบคุณ
tehcpu

1
ทำงานได้ดีมาก ... ฉันพยายามหามัน คำตอบนี้ควรถูกระบุว่าเป็นคำตอบที่ดีที่สุด
MFAL

7
เหตุใดจึงใช้งานได้เมื่อเทียบกับการตั้งค่าทั้งหมดใน xml
Andrew Steinmetz

1
ดิ้นรนเล็กน้อยเพื่อค้นหาข้อมูลนี้ มันยังคงทำงานอย่างมีเสน่ห์!
Costin

51

จากเอกสารประกอบหุ่นยนต์: ' 'textMultiLine' แป้นพิมพ์ข้อความปกติที่ช่วยให้ผู้ใช้สามารถป้อนข้อมูลสายยาวของข้อความที่มีการแบ่งบรรทัด (ผลตอบแทนการขนส่ง) "ดังนั้นแอตทริบิวต์ textMultiLine จึงไม่เหมาะสมหากคุณต้องการให้มีปุ่ม" เสร็จสิ้น "ในแป้นพิมพ์

วิธีง่ายๆในการรับฟิลด์อินพุตแบบหลายบรรทัด (ในกรณีนี้คือ 3 บรรทัด) ด้วยปุ่มเสร็จสิ้นคือการใช้ EditText กับ

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

อย่างไรก็ตามด้วยเหตุผลบางประการสิ่งนี้ใช้ได้กับฉันเท่านั้นถ้าฉันทำการตั้งค่าเหล่านี้ในโค้ดแทนไฟล์เลย์เอาต์ (ใน onCreate) โดย

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

ฉันหวังว่านี่จะช่วยใครบางคนได้เนื่องจากต้องใช้เวลาพอสมควรในการคิดออก หากคุณพบวิธีทำให้ใช้งานได้จากไฟล์ Manifest โปรดแจ้งให้เราทราบ


4
ฉันขอแนะนำให้ลองmaxLines()แทนsetLines()หากคุณต้องการหลีกเลี่ยงการเปลี่ยนความสูงของEditText
Daniel Smith

ฉันคิดว่าในคำถามนี้ไม่ได้รับการชี้แจงว่าคุณควรตั้งค่า android: imeOptions ด้วยค่าเช่น actionSend ฉันต้องตั้งค่า android: singleLine = "true" ให้เสร็จแม้ว่า setMaxLines จะเขียนทับด้วยรหัสก็ตาม (การไม่ทำเช่นนั้นจะไม่ให้รหัส Enter แก่คุณเช่น "Send") ในการบันทึกการดำเนินการ <Enter> ให้ตรวจสอบคำตอบแรกจากstackoverflow.com/questions/5014219/… out
DNax

ขออภัยทางเลือกที่ดีที่สุดที่ฉันพบเกี่ยวกับการจับ <Enter> คือคำตอบของ @earlcasper ที่นี่stackoverflow.com/questions/1489852/…
DNax

1
สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน (โดยใช้setMaxLines(3)) ขอบคุณมาก!
laurencevs

1
ทำงานได้อย่างมีเสน่ห์เพียงแค่เพิ่ม android: imeOptions = "actionDone" android: inputType = "text" ลงใน XML ของคุณเช่นกันและลบ android: lines = "3" android: scrollHorizontally = "false" จาก XML
HannahCarney

24

ตัวอย่างการทำงาน! สร้างคลาส EditText แบบกำหนดเองด้านล่างที่รองรับฟีเจอร์นี้และใช้คลาสในไฟล์ xml รหัสการทำงาน:

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

สิ่งนี้ใช้ได้ผลสำหรับฉันความต้องการของฉันคือการแก้ไขข้อความซึ่งควรเป็นหลายบรรทัดและควรมีปุ่มถัดไปบนซอฟต์คีย์ ............... ขอบคุณมากที่ฉันทำ อยู่ในการแก้ไขข้อความฉันเพิ่ม 2 บรรทัด android: inputType = "textMultiLine" android: imeOptions = "actionNext" และในคลาสที่กำหนดเองด้านบนฉันทำ: InputConnection conn = super.onCreateInputConnection (outAttrs); //outAttrs.imeOptions & = ~ EditorInfo.IME_FLAG_NO_ENTER_ACTION; outAttrs.imeOptions & = EditorInfo.IME_ACTION_NEXT; กลับคอน;
yash

โรงงาน ทดสอบกับ Andorid 6.0.1
AmiguelS

9

ในการทำสิ่งนี้ใน Kotlin (และยังเลือกใช้การกำหนดค่าอื่น ๆ เช่นtextCapSentencesคุณสามารถใช้ฟังก์ชันส่วนขยายนี้:

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

การใช้งาน:

myEditText.setMultiLineCapSentencesAndDoneAction()

1
ใช้งานได้ถึงเดือนมิถุนายน 2562! ขอบคุณ :)
Rohan Taneja

กุญแจสำคัญสำหรับฉันคือใช้setRawInputTypeแทนsetInputType
Tamoxin

9

ฉันคิดว่านี่คือวิธีที่จะทำให้คุณทำสิ่งต่างๆ มีandroid:inputType="textMultiLine", android:imeOptions="actionDone"ทำให้ใส่ทำงานที่สำคัญที่ไม่ชัดเจน เพียงจำไว้ว่าคุณสามารถใช้android:lines="10"และอาจลบออกandroid:inputType="textMultiLine"แต่ขึ้นอยู่กับสิ่งที่คุณต้องการบรรลุในบางครั้งคุณเพียงแค่ต้องการandroid:inputType="textMultiLine"และไม่มีสิ่งใดทดแทนได้

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

การใช้จำนวนสูงสุดคงที่กับandroid: lines = "10"ได้ผลสำหรับฉันโดยได้รับปุ่ม ok บนแป้นพิมพ์ เคล็ดลับที่ดีหากรู้ว่าจะมีกี่บรรทัดเช่นมีชุด maxLength ขนาดเล็ก
sunadorer

ฉันต้องการปิดการใช้งาน keyCode # 66 เป็นไปได้หรือไม่? ฉันจะทำเช่นนั้นได้อย่างไร?
Adil Malik

1
ทำไม keyCode == 66 แทน keyCode == EditorInfo.IME_ACTION_GO
tse

5

ดูเหมือนว่าจะได้ผลสำหรับฉันอย่างสมบูรณ์แบบ

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

4

โซลูชัน Kotlin ที่ใช้ซ้ำได้

การตั้งค่าเหล่านี้ในโค้ดเป็นสิ่งเดียวที่ใช้ได้ผลสำหรับฉัน

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

ฉันต้องการสิ่งนี้บ่อยครั้งจึงทำให้รหัสนี้สะอาด:

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)

หากคุณต้องการเพิ่มการดำเนินการแบบกำหนดเองที่เป็นทางเลือกใน "เสร็จสิ้น" ให้ลองทำดังนี้:

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()

ต้องการควบคุมแป้นพิมพ์ในการโทรกลับอย่างง่ายดายหรือไม่? อ่านโพสต์นี้

จากนั้นเพิ่มการhideKeyboard()โทรเข้าEditText.multilineDone


1
☝️นี่คือคำตอบที่ดี
Michael

3

คำตอบสั้น ๆ : ไม่ฉันเชื่อว่าไม่สามารถทำได้ก่อน API ระดับ 11 (3.0)

ปัญหาเดียวกันเกิดขึ้นที่นี่ (กล่าวถึงในความคิดเห็นของคำตอบที่ยอมรับ):

ปุ่มการทำงานของแป้นพิมพ์ Android Soft

จากความคิดเห็นสุดท้าย:

เมื่อดูแอปบางแอปในโทรศัพท์ของฉันดูเหมือนว่ากล่องมัลติไลน์จะอยู่ในอันดับสุดท้ายโดยมีปุ่ม "เสร็จสิ้น" หรือ "ส่ง" ที่มองเห็นได้ด้านล่าง (เช่นแอปอีเมล)


3

วิธีง่ายๆในการแก้ไขสถานการณ์นี้:

  • เก็บแอตทริบิวต์นี้ไว้ใน EditText:

    android:inputType="textMultiLine" 
    android:scrollHorizontally="false"
  • จากนั้นเพิ่มรหัสนี้เพื่อซ่อนแป้นพิมพ์เมื่อกด ENTER เท่านั้น:

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

2

หากไม่ได้เกี่ยวกับรูปลักษณ์ของแป้นพิมพ์บนหน้าจอคุณสามารถใส่ตัวฟังอินพุตบนแป้นพิมพ์และเริ่มการทำงานของสถานะ "เสร็จสิ้น" หากผู้ใช้ป้อนขึ้นบรรทัดใหม่


2

ถ้าคุณใช้ตัวเลือกการป้อน textImeMultiline กับ imeoptions flagnext และ actionnext คุณจะได้รับปุ่มถัดไปแทนที่จะเป็น cariage return


2

แม้ว่าจะไม่มีวิธีแก้ปัญหาอื่นใดที่ใช้ได้ผลสำหรับฉัน แต่สิ่งต่อไปนี้ก็ทำงานได้อย่างสวยงามและช่วยฉันได้หลายวันและหลายวันในการ Googling มากขึ้นด้วยการบิดตัวของฉันเอง น่าเสียดายที่จำไม่ได้ว่าฉันได้รหัสมาจากที่ไหนและไม่สามารถให้เครดิตกับผู้เขียนที่เขา / เธอสมควรได้รับได้

ในโค้ด Java ของคุณ:

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

น่าจะมาจากgist.github.com/Dogesmith/2b98df97b4fca849ff94
Naz

น่าจะมาจากgist.github.com/Dogesmith/2b98df97b4fca849ff94
Naz

น่าจะมาจากgist.github.com/Dogesmith/2b98df97b4fca849ff94
Naz

1

ฉันใช้ 4.x และพยายามโทร setHorizontallyScrolling () (มีหรือไม่มี setLine () หรือ setMaxLines ()) รวมถึงการกำหนดค่า XML ต่างๆมากมายเพื่อให้ปุ่มเสร็จสิ้นเพื่อแสดง ไม่มีใครทำงาน บรรทัดล่างคือถ้า EditText ของคุณเป็นแบบหลายบรรทัด Android มักจะต้องการแสดงการกลับรถแทนปุ่ม "เสร็จสิ้น" เว้นแต่คุณจะทำการแฮ็กในส่วนนี้

วิธีการแก้ปัญหาภาวะแทรกซ้อนน้อยฉันพบว่าไม่เกี่ยวข้องกับการแมปพฤติกรรมของกลับสายการบินอยู่ที่นี่: https://stackoverflow.com/a/12570003/3268329 โซลูชันนี้จะลบล้างความปรารถนาอย่างไม่ลดละของ Android ที่จะบังคับให้ตั้งค่าสถานะ IME_FLAG_NO_ENTER_ACTION สำหรับมุมมองหลายบรรทัดซึ่งทำให้ปุ่มเสร็จสิ้นหายไป


0

ฉันต่อสู้มาพอสมควร แต่ในที่สุดฉันก็พบวิธีแก้ปัญหา!

เพียงสร้างคลาส EditText แบบกำหนดเองดังนี้:

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

คลาสนี้จะลบ lineBreaks (\ n) ตัดข้อความตามที่ textMultiline ทำได้และช่วยให้คุณสามารถแทนที่ปุ่ม Enter ด้วย ImeAction;)

คุณต้องเรียกมันใน XML ของคุณแทนคลาส EditText แบบคลาสสิก

เพื่ออธิบายตรรกะที่นี่:

  • ตั้งค่า EditText เป็นบรรทัดเดียวเพื่อให้สามารถแสดงปุ่ม ImeAction แทน Enter
  • ลบการเลื่อนแนวนอนเพื่อให้ข้อความไปที่บรรทัดถัดไปเมื่อถึงจุดสิ้นสุดของมุมมอง
  • ดูการเปลี่ยนแปลงเค้าโครงด้วย onGlobalLayoutListener และตั้งค่าพารามิเตอร์ "line" เป็น "lineCount" ของข้อความปัจจุบันที่แก้ไขโดย editText นี่คือสิ่งที่ช่วยฟื้นฟูความสูงของมัน

0

โซลูชันการทำงานอยู่ที่นี่สร้าง EditTextView แบบกำหนดเองของคุณ (เพียงแค่ขยาย textview) และแทนที่ onInputConnection ด้วยโค้ดส่วนหนึ่งที่คุณจะพบในคำตอบที่ยอมรับที่นี่: Multiline EditText พร้อม Done SoftInput Action Label บน 2.3

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