source

텍스트 편집 외부를 클릭한 후 안드로이드에서 소프트 키보드를 숨기는 방법은 무엇입니까?

manysource 2023. 6. 4. 10:36

텍스트 편집 외부를 클릭한 후 안드로이드에서 소프트 키보드를 숨기는 방법은 무엇입니까?

좋습니다. 구현해야 하는 키보드를 숨기려면 다음과 같은 작업을 수행해야 한다는 것을 모두가 알고 있습니다.

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);

하지만 여기서 중요한 것은 사용자가 다른 장소를 터치하거나 선택할 때 키보드를 숨기는 방법입니다.EditText아니면 소프트 키보드?

나는 그것을 사용하려고 했습니다.onTouchEvent()Activity그러나 사용자가 다른 보기 외부를 터치하고 스크롤 보기가 없는 경우에만 작동합니다.

터치, 클릭, 포커스 리스너를 구현하려고 했지만 성공하지 못했습니다.

터치 이벤트를 차단하기 위해 자체 스크롤 뷰를 구현하려고도 했지만 이벤트 좌표만 확인할 수 있고 보기를 클릭할 수 없습니다.

이것을 하는 표준적인 방법이 있습니까?아이폰에서는 정말 쉬웠습니다.

다음 스니펫은 단순히 키보드를 숨깁니다.

public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = 
        (InputMethodManager) activity.getSystemService(
            Activity.INPUT_METHOD_SERVICE);
    if(inputMethodManager.isAcceptingText()){
        inputMethodManager.hideSoftInputFromWindow(
                activity.getCurrentFocus().getWindowToken(),
                0
        );
    }
}

유틸리티 클래스에 게시하거나 활동 내에서 정의하는 경우 활동 매개 변수를 피하거나 호출할 수 있습니다.hideSoftKeyboard(this).

가장 까다로운 부분은 언제 부를지입니다.다음과 같이 반복되는 방법을 작성할 수 있습니다.View당신의 활동에서, 그리고 그것이 그것인지 확인합니다.instanceof EditText등록하지 않은 경우setOnTouchListener모든 것이 제자리에 있을 것입니다.어떻게 하는지 궁금하실 경우를 대비해서, 사실 꽤 간단합니다.다음과 같은 재귀적인 방법을 작성합니다. 실제로 사용자 지정 서체 설정 등 모든 작업에 사용할 수 있습니다.이 있습니다.

public void setupUI(View view) {

    // Set up touch listener for non-text box views to hide keyboard.
    if (!(view instanceof EditText)) {
        view.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(MyActivity.this);
                return false;
            }
        });
    }

    //If a layout container, iterate over children and seed recursion.
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            View innerView = ((ViewGroup) view).getChildAt(i);
            setupUI(innerView);
        }
    }
}

그게 전부입니다, 당신이 이 방법을 부른 후에.setContentView당신의 활동에서. 변수를는 어떤매변전궁지금경우할할그은것, 달개수를▁in▁the은입니다.id상위 컨테이너의.id.

<RelativeLayoutPanel android:id="@+id/parent"> ... </RelativeLayout>

와를 요.setupUI(findViewById(R.id.parent)) 다야 , 게다야그다야.

당신이 효과적으로 , 당신은 ▁an▁extended▁create다▁if▁you▁may니있습▁effect▁this이수▁you만,ively▁to▁want▁use를 만들 수 있습니다.Activity그리고 이 방법을 넣고, 당신의 애플리케이션의 다른 모든 활동들이 이 활동을 확장하고 그것을 부르도록 합니다.setupUI()에 시대에onCreate()방법.

개 을 사용할 합니다. 예를 들어, " " 이 의 활 를 " 정 " 둘 " 상 " 공 " 에 " 의 " 합 " 니 " 웃 " 다 " 아 " 이 " 레 " 부 " 모 " 을 " 동 " 통 " 같 " 사 " 하 " 용 " 는 " 이 " 과 " 음 " 우 " 경 "<RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>

그런다클확장를에서 하세요.Activity 정의합니다.setupUI(findViewById(R.id.main_parent))의 그안 에.OnResume() "" "Activity"를을 확장합니다. in your program


