具有完成操作按钮的多行EditText


114

是否可以EditText同时android:inputType="textMultiLine"设置一个小部件android:imeOptions="actionDone"

我想要一个多行编辑框,将键盘上的操作按钮设置为“完成”,而不是Enter(回车),但是它似乎不起作用。

提前致谢


尝试将多行EditText和Button组合在一起的复合窗口小部件怎么办?
Subin Sebastian

Answers:


194

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而不起作用?
安德鲁·斯坦梅茨

1
苦苦挣扎找到此信息。它仍然像魅力一样运作!
Costin

51

来自android文档:' “ textMultiLine”普通文本键盘,允许用户输入长文本字符串,包括换行符(回车)'因此,如果您想在键盘上使用“完成”按钮,则textMultiLine属性不合适。

使用完成按钮获取多行(在本例中为3行)输入字段的简单方法是将EditText与

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

但是,由于某种原因,这仅对我有效,如果我在代码中而不是在onCreate中通过布局文件(在onCreate中)进行了这些设置

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

我希望这可以帮助某人,因为花了很长时间才弄清楚。如果您发现从清单中使之工作的方法,请告诉我们。


4
我也建议尝试maxLines(),而不是setLines()如果你想避免改变的高度EditText
丹尼尔·史密斯

我认为在这个问题中,没有澄清您应该使用诸如actionSend之类的值来设置android:imeOptions。完成此答案后,我不得不设置android:singleLine =“ true”,即使setMaxLines会被代码覆盖(不这样做也不会给您输入Enter键,例如“ Send”)。要捕获<Enter>操作,请从stackoverflow.com/questions/5014219/…中检查第一个答案。
DNax 2014年

对不起,最好的选择,我发现有关捕获<回车>是@earlcasper答案在这里stackoverflow.com/questions/1489852/...
DNAX

1
非常适合我使用(使用了setMaxLines(3)),非常感谢!
laurencevs

1
就像魅力一样:只需将android:imeOptions =“ actionDone” android:inputType =“ text”添加到您的XML中,然后从XML中删除android:lines =“ 3” android:scrollHorizo​​ntally =“ false”
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&=编辑器信息.IME_ACTION_NEXT; 返回conn;
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
自2019年6月起可用!谢谢:)
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”上使用固定数量的最大数字对我有用,在键盘上获得了确定按钮。如果有人知道会有多少行,例如设置一小段maxLength,那将是一个很好的技巧。
sunadorer

我想禁用keyCode#66吗?我怎样才能做到这一点?
阿迪尔·马利克

1
为什么用keyCode == 66而不是keyCode == EditorInfo.IME_ACTION_GO?
tse 2015年

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软键盘操作按钮

从最后的评论:

查看我手机上的一些应用程序,最后一个多行框似乎很常见,在其下方有一个可见的“完成”或“发送”按钮(例如,电子邮件应用程序)。


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一起使用,则会得到一个下一个按钮,而不是回车


2

尽管没有其他解决方案对我有用,但以下解决方案有效精美,救了我天或以上的谷歌搜索的天,我自己当然的一些曲折。不幸的是,我不记得我从哪里确切地获得了代码,因此不能给予作者应有的荣誉。

在您的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;
        }
});




1

我在4.x上,尝试调用setHorizo​​ntallyScrolling()(带有或不带有setLine()或setMaxLines())以及许多不同的XML配置,以显示“完成”按钮。他们都没有工作。底线是,如果您的EditText是多行,Android将始终希望显示回车而不是“ Done”按钮,除非对此进行了一些修改。

我发现的最不复杂的解决方案不涉及重新映射回车的行为,请参见: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那样包装文本,并允许您用ImeAction;)替换Enter按钮。

您只需要在XML中而不是经典的EditText类中调用它即可。

在这里解释逻辑:

  • 将EditText设置为singleLine,以便能够显示ImeAction按钮而不是Enter。
  • 删除水平滚动以使文本在到达视图末尾时转到下一行。
  • 使用onGlobalLayoutListener观看布局更改,并将其“ line”参数设置为editText所保存的当前文本的“ lineCount”。这就是刷新其高度的原因。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.