完了アクションボタン付きの複数行EditText


114

EditTextウィジェットをandroid:inputType="textMultiLine"セットでandroid:imeOptions="actionDone"同時に持つことは可能ですか?

キーボードのアクションボタンがEnter(キャリッジリターン)ではなくDoneになっている複数行の編集ボックスが欲しいのですが、機能していないようです。

前もって感謝します


複数行のEditTextとボタンを組み合わせた複合ウィジェットを試してみてはどうですか?
Subin Sebastian

回答:


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 2018

1
とてもうまくいきます...私はそれを見つけるのに苦労しました。この回答はベストアンサーとしてマークする必要があります
MFAL 2018

7
すべてをxmlで設定するのではなく、なぜこれが機能するのですか?
Andrew Steinmetz、2018

1
この情報を見つけるのに苦労しました。それはまだ魅力のように働いています!
Costin

51

androidのドキュメントから: ' "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);
}

理解するのにかなり時間がかかったので、これが誰かに役立つことを願っています。マニフェストから機能させる方法を見つけた場合は、お知らせください。


4
高さの変更を避けたい場合maxLines()setLines()、代わりに試すことをお勧めしますEditText
ダニエル・スミス

質問では、android:imeOptionsにactionSendなどの値を設定する必要があるかどうかは明確ではないと思います。この回答を完了すると、setMaxLinesがコードによって上書きする場合でも、android:singleLine = "true"を設定する必要がありました(そうしないと、「送信」などのEnterキーが提供されません)。<Enter>アクションをキャプチャするには、stackoverflow.com / questions / 5014219 /…からの最初の回答を確認してください。
DNax 14

申し訳ありませんが、<Enter>のキャプチャに関して見つけた最良の代替案は、@ earlcasperの回答です。ここで、stackoverflow.com
questions / 1489852 /…

1
これは私にとって完璧に機能しました(を使用setMaxLines(3))ありがとうございます!
laurencevs

1
チャームのように機能しました:android:imeOptions = "actionDone" android:inputType = "text"をXMLにも追加し、android:lines = "3" android:scrollHorizo​​ntally = "false"をXMLから
削除

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; connを返します。
yash

動作します。Andorid 6.0.1でテスト済み。
AmiguelS 2017

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
タモキシン

9

これがあなたのやり方です。持っているandroid:inputType="textMultiLine"android:imeOptions="actionDone"、Enterキーの機能が曖昧になります。を使用し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なのですか?
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
This️これは素晴らしい答えです
マイケル

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です。このソリューションは、複数行ビューのIME_FLAG_NO_ENTER_ACTIONフラグの設定を強制するAndroidの絶え間ない欲求を無効にし、[完了]ボタンを非表示にします。


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;)で置き換えることができます。

従来のEditTextクラスではなく、XMLで呼び出す必要があります。

ここでロジックを説明するには:

  • Enterの代わりにImeActionボタンを表示できるように、EditTextをsingleLineとして設定します。
  • 水平スクロールを削除して、ビューの最後に達したときにテキストを次の行に移動します。
  • onGlobalLayoutListenerでレイアウトの変更を監視し、その「line」パラメーターをeditTextが保持する現在のテキストの「lineCount」に設定します。これは、その高さを更新するものです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.