위 함수의 코틀린 버전은 다음과 같습니다.

@file:JvmName("KeyboardUtils")

fun Activity.hideSoftKeyboard() {
    currentFocus?.let {
        val inputMethodManager = ContextCompat.getSystemService(this, InputMethodManager::class.java)!!
        inputMethodManager.hideSoftInputFromWindow(it.windowToken, 0)
    }
}

이 작업은 다음 단계를 수행하여 수행할 수 있습니다.

  1. 다음 속성을 추가하여 상위 보기(활동의 내용 보기)를 클릭 가능하고 초점을 맞출 수 있도록 합니다.

        android:clickable="true" 
        android:focusableInTouchMode="true" 
    
  2. hideKeyboard() 메서드 구현

        public void hideKeyboard(View view) {
            InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    
  3. 마지막으로 편집 텍스트의 onFocusChangeListener를 설정합니다.

        edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!hasFocus) {
                    hideKeyboard(v);
                }
            }
        });
    

아래 설명 중 하나에서 지적한 것처럼 상위 보기가 ScrollView인 경우 이 기능이 작동하지 않을 수 있습니다.이러한 경우 클릭 가능 및 포커스 가능 In터치 모드는 Scroll View(스크롤 보기) 바로 아래에 있는 보기에 추가할 수 있습니다.

활동에서 아래 코드를 무시하기만 하면 됩니다.

 @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (getCurrentFocus() != null) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
    }
    return super.dispatchTouchEvent(ev);
}

업데이트:

누군가 이 답변의 코틀린 버전이 필요한 경우:

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    if (currentFocus != null) {
        val imm = activity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(activity!!.currentFocus!!.windowToken, 0)
    }
    return super.dispatchTouchEvent(ev)
}

저는 받아들여진 답변이 좀 복잡하다고 생각합니다.

제 해결책은 이렇습니다.를 합니다.OnTouchListener기본 레이아웃으로, 즉:

findViewById(R.id.mainLayout).setOnTouchListener(this)

온터치 방식으로 다음 코드를 입력합니다.

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);

이렇게 하면 모든 보기를 반복할 필요가 없습니다.

키보드를 숨길 수 있는 솔루션이 하나 더 있습니다.

InputMethodManager imm = (InputMethodManager) getSystemService(
    Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

기여패스패스.HIDE_IMPLICIT_ONLY에의 에.showFlag그리고.0에의 에.hiddenFlag소프트 키보드가 강제로 닫힙니다.

Text Input Edit을 이용한 Kotlin & Material Design 기법 개발텍스트(이 접근 방식은 EditTextView와도 호환됨)...

1. 다음 속성을 추가하여 부모 보기(활동/분절의 내용 보기)를 클릭 가능하고 초점을 맞출 수 있도록 합니다.

android:focusable="true"
android:focusableInTouchMode="true"
android:clickable="true"

2.모든 보기에 대한 확장자 만들기(보기 내부)extension.kt 파일(예: ):

fun View.hideKeyboard(){
    val inputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    inputMethodManager.hideSoftInputFromWindow(this.windowToken, 0)
}

3.기본 텍스트 입력 편집 만들기TextInputEditText를 상속하는 텍스트입니다.보기에 초점이 맞지 않을 때 키보드를 숨기도록 FocusChanged에 메소드를 구현합니다.

class BaseTextInputEditText(context: Context?, attrs: AttributeSet?) : TextInputEditText(context, attrs){
    override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect)
        if (!focused) this.hideKeyboard()
    }
}

4. XML에서 새로운 사용자 정의 보기를 호출하기만 하면 됩니다.

<android.support.design.widget.TextInputLayout
        android:id="@+id/textInputLayout"
        ...>

        <com.your_package.BaseTextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            ... />

    </android.support.design.widget.TextInputLayout> 

이상입니다.반복적인 사례를 처리하기 위해 컨트롤러(조각 또는 활동)를 수정할 필요가 없습니다.

