EditText, 외부 터치에 대한 명확한 초점 나타납니다. 외부

내 레이아웃에는 ListView, SurfaceViewEditText. 를 클릭하면 EditText포커스를 받고 화상 키보드가 나타납니다. 외부 어딘가를 클릭 EditText해도 여전히 포커스가 있습니다 (안됨). OnTouchListener레이아웃의 다른 뷰에서의를 설정하고 EditText의 포커스를 수동으로 지울 수 있다고 생각 합니다. 하지만 너무 끔찍해 보입니다 …

다른 레이아웃에서도 동일한 상황이 발생합니다. 다른 유형의 항목이있는 목록보기 중 일부는 EditText내부에 ‘가 있습니다. 위에서 쓴 것처럼 행동합니다.

작업은 EditText사용자가 외부의 무언가를 만질 때 초점 을 잃게 만드는 것입니다.

여기에서 비슷한 질문을 보았지만 해결책을 찾지 못했습니다 …



답변

이 모든 솔루션을 시도했습니다. edc598은 작동에 가장 가깝지만 터치 이벤트는 View레이아웃에 포함 된 다른에서 트리거되지 않았습니다 . 누군가이 행동이 필요한 경우, 이것이 내가 한 일입니다.

나는 (보이지 않는) 생성 FrameLayout이라는 touchInterceptor 마지막으로을 View은 모든 오버레이 그래서 레이아웃에 ( 편집 : 당신은 또한을 사용할 필요가 RelativeLayout부모 레이아웃으로와 줄 touchInterceptor의 fill_parent 특성). 그런 다음 터치를 차단하고 터치가 맨 위에 있는지 여부를 결정하는 데 사용했습니다 EditText.

FrameLayout touchInterceptor = (FrameLayout)findViewById(R.id.touchInterceptor);
touchInterceptor.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (mEditText.isFocused()) {
                Rect outRect = new Rect();
                mEditText.getGlobalVisibleRect(outRect);
                if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
                    mEditText.clearFocus();
                    InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                }
            }
        }
        return false;
    }
});

터치 처리가 실패하도록하려면 false를 반환합니다.

그것은 해키이지만 나에게 일한 유일한 것입니다.


답변

Ken의 답변을 바탕으로 가장 모듈화 된 복사 및 붙여 넣기 솔루션이 있습니다.

XML이 필요하지 않습니다.

그것을 당신의 활동에 넣으면 해당 활동 내의 조각을 포함하여 모든 EditText에 적용됩니다.

@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())) {
                v.clearFocus();
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
        }
    }
    return super.dispatchTouchEvent( event );
}


답변

EditText의 상위 뷰에 대해 clickable , focusable , focusableInTouchMode의 3 가지 속성을 ” true “로 설정 합니다.

뷰가 포커스를 받으려면 다음 3 가지 조건을 충족해야합니다.

android.view 참조 :

public boolean onTouchEvent(MotionEvent event) {
    ...
    if (((viewFlags & CLICKABLE) == CLICKABLE ||
        (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
        ...
        if (isFocusable() && isFocusableInTouchMode()
            && !isFocused()) {
                focusTaken = requestFocus();
        }
        ...
    }
    ...
}

도움이되기를 바랍니다.


답변

이 속성을 최상위 상위 항목에 넣으십시오.

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


답변

Ken의 대답은 작동하지만 해키입니다. pcans가 답변의 주석에서 언급했듯이 dispatchTouchEvent에서도 동일한 작업을 수행 할 수 있습니다. 이 솔루션은 투명한 더미 FrameLayout으로 XML을 해킹하지 않아도되므로 더 깔끔합니다. 다음은 다음과 같습니다.

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    EditText mEditText = findViewById(R.id.mEditText);
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        View v = getCurrentFocus();
        if (mEditText.isFocused()) {
            Rect outRect = new Rect();
            mEditText.getGlobalVisibleRect(outRect);
            if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
                mEditText.clearFocus();
                //
                // Hide keyboard
                //
                InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
        }
    }
    return super.dispatchTouchEvent(event);
}


답변

저를 위해 일한 것-

1. 추가 android:clickable="true"하고 android:focusableInTouchMode="true"받는 사람 parentLayoutEditTextandroid.support.design.widget.TextInputLayout

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusableInTouchMode="true">
<EditText
    android:id="@+id/employeeID"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ems="10"
    android:inputType="number"
    android:hint="Employee ID"
    tools:layout_editor_absoluteX="-62dp"
    tools:layout_editor_absoluteY="16dp"
    android:layout_marginTop="42dp"
    android:layout_alignParentTop="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:layout_marginRight="36dp"
    android:layout_marginEnd="36dp" />
    </android.support.design.widget.TextInputLayout>

2. Activity 클래스 재정의 dispatchTouchEventhideKeyboard()함수 삽입

@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            View view = getCurrentFocus();
            if (view != null && view instanceof EditText) {
                Rect r = new Rect();
                view.getGlobalVisibleRect(r);
                int rawX = (int)ev.getRawX();
                int rawY = (int)ev.getRawY();
                if (!r.contains(rawX, rawY)) {
                    view.clearFocus();
                }
            }
        }
        return super.dispatchTouchEvent(ev);
    }

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

3. EditText 추가setOnFocusChangeListener

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


답변

이 문제에 대한 답을 이미 찾았을 수도 있지만이 문제를 해결하는 방법을 찾고 있었지만 여전히 내가 찾고있는 것을 정확히 찾을 수 없으므로 여기에 게시 할 것이라고 생각했습니다.

내가 한 일은 다음과 같습니다 (이것은 매우 일반화되어 있으며 모든 코드를 복사하고 붙여 넣는 방법에 대한 아이디어를 제공하는 것이 O : D 작동하지 않습니다) :

먼저 EditText 및 프로그램에서 원하는 다른 뷰를 단일 뷰로 래핑하십시오. 제 경우에는 LinearLayout을 사용하여 모든 것을 래핑했습니다.

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/mainLinearLayout">
 <EditText
  android:id="@+id/editText"/>
 <ImageView
  android:id="@+id/imageView"/>
 <TextView
  android:id="@+id/textView"/>
 </LinearLayout>

그런 다음 코드에서 터치 리스너를 기본 LinearLayout으로 설정해야합니다.

final EditText searchEditText = (EditText) findViewById(R.id.editText);
mainLinearLayout.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            if(searchEditText.isFocused()){
                if(event.getY() >= 72){
                    //Will only enter this if the EditText already has focus
                    //And if a touch event happens outside of the EditText
                    //Which in my case is at the top of my layout
                    //and 72 pixels long
                    searchEditText.clearFocus();
                    InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                }
            }
            Toast.makeText(getBaseContext(), "Clicked", Toast.LENGTH_SHORT).show();
            return false;
        }
    });

나는 이것이 어떤 사람들에게 도움이되기를 바랍니다. 또는 적어도 문제 해결을 시작하도록 도와줍니다.