developer tip

완료 작업 버튼이있는 여러 줄 EditText

optionbox 2020. 8. 26. 07:48
반응형

완료 작업 버튼이있는 여러 줄 EditText


세트와 동시에 EditText위젯 을 가질 수 있습니까?android:inputType="textMultiLine"android:imeOptions="actionDone"

키보드의 작업 단추가 Enter (캐리지 리턴)가 아닌 완료로 된 여러 줄 편집 상자를 원하지만 작동하지 않는 것 같습니다 ..

미리 감사드립니다


사용하다

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

그리고 XML :

android:inputType="textMultiLine"

안드로이드 문서에서 : ' "textMultiLine"사용자가 줄 바꿈 (캐리지 리턴) 을 포함하는 긴 텍스트 문자열을 입력 할 수있는 일반 텍스트 키보드 . '따라서 키보드에서'완료 '버튼을 사용하려는 경우 textMultiLine 속성이 적합하지 않습니다.

done 버튼으로 여러 줄 (이 경우 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);
}

알아내는 데 꽤 오랜 시간이 걸렸기 때문에 이것이 누군가에게 도움이되기를 바랍니다. 매니페스트에서 작동하는 방법을 찾으면 알려주십시오.


작업 예! 이 기능을 지원하는 아래 사용자 정의 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" />

나는 이것이 당신의 일을하는 방법이라고 생각합니다. 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;
        }
});

이것은 나를 위해 완벽하게 작동하는 것 같습니다.

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

To do this in Kotlin (and also optionally apply other configurations like textCapSentences you can use this extension function:

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

Usage:

myEditText.setMultiLineCapSentencesAndDoneAction()

Short answer: No, I believe it's not possible prior to API level 11 (3.0).

The same issue cropped up here (discussed in the comments to the accepted answer):

Android Soft keyboard action button

From the final comment:

Looking at a few apps on my phone, it seems common to have the multiline box last, with a visible "Done" or "Send" button below it (e.g. Email app).


A simple way to work around this situation:

  • keep this attributes on the EditText:

    android:inputType="textMultiLine" 
    android:scrollHorizontally="false"
    
  • then add this code to only hide the keyboard when ENTER is pressed:

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

If it is not about the look of the on-screen keyboard, you could simply put a input listener on the keyboard and fire the "done"-status if the user inputs a newline.


if you use the input option textImeMultiline with imeoptions flagnext and actionnext you get a next button instead of the cariage return


I'm on 4.x and tried calling setHorizontallyScrolling() (with or without setLine() or setMaxLines()), as well as many different XML configurations to get the Done button to show. None of them worked. The bottom line is that if your EditText is multi-line, Android will always want to show the carriage return instead of the "Done" button, unless you put in some hack around this.

The least complication solution I found that doesn't involve remapping the behavior of the carriage return is here: https://stackoverflow.com/a/12570003/3268329. This solution will nullify Android relentless desire to force setting of the IME_FLAG_NO_ENTER_ACTION flag for multi-line views, which causes the Done button to disappear.


While none of the other solutions ever worked for me, the following worked beautifully and saved me days and days of more googling, with a few twists of my own of course. Unfortunately don't remember where I got the code from exactly and so cannot give the author the credit he/she so deserves.

In your Java code :

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

I struggled as well for quite some time, but i finally found a solution!

Just create a custom EditText class as such :

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

This class removes lineBreaks (\n), wraps the text as textMultiline would do, AND allows you to replace the Enter button by a ImeAction ;).

You just need to call it in your XML instead of the classic EditText class.

To explain the logic here :

  • Set the EditText as a singleLine to be able to show a ImeAction button instead of Enter.
  • Remove the horizontal scrolling to make the text go to the next line when reaching the end of the view.
  • Watch the layout changes with the onGlobalLayoutListener, and set it's "line" parameter to the "lineCount" of the current text held by the editText. This is what refreshes its height.

Working solution is here, create your custom EditTextView (just extend a textview) and override onInputConnection wit a piece of code youll find in accepted answer here: Multiline EditText with Done SoftInput Action Label on 2.3

참고URL : https://stackoverflow.com/questions/2986387/multi-line-edittext-with-done-action-button

반응형