문제를 어느 정도 해결할 수 있었습니다. 활동에서 dispatchTouchEvent를 오버로드했습니다. 키보드를 숨기기 위해 다음을 사용하고 있습니다.

 /**
 * Called to process touch screen events. 
 */
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {

    switch (ev.getAction()){
        case MotionEvent.ACTION_DOWN:
            touchDownTime = SystemClock.elapsedRealtime();
            break;

        case MotionEvent.ACTION_UP:
            //to avoid drag events
            if (SystemClock.elapsedRealtime() - touchDownTime <= 150){  

                EditText[] textFields = this.getFields();
                if(textFields != null && textFields.length > 0){

                    boolean clickIsOutsideEditTexts = true;

                    for(EditText field : textFields){
                        if(isPointInsideView(ev.getRawX(), ev.getRawY(), field)){
                            clickIsOutsideEditTexts = false;
                            break;
                        }
                    }

                    if(clickIsOutsideEditTexts){
                        this.hideSoftKeyboard();
                    }               
                } else {
                    this.hideSoftKeyboard();
                }
            }
            break;
    }

    return super.dispatchTouchEvent(ev);
}

편집: getFields() 메서드는 보기에 텍스트 필드가 있는 배열을 반환하는 메서드입니다.터치할 때마다 이 배열을 만들지 않기 위해 getFields() 메서드에서 반환되는 sFields라는 정적 배열을 만들었습니다.이 배열은 다음과 같은 onStart() 메서드에서 초기화됩니다.

sFields = new EditText[] {mUserField, mPasswordField};


완벽하지 않습니다. 드래그 이벤트 시간은 휴리스틱만을 기반으로 하기 때문에 때때로 긴 클릭을 수행할 때 숨기지 않습니다. 또한 보기당 모든 편집 텍스트를 가져오는 방법을 만드는 것으로 마쳤습니다. 그렇지 않으면 키보드가 숨어서 다른 편집 텍스트를 클릭할 때 표시됩니다.

그래도 더 깨끗하고 짧은 솔루션을 환영합니다.

OnFocus Change Listener를 사용합니다.

예:

editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (!hasFocus) {
            hideKeyboard();
        }
    }
});

업데이트: 재정의할 수도 있습니다.onTouchEvent()터치 좌표를 확인합니다.좌표가 텍스트 편집 외부에 있으면 키보드를 숨깁니다.

모든 활동(또는 활동 클래스 확장)에서 공용 부울 dispatchTouchEvent(MotionEvent 이벤트)를 재정의합니다.

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    View view = getCurrentFocus();
    boolean ret = super.dispatchTouchEvent(event);

    if (view instanceof EditText) {
        View w = getCurrentFocus();
        int scrcoords[] = new int[2];
        w.getLocationOnScreen(scrcoords);
        float x = event.getRawX() + w.getLeft() - scrcoords[0];
        float y = event.getRawY() + w.getTop() - scrcoords[1];
        
        if (event.getAction() == MotionEvent.ACTION_UP 
 && (x < w.getLeft() || x >= w.getRight() 
 || y < w.getTop() || y > w.getBottom()) ) { 
            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
        }
    }
 return ret;
}

코틀린 버전:

 override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        val ret = super.dispatchTouchEvent(ev)
        ev?.let { event ->
            if (event.action == MotionEvent.ACTION_UP) {
                currentFocus?.let { view ->
                    if (view is EditText) {
                        val touchCoordinates = IntArray(2)
                        view.getLocationOnScreen(touchCoordinates)
                        val x: Float = event.rawX + view.getLeft() - touchCoordinates[0]
                        val y: Float = event.rawY + view.getTop() - touchCoordinates[1]
                        //If the touch position is outside the EditText then we hide the keyboard
                        if (x < view.getLeft() || x >= view.getRight() || y < view.getTop() || y > view.getBottom()) {
                            val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                            imm.hideSoftInputFromWindow(view.windowToken, 0)
                            view.clearFocus()
                        }
                    }
                }
            }
        }
        return ret
    }

그리고 당신이 해야 할 일은 그것뿐입니다.

다음을 수행하기 위해 활동에 dispatchTouchEvent를 구현했습니다.

