EditText, 외부 터치에 대한 명확한 증가
내 레이아웃에는 ListView
, SurfaceView
및 EditText
. 를 클릭하면 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;
}
});
터치 처리가 실패하면 거짓을 반환합니다.
그것은 해키이지만 나에게 일한 유일한 것입니다.
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 );
}
글고의 상위 뷰에 대해 클릭 , 포커스 , focusableIn TouchMode를의 3 가지 속성을 " 진정한 "설정로 합니다.
다음 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);
}
이미이 문제에 대한 답을 찾았습니다.이 문제를 해결하는 방법을 찾고 있었지만 여전히 내가 찾고있는 것을 정확히 파악할 수 있습니다 여기에 게시 할 생각했습니다.
내가 한 일은 다음과 같다 (이것은 매우 일반화되어있는 모든 코드를 복사하고 너에게 넣는 방법에 아이디어를 제공하는 것이 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;
}
});
나는 이것이 어떤 사람들에게 도움이되기를 바랍니다. 또는 문제 해결을 시작하도록 지원합니다.
저를 위해 일한 것-
1. 추가 android:clickable="true"
하고 android:focusableInTouchMode="true"
받는 사람 parentLayout
의 EditText
예android.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 클래스 재정의 dispatchTouchEvent
및 hideKeyboard()
함수 삽입
@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);
}
}
});
난 정말이 사용하는 더 강력한 방법 생각 getLocationOnScreen
보다 getGlobalVisibleRect
. 문제가 발생했기 때문입니다. 일부 Edittext를 포함 ajustpan
하고 활동에 설정된 Listview가 있습니다 . 내가 찾아 getGlobalVisibleRect
거기에 scrollY하지만 event.getRawY 등 같은 외모가 화면에 의해 항상하는 값을 반환합니다. 아래 코드는 잘 작동합니다.
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if ( v instanceof EditText) {
if (!isPointInsideView(event.getRawX(), event.getRawY(), v)) {
Log.i(TAG, "!isPointInsideView");
Log.i(TAG, "dispatchTouchEvent clearFocus");
v.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
}
return super.dispatchTouchEvent( event );
}
/**
* Determines if given points are inside view
* @param x - x coordinate of point
* @param y - y coordinate of point
* @param view - view object to compare
* @return true if the points are within view bounds, false otherwise
*/
private boolean isPointInsideView(float x, float y, View view) {
int location[] = new int[2];
view.getLocationOnScreen(location);
int viewX = location[0];
int viewY = location[1];
Log.i(TAG, "location x: " + location[0] + ", y: " + location[1]);
Log.i(TAG, "location xWidth: " + (viewX + view.getWidth()) + ", yHeight: " + (viewY + view.getHeight()));
// point is inside view bounds
return ((x > viewX && x < (viewX + view.getWidth())) &&
(y > viewY && y < (viewY + view.getHeight())));
}
다음 EditText
과 같이 부모의 두 속성을 정의하기 만하면 됩니다.
android:clickable="true"
android:focusableInTouchMode="true"
따라서 사용자가 EditText
영역 외부를 터치 하면 포커스가 상위 뷰로 전환되므로 포커스가 제거됩니다.
다른 뷰를 터치했을 때 포커스를 잃으려면 두 뷰를 모두 view.focusableInTouchMode (true)로 설정해야합니다.
그러나 터치 모드에서 초점을 사용하는 것은 권장되지 않는 것 같습니다. 여기를보세요 : http://android-developers.blogspot.com/2008/12/touch-mode.html
나는 견해 로 ListView
구성되어 EditText
있습니다. 시나리오는 하나 이상의 행에서 텍스트를 편집 한 후 "마침"이라는 버튼을 클릭해야한다고 말합니다. 내부보기 onFocusChanged
에서 사용 했지만 완료를 클릭하면 데이터가 저장되지 않습니다. 문제는 다음을 추가하여 해결되었습니다.EditText
listView
listView.clearFocus();
내부 onClickListener
"마침"버튼과 데이터를 성공적으로 저장되었습니다.
가장 좋은 방법은 기본 방법을 사용하는 것입니다. clearFocus()
코드를 onTouchListener
올바르게 해결하는 방법을 알고 있습니까?
전화 만하세요 EditText.clearFocus()
. 에서 초점이 명확 해 last EditText
집니다.
@pcans가 제안했듯이 dispatchTouchEvent(MotionEvent event)
활동 에서이 재정의 를 수행 할 수 있습니다 .
여기에서 터치 좌표를 얻고이를 뷰 경계와 비교합니다. 터치가 뷰 외부에서 수행되면 무언가를 수행하십시오.
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
View yourView = (View) findViewById(R.id.view_id);
if (yourView != null && yourView.getVisibility() == View.VISIBLE) {
// touch coordinates
int touchX = (int) event.getX();
int touchY = (int) event.getY();
// get your view coordinates
final int[] viewLocation = new int[2];
yourView.getLocationOnScreen(viewLocation);
// The left coordinate of the view
int viewX1 = viewLocation[0];
// The right coordinate of the view
int viewX2 = viewLocation[0] + yourView.getWidth();
// The top coordinate of the view
int viewY1 = viewLocation[1];
// The bottom coordinate of the view
int viewY2 = viewLocation[1] + yourView.getHeight();
if (!((touchX >= viewX1 && touchX <= viewX2) && (touchY >= viewY1 && touchY <= viewY2))) {
Do what you want...
// If you don't want allow touch outside (for example, only hide keyboard or dismiss popup)
return false;
}
}
}
return super.dispatchTouchEvent(event);
}
또한 활동의 레이아웃이 런타임 중에 변경되지 않는 경우보기 존재 여부와 가시성을 확인할 필요가 없습니다 (예 : 레이아웃에서 조각을 추가하거나보기를 교체 / 제거하지 않음). 그러나 사용자 정의 컨텍스트 메뉴 (예 : 항목의 오버플로 메뉴를 사용할 때 Google Play 스토어에서)를 닫고 (또는 유사한 작업을 수행하려면)보기 존재 여부를 확인해야합니다. 그렇지 않으면 NullPointerException
.
이 간단한 코드 조각은 원하는 작업을 수행합니다.
GestureDetector gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
KeyboardUtil.hideKeyboard(getActivity());
return true;
}
});
mScrollView.setOnTouchListener((v, e) -> gestureDetector.onTouchEvent(e));
참고 URL : https://stackoverflow.com/questions/4828636/edittext-clear-focus-on-touch-outside
'IT' 카테고리의 다른 글
이 프로그램은 어떻게 작동합니까? (0) | 2020.09.08 |
---|---|
두 개의 개의 연결 목록이 병합 확인하십시오. (0) | 2020.09.08 |
AppDelegate에서 UINavigationBar 배경색을 변경하는 방법 (0) | 2020.09.08 |
Python의 네트워크에 IP가 어디에 있는지 확인할 수 있습니까? (0) | 2020.09.08 |
Eclipse에서 AVD 또는 SDK 관리자를 사용할 수 없습니다. (0) | 2020.09.08 |