private EditText mEditText;
private Rect mRect = new Rect();
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    final int action = MotionEventCompat.getActionMasked(ev);

    int[] location = new int[2];
    mEditText.getLocationOnScreen(location);
    mRect.left = location[0];
    mRect.top = location[1];
    mRect.right = location[0] + mEditText.getWidth();
    mRect.bottom = location[1] + mEditText.getHeight();

    int x = (int) ev.getX();
    int y = (int) ev.getY();

    if (action == MotionEvent.ACTION_DOWN && !mRect.contains(x, y)) {
        InputMethodManager input = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        input.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
    }
    return super.dispatchTouchEvent(ev);
}

제가 테스트를 해봤는데 완벽하게 작동합니다!

Andre Luis IM의 솔루션을 수정했습니다. 이를 달성했습니다.

Andre Luiz IM이 했던 것과 같은 방식으로 소프트 키보드를 숨기기 위한 유틸리티 메소드를 만들었습니다.

public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

그러나 성능이 떨어지는 모든 보기에 대해 OnTouch Listener를 등록하는 대신 루트 보기에만 OnTouch Listener를 등록했습니다.이벤트가 사용될 때까지 거품이 발생하므로(EditText는 기본적으로 이벤트를 사용하는 보기 중 하나임) 루트 보기에 도착하면 이벤트가 사용되지 않았기 때문에 소프트 키보드를 닫습니다.

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});

저는 이 스레드가 꽤 오래되었고 정답이 유효한 것으로 보이며 많은 작업 솔루션이 존재한다는 것을 알고 있습니다. 하지만 아래에 명시된 접근 방식은 효율성과 우아함과 관련하여 추가적인 이점이 있을 수 있다고 생각합니다.

모든 활동에 이 동작이 필요하기 때문에 클래스 활동에서 상속되는 클래스 사용자 지정 활동을 만들고 dispatchTouchEvent 기능을 "후킹"했습니다.크게 두 가지 조건을 충족해야 합니다.

  1. 포커스가 변경되지 않고 다른 사용자가 현재 입력 필드 외부를 누르고 있으면 IME를 해제합니다.
  2. 포커스가 변경되었고 다음 포커스 요소가 입력 필드의 인스턴스가 아닌 경우 IME를 해제합니다.

제 결과는 다음과 같습니다.

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if(ev.getAction() == MotionEvent.ACTION_UP) {
        final View view = getCurrentFocus();

        if(view != null) {
            final boolean consumed = super.dispatchTouchEvent(ev);

            final View viewTmp = getCurrentFocus();
            final View viewNew = viewTmp != null ? viewTmp : view;

            if(viewNew.equals(view)) {
                final Rect rect = new Rect();
                final int[] coordinates = new int[2];

                view.getLocationOnScreen(coordinates);

                rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight());

                final int x = (int) ev.getX();
                final int y = (int) ev.getY();

                if(rect.contains(x, y)) {
                    return consumed;
                }
            }
            else if(viewNew instanceof EditText || viewNew instanceof CustomEditText) {
                return consumed;
            }

            final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

            inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0);

            viewNew.clearFocus();

            return consumed;
        }
    }       

    return super.dispatchTouchEvent(ev);
}

참고 사항:또한 루트 보기에 이러한 속성을 할당하여 모든 입력 필드에 초점을 맞출 수 있도록 하고, 입력 필드가 활동 시작에 초점을 맞추는 것을 방지합니다(내용을 "포커스 캐처"로 표시).

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final View view = findViewById(R.id.content);

    view.setFocusable(true);
    view.setFocusableInTouchMode(true);
}

모든 보기를 반복하거나 dispatchTouchEvent를 재정의하는 대신

활동의 onUserInteraction()을(를) 재정의하지 않는 이유는 사용자가 EditText 밖을 탭할 때마다 키보드가 해제됩니다.

편집 텍스트가 스크롤 보기 안에 있을 때도 작동합니다.

@Override
public void onUserInteraction() {
    if (getCurrentFocus() != null) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
    }
}

코틀린에서, 우리는 다음을 할 수 있습니다.모든 보기를 반복할 필요가 없습니다.파편에도 사용할 수 있습니다.

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    currentFocus?.let {
        val imm: InputMethodManager = getSystemService(
            Context.INPUT_METHOD_SERVICE
        ) as (InputMethodManager)
        imm.hideSoftInputFromWindow(it.windowToken, 0)
    }
    return super.dispatchTouchEvent(ev)
}

전화하는 방식이 마음에 들었습니다.dispatchTouchEventhtafoya 에의만지만졌어들해,만지:,

  • 타이머 부분을 이해하지 못했습니다(다운타임 측정이 왜 필요한지 모르겠습니다).
  • 모든 보기 변경 시 모든 편집 텍스트를 등록/등록 취소하고 싶지 않습니다(복잡한 계층에서 보기 변경 및 편집 텍스트가 상당히 많을 수 있음).

그래서 좀 더 쉬운 해결책을 만들었습니다.

@Override
public boolean dispatchTouchEvent(final MotionEvent ev) {
    // all touch events close the keyboard before they are processed except EditText instances.
    // if focus is an EditText we need to check, if the touchevent was inside the focus editTexts
    final View currentFocus = getCurrentFocus();
    if (!(currentFocus instanceof EditText) || !isTouchInsideView(ev, currentFocus)) {
        ((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE))
            .hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
    return super.dispatchTouchEvent(ev);
}

/**
 * determine if the given motionevent is inside the given view.
 * 
 * @param ev
 *            the given view
 * @param currentFocus
 *            the motion event.
 * @return if the given motionevent is inside the given view
 */
private boolean isTouchInsideView(final MotionEvent ev, final View currentFocus) {
    final int[] loc = new int[2];
    currentFocus.getLocationOnScreen(loc);
    return ev.getRawX() > loc[0] && ev.getRawY() > loc[1] && ev.getRawX() < (loc[0] + currentFocus.getWidth())
        && ev.getRawY() < (loc[1] + currentFocus.getHeight());
}

한 가지 단점이 있습니다.

의 나에서에서 EditText 다른사.EditText에서는 키보드를 숨겼다가 다시 표시합니다. 이 경우 두 입력 구성 요소 사이를 전환한 것으로 표시되기 때문에 이러한 방식이 좋습니다.

탄원: 제가 영향력이 없다는 것은 알지만, 제 대답을 진지하게 받아들여 주십시오.

문제:키보드에서 멀리를 클릭할 때 소프트 키보드를 해제하거나 최소한의 코드로 텍스트를 편집합니다.

솔루션:버터나이프로 알려진 외부 라이브러리입니다.

한 줄 솔루션:

@OnClick(R.id.activity_signup_layout) public void closeKeyboard() { ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); }

더 읽기 쉬운 솔루션:

@OnClick(R.id.activity_signup_layout) 
public void closeKeyboard() {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

설명: OnClick Listener를 활동의 XML 레이아웃 상위 ID에 바인딩합니다. 그러면 편집 텍스트나 키보드가 아닌 레이아웃을 클릭하면 키보드가 숨겨지는 코드 조각이 실행됩니다.

예:레이아웃 파일이 R.layout.my _http이고 레이아웃 ID가 R.id.my _http_id인 경우 버터나이프 바인딩 호출은 다음과 같습니다.

(@OnClick(R.id.my_layout_id) 
public void yourMethod {
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

버터나이프 설명서 링크: http://jakewharton.github.io/butterknife/

플러그: 버터나이프는 당신의 안드로이드 개발에 혁명을 일으킬 것입니다.생각해 보세요.

참고: 외부 라이브러리 Butterknife를 사용하지 않아도 동일한 결과를 얻을 수 있습니다.위에서 설명한 대로 OnClickListener를 부모 레이아웃으로 설정하면 됩니다.

너무 단순합니다. 최근 레이아웃을 클릭할 수 있도록 이 코드로 포커스할 수 있도록 설정하십시오.

android:id="@+id/loginParentLayout"
android:clickable="true"
android:focusableInTouchMode="true"

그런 다음 해당 레이아웃에 대한 메소드와 OnClickListner를 작성하여 맨 위의 레이아웃을 누르면 키보드를 해제하는 코드를 작성하는 메소드를 호출합니다.다음은 둘 다에 대한 코드입니다. // OnCreate()에 이 코드를 작성해야 합니다.

 yourLayout.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View view) {
                    hideKeyboard(view);
                }
            });

리스너에서 호출된 메서드:-

 public void hideKeyboard(View view) {
     InputMethodManager imm =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

site가 제기한 문제를 다루는 fje의 답변에 대한 또 다른 변형이 있습니다.

업 동작을 입니다.dispatchTouchEvent방법. 을 맞춘 보기경우)와가 그 안에 할 수 있도록 두 를 모두 합니다.아래로 이동할 때는 현재 초점을 맞춘 보기(있는 경우)와 터치가 그 안에 있었는지 여부를 기록하여 나중에 사용할 수 있도록 두 가지 정보를 모두 저장합니다.

다음 단계에서는 먼저 다른 보기가 잠재적으로 집중될 수 있도록 파견합니다.그런 다음 현재 포커스가 있는 보기가 원래 포커스가 있는 보기이고 아래쪽 터치가 해당 보기 안에 있으면 키보드를 열어 둡니다.

현재 초점을 맞춘 뷰가 원래 초점을 맞춘 와 다른 경우에 해당하는 경우EditText그리고 키보드도 열어둡니다.

그렇지 않으면 닫아야 합니다.

요약하면, 이것은 다음과 같이 작동합니다.

  • 현재 초점을 맞춘 내부를 만질 때EditText키보드가 열린 상태로 유지됩니다.
  • ▁from▁moving▁a▁when.EditText 다른사.EditText키보드가 열린 상태로 유지됨(닫히지 않음/닫히지 않음)
  • 현재 초점을 맞춘 외부의 어느 곳이든 만질 때.EditText그것은 다른 것이 아닙니다.EditText가 닫힙니다.
  • 오래 머물 때.EditText 표시줄단추 을 곳에서 열린 됩니다.EditText(CAB를 위한 공간을 만들기 위해 아래로 이동했습니다.)그러나 CAB에서 버튼을 누르면 키보드가 닫힙니다.이것은 바람직한 것일 수도 있고 바람직하지 않을 수도 있습니다. 한 필드에서 잘라내기/복사하여 다른 필드에 붙여넣으려면 그렇게 해야 합니다.한 한일항다로 다시 면넣으려붙여시에.EditText그렇지 않을 것입니다.
  • 이 맞춰질 때EditText화면 하단에 있고 텍스트를 길게 클릭하여 선택합니다.EditText는 포커스를 유지하므로 키보드가 원하는 대로 열립니다. 이는 위쪽 작업이 아니라 아래쪽 작업에 대해 "터치가 보기 범위 내에 있음"을 확인하기 때문입니다.

    private View focusedViewOnActionDown;
    private boolean touchWasInsideFocusedView;
    
    
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                focusedViewOnActionDown = getCurrentFocus();
                if (focusedViewOnActionDown != null) {
                    final Rect rect = new Rect();
                    final int[] coordinates = new int[2];
    
                    focusedViewOnActionDown.getLocationOnScreen(coordinates);
    
                    rect.set(coordinates[0], coordinates[1],
                            coordinates[0] + focusedViewOnActionDown.getWidth(),
                            coordinates[1] + focusedViewOnActionDown.getHeight());
    
                    final int x = (int) ev.getX();
                    final int y = (int) ev.getY();
    
                    touchWasInsideFocusedView = rect.contains(x, y);
                }
                break;
    
            case MotionEvent.ACTION_UP:
    
                if (focusedViewOnActionDown != null) {
                    // dispatch to allow new view to (potentially) take focus
                    final boolean consumed = super.dispatchTouchEvent(ev);
    
                    final View currentFocus = getCurrentFocus();
    
                    // if the focus is still on the original view and the touch was inside that view,
                    // leave the keyboard open.  Otherwise, if the focus is now on another view and that view
                    // is an EditText, also leave the keyboard open.
                    if (currentFocus.equals(focusedViewOnActionDown)) {
                        if (touchWasInsideFocusedView) {
                            return consumed;
                        }
                    } else if (currentFocus instanceof EditText) {
                        return consumed;
                    }
    
                    // the touch was outside the originally focused view and not inside another EditText,
                    // so close the keyboard
                    InputMethodManager inputMethodManager =
                            (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    inputMethodManager.hideSoftInputFromWindow(
                        focusedViewOnActionDown.getWindowToken(), 0);
                    focusedViewOnActionDown.clearFocus();
    
                    return consumed;
                }
                break;
        }
    
        return super.dispatchTouchEvent(ev);
    }
    

저는 이 간단한 요구 사항에 대해 승인된 답변 비트가 복잡하다고 생각합니다.이것이 아무런 문제 없이 저에게 효과가 있었던 것입니다.

findViewById(R.id.mainLayout).setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
            return false;
        }
    });

이것이 저에게 가장 쉬운 해결책입니다.

키보드를 숨기는 방법입니다.

public void hideKeyboard(View view){
        if(!(view instanceof EditText)){
            InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
        }
    }

의 방법으로 시 을 설정합니다.hideKeyboard파일의 합니다.XML 파일의 텍스트 보기에서 XML 파일을 사용합니다.

android:onClick="hideKeyboard"

아이폰과 같은 문제를 기반으로 한 더 간단한 접근법이 있습니다.편집 텍스트가 포함된 터치 이벤트에서 배경의 레이아웃을 재정의하기만 하면 됩니다.활동의 OnCreate에서 이 코드를 사용하면 됩니다(login_fondo가 루트 레이아웃임).

    final LinearLayout llLogin = (LinearLayout)findViewById(R.id.login_fondo);
    llLogin.setOnTouchListener(
            new OnTouchListener()
            {
                @Override
                public boolean onTouch(View view, MotionEvent ev) {
                    InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(
                            android.content.Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(mActivity.getCurrentFocus().getWindowToken(), 0);
                    return false;
                }
            });

소프트 키보드 표시/숨기기 방법

InputMethodManager inputMethodManager = (InputMethodManager) currentActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
    if (isShow) {
        if (currentActivity.getCurrentFocus() == null) {
            inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
        } else {
            inputMethodManager.showSoftInput(currentActivity.getCurrentFocus(), InputMethodManager.SHOW_FORCED);    
        }

    } else {
        if (currentActivity.getCurrentFocus() == null) {
            inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
        } else {
            inputMethodManager.hideSoftInputFromInputMethod(currentActivity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);    
        }

    }

그것들이 유용했길 바랍니다.

활동

 @Override
 public boolean dispatchTouchEvent(MotionEvent ev) {
     ScreenUtils.hideKeyboard(this, findViewById(android.R.id.content).getWindowToken());
     return super.dispatchTouchEvent(ev);
 }

스크린 유틸리티

 public static void hideKeyboard(Context context, IBinder windowToken) {
     InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
     imm.hideSoftInputFromWindow(windowToken, InputMethodManager.HIDE_NOT_ALWAYS);
 }

페르난도 카마라고의 해결책에 약간의 변형을 가해서 이 일을 했습니다.나의 onCreate 메서드에서 단일 onTouchListener를 루트 뷰에 첨부하지만 작업이 아닌 뷰를 인수로 보냅니다.

        findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {           
        public boolean onTouch(View v, MotionEvent event) {
            Utils.hideSoftKeyboard(v);
            return false;
        }
    });

별도의 Utils 클래스는...

    public static void hideSoftKeyboard(View v) {
    InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 
    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}

오래된 것일 수도 있지만 사용자 지정 클래스를 구현하여 이 작업을 수행했습니다.

public class DismissKeyboardListener implements OnClickListener {

    Activity mAct;

    public DismissKeyboardListener(Activity act) {
        this.mAct = act;
    }

    @Override
    public void onClick(View v) {
        if ( v instanceof ViewGroup ) {
            hideSoftKeyboard( this.mAct );
        }
    }       
}

public void hideSoftKeyboard(Activity activity) {
        InputMethodManager imm = (InputMethodManager)
        getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}

여기서 가장 좋은 방법은 도우미 클래스를 만드는 것이며 모든 컨테이너 Relative/Linear Layouts에서 이를 구현해야 합니다.

주 컨테이너만 이 클래스를 구현해야 합니다(최적화를 위해) ****.

다음과 같이 구현합니다.

Parent.setOnClickListener( new DismissKeyboardListener(this) ); 

활동에 대한 키워드입니다.따라서 fragment에 있는 경우 getActivity()와 같이 사용합니다.

도움이 된다면 엄지손가락을 치켜세우고 랠프를 응원합니다.

나는 다음과 같은 방법을 수행했습니다.

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
   View view = getCurrentFocus();
   if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) {
            int scrcoords[] = new int[2];
            view.getLocationOnScreen(scrcoords);
            float x = ev.getRawX() + view.getLeft() - scrcoords[0];
            float y = ev.getRawY() + view.getTop() - scrcoords[1];
            if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom())
                hideKeyboard(this);
        }
    return super.dispatchTouchEvent(ev);
}

키보드 코드 숨기기:

public static void hideKeyboard(Activity act) {
    if(act!=null)
      ((InputMethodManager)act.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((act.getWindow().getDecorView().getApplicationWindowToken()), 0);
  }

다 했어요.

이 문제를 해결하려면 먼저 해당 편집 텍스트의 setOnFocusChangeListener를 사용해야 합니다.

edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!hasFocus) {
                    Log.d("focus", "focus loosed");
                    // Do whatever you want here
                } else {
                    Log.d("focus", "focused");
                }
            }
        });

그런 다음 아래 코드를 참조하여 텍스트 편집이 포함된 활동에서 dispatchTouchEvent를 재정의해야 합니다.

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        View v = getCurrentFocus();
        if ( v instanceof EditText) {
            Rect outRect = new Rect();
            v.getGlobalVisibleRect(outRect);
            if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
                Log.d("focus", "touchevent");
                v.clearFocus();
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
        }
    }
    return super.dispatchTouchEvent(event);
}

이제 사용자가 밖을 클릭하면 먼저 dispatchTouchEvent가 호출되고 다음 편집에서 포커스가 지워집니다. 이제 OnFocusChangeListener가 포커스가 변경되었다는 호출을 받게 됩니다. 여기서 원하는 모든 작업을 수행할 수 있습니다.

나는 방법을 개선했고, 다음 코드를 일부 UI 유틸리티 클래스에 넣어 모든 활동 또는 조각 클래스에서 액세스하여 목적을 달성할 수 있도록 했습니다.

public static void serachAndHideSoftKeybordFromView(View view, final Activity act) {
    if(!(view instanceof EditText)) {
        view.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(act);
                return false;
            }
        });
    }
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            View nextViewInHierarchy = ((ViewGroup) view).getChildAt(i);
            serachAndHideSoftKeybordFromView(nextViewInHierarchy, act);
        }
    }
}
public static void hideSoftKeyboard (Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

그런 다음 예를 들어 활동에서 호출해야 한다고 가정합니다. 다음과 같이 호출합니다.

UIutils.serachAndHideSoftKeybordFromView(findViewById(android.R.id.content), YourActivityName.this);

공지

findViewById(안드로이드)를 선택합니다.R.id .content)

그러면 현재 그룹의 루트 보기가 표시됩니다(루트 보기에 ID를 설정하지 않았을 것).

건배 :)

상태 Hidden으로 .windowSoftInputMode

http://developer.android.com/reference/android/R.attr.html#windowSoftInputMode

활동 예:

this.getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

@Overide 클래스에 이 코드를 추가합니다.

public boolean dispatchTouchEvent(MotionEvent ev) {
    View view = getCurrentFocus();
    if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) {
        int scrcoords[] = new int[2];
        view.getLocationOnScreen(scrcoords);
        float x = ev.getRawX() + view.getLeft() - scrcoords[0];
        float y = ev.getRawY() + view.getTop() - scrcoords[1];
        if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom())
            ((InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((this.getWindow().getDecorView().getApplicationWindowToken()), 0);
    }
    return super.dispatchTouchEvent(ev);
}

언급URL : https://stackoverflow.com/questions/4165414/how-to-hide-soft-keyboard-on-android-after-clicking-outside-edittext