EditText 외부를 클릭 한 후 안드로이드에서 소프트 키보드를 숨기는 방법은 무엇입니까?
모든 사람은 키보드를 숨기려면 구현해야한다는 것을 알고 있습니다.
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
그러나 여기서 가장 중요한 것은 사용자가 소프트 키보드가 아닌 다른 장소를 만지거나 선택할 때 키보드를 숨기는 방법입니다 EditText
.
onTouchEvent()
부모님 을 사용하려고했지만 Activity
사용자가 다른보기 외부를 만지고 스크롤보기가없는 경우에만 작동합니다.
나는 터치, 클릭, 포커스 리스너를 성공없이 구현하려고했습니다.
터치 이벤트를 가로 채기 위해 자체 스크롤보기를 구현하려고했지만보기를 클릭하지 않고 이벤트의 좌표 만 가져올 수 있습니다.
이것을 수행하는 표준 방법이 있습니까 ?? iPhone에서는 정말 쉬웠습니다.
다음 스 니펫은 단순히 키보드를 숨 깁니다.
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager =
(InputMethodManager) activity.getSystemService(
Activity.INPUT_METHOD_SERVICE);
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
입니다. 활동을 마친 후에이 메소드를 호출 하십시오. 전달할 매개 변수가 궁금한 경우 id
부모 컨테이너의 매개 변수 입니다. 다음 id
과 같이 부모 컨테이너에
<RelativeLayoutPanel android:id="@+id/parent"> ... </RelativeLayout>
그리고 전화 setupUI(findViewById(R.id.parent))
, 그게 다야.
이를 효과적으로 사용하려면 확장을 작성 Activity
하고이 메소드를 삽입하고 애플리케이션의 다른 모든 활동이이 활동을 확장 setupUI()
하고 onCreate()
메소드 에서 호출하도록 할 수 있습니다.
도움이 되길 바랍니다.
둘 이상의 활동을 사용하는 경우 공통 ID를 상위 레이아웃에 정의하십시오. <RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>
그런 다음 클래스를 확장하고 클래스 내 에서 Activity
정의 하고``활동 대신이 클래스를 확장하십시오.setupUI(findViewById(R.id.main_parent))
OnResume()
in your program
다음 단계를 수행하여이를 달성 할 수 있습니다.
다음 속성을 추가하여 상위보기 (활동의 컨텐츠보기)를 클릭 가능하고 집중 가능하게하십시오.
android:clickable="true" android:focusableInTouchMode="true"
hideKeyboard () 메소드 구현
public void hideKeyboard(View view) { InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); }
마지막으로 편집 텍스트의 onFocusChangeListener를 설정하십시오.
edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { hideKeyboard(v); } } });
아래 주석 중 하나에서 지적했듯이 부모보기가 ScrollView 인 경우 작동하지 않을 수 있습니다. 이러한 경우 클릭 가능 및 포커스 가능 InTouchMode가 ScrollView 바로 아래의보기에 추가 될 수 있습니다.
수락 된 답변이 약간 복잡하다는 것을 알았습니다.
여기 내 해결책이 있습니다. OnTouchListener
기본 레이아웃에을 추가하십시오 .
findViewById(R.id.mainLayout).setOnTouchListener(this)
다음 코드를 onTouch 메소드에 넣습니다.
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
. 소프트 키보드가 강제로 닫힙니다.
활동에서 아래 코드를 재정의하십시오.
@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);
}
글쎄, 나는 다소 문제를 해결하고, 활동에 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};
완벽하지는 않습니다. 드래그 이벤트 시간은 휴리스틱에만 기반하기 때문에 긴 성직자를 수행 할 때 숨기지 않는 경우가 많으며 뷰당 모든 editText를 가져 오는 방법도 작성했습니다. 그렇지 않으면 다른 EditText를 클릭 할 때 키보드가 숨겨져 표시됩니다.
더 깨끗하고 짧은 솔루션은 환영합니다
OnFocusChangeListener를 사용하십시오 .
예를 들면 다음과 같습니다.
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
hideKeyboard();
}
}
});
업데이트 : onTouchEvent()
활동을 재정의 하고 터치 좌표를 확인할 수도 있습니다 . 좌표가 EditText 외부에 있으면 키보드를 숨 깁니다.
이를 위해 Activity에서 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);
}
나는 그것을 테스트하고 완벽하게 작동합니다!
모든 활동에서 공개 부울 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;
}
그리고 그게 당신이해야 할 전부입니다
더 코 틀린 및 재질 디자인 사용 방법 TextInputEditText (이 방법은과도 호환 EditTextView ) ...
1. 다음 속성을 추가하여 상위 뷰 (활동 / 조각의 컨텐츠 뷰)를 클릭하고 초점을 맞 춥니 다.
android:focusable="true"
android:focusableInTouchMode="true"
android:clickable="true"
2. 모든 View의 확장명을 만듭니다 (예 : ViewExtension.kt 파일 내부).
fun View.hideKeyboard(){
val inputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(this.windowToken, 0)
}
3. TextInputEditText를 상속하는 BaseTextInputEditText를 작성하십시오. 보기에 초점이 맞지 않을 때 키보드를 숨기려면 onFocusChanged 메소드를 구현하십시오.
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>
그게 다야. 이 반복적 인 사례를 처리하기 위해 컨트롤러 (조각 또는 활동) 를 수정할 필요가 없습니다 .
이 스레드가 상당히 오래되었다는 것을 알고 있습니다. 정답은 유효하고 많은 해결책이 있지만, 아래에 언급 된 접근법은 효율성과 우아함에 대해 추가 이점이있을 수 있습니다.
모든 활동에 대해이 동작이 필요하므로 Activity 클래스에서 상속되는 CustomActivity 클래스를 작성 하고 dispatchTouchEvent 함수를 "후크"했습니다 . 주의해야 할 두 가지 조건이 있습니다.
- 포커스가 변경되지 않고 누군가 현재 입력 필드 외부를 두드리면 IME를 해제하십시오.
- 포커스가 변경되고 다음 포커스 요소가 입력 필드의 인스턴스가 아닌 경우 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);
}
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);
}
그러나 성능이 떨어지는 모든보기에 OnTouchListener를 등록하는 대신 루트보기 만 OnTouchListener를 등록했습니다. 이벤트가 소비 될 때까지 버블 링되므로 (EditText는 기본적으로 소비하는 뷰 중 하나입니다) 루트보기에 도달하면 소비되지 않았기 때문에 소프트 키보드를 닫습니다.
findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Utils.hideSoftKeyboard(activity);
return false;
}
});
나는 dispatchTouchEvent
htafoya 의 전화 접근 방식이 마음에 들었습니다 .
- 타이머 부분을 이해하지 못했습니다 (정지 시간을 측정 해야하는 이유를 모르십니까?)
- 모든보기 변경마다 모든 EditText를 등록 / 등록 취소하고 싶지 않습니다 (복잡한 계층 구조에서 많은 viewchanges 및 edittext 일 수 있음)
따라서이 다소 쉬운 솔루션을 만들었습니다.
@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
하면 키보드가 숨겨지고 다시 표시됩니다. 필자의 경우 두 입력 구성 요소 사이에서 전환되었음을 보여주기 때문에 그런 식으로 원합니다.
탄원 : 나는 영향력이 없다는 것을 알고 있지만, 대답을 진지하게 받아들이십시오.
문제 : 키보드에서 멀리 클릭하거나 최소한의 코드로 텍스트를 편집 할 때 소프트 키보드를 닫으십시오.
솔루션 : Butterknife로 알려진 외부 라이브러리 .
한 줄 솔루션 :
@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 리스너를 활동의 XML 레이아웃 상위 ID에 바인드하여 레이아웃 (편집 텍스트 또는 키보드가 아님)을 클릭하면 키보드를 숨길 코드 스 니펫을 실행합니다.
예 : 레이아웃 파일이 R.layout.my_layout이고 레이아웃 ID가 R.id.my_layout_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를 상위 레이아웃으로 설정하십시오.
다음은 사이트에서 제기 된 문제를 해결하는 fje의 답변에 대한 또 다른 변형입니다.
여기서 아이디어는 활동 dispatchTouchEvent
방법 에서 아래로 및 위로 작업을 모두 처리 하는 것입니다. 다운 액션에서는 현재 포커스가있는 뷰 (있는 경우)와 터치가 내부에 있는지 여부를 기록하여 나중에 정보 비트를 모두 저장합니다.
우리는 먼저 다른 조치에 초점을 맞출 수 있도록 조치를 취합니다. 그 후에 현재 포커스가있는 뷰가 원래 포커스 된 뷰이고 아래쪽 터치가 해당 뷰 안에있는 경우 키보드를 열어 둡니다.
현재 포커스 뷰가 원래 뷰를 초점을 맞추고 다른 경우 와 그것이이다 EditText
, 우리는 열려있는 키보드를 둡니다.
그렇지 않으면 우리는 그것을 닫습니다.
요약하면 다음과 같이 작동합니다.
- 현재 포커스
EditText
가있는 내부를 만지면 키보드는 열린 상태를 유지합니다 - 포커스
EditText
에서 다른 포커스 로 이동할 때EditText
키보드는 열린 상태를 유지합니다 (닫거나 다시 열지 않음) - 현재 초점
EditText
이 아닌 다른 곳을 터치EditText
하면 키보드가 닫힙니다. EditText
상황에 맞는 작업 표시 줄 (잘라 내기 / 복사 / 붙여 넣기 단추 사용)을 표시하기 위해 길게 누르면 키보드가 열려 있습니다 (UP 작업이 초점을 벗어난 위치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); }
이 코드로 최근 레이아웃을 클릭 가능하게 만들 수 있습니다.
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);
}
});
listner에서 호출 된 메소드 :-
public void hideKeyboard(View view) {
InputMethodManager imm =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
이 간단한 요구 사항에 대해 허용되는 답변 비트가 복잡하다는 것을 알았습니다. 결함없이 나를 위해 일한 것은 다음과 같습니다.
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;
}
});
소프트 키보드 표시 / 숨기기 방법
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);
}
}
나는 그들이 유용했으면 좋겠다.
iPhone과 동일한 문제를 기반으로 한 더 간단한 접근 방식이 있습니다. 편집 텍스트가 포함 된 터치 이벤트에서 배경의 레이아웃을 무시하기 만하면됩니다. 액티비티의 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;
}
});
나는 메소드를 세분화하고, 일부 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 (android.R.id.content)
이것은 현재 그룹의 루트보기를 제공합니다 (루트보기에서 ID를 설정하지 않아야합니다).
건배 :)
stateHidden을 활동 windowSoftInputMode
값 으로 설정하십시오.
http://developer.android.com/reference/android/R.attr.html#windowSoftInputMode
예를 들어 활동의 경우 :
this.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
활동
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
ScreenUtils.hideKeyboard(this, findViewById(android.R.id.content).getWindowToken());
return super.dispatchTouchEvent(ev);
}
ScreenUtils
public static void hideKeyboard(Context context, IBinder windowToken) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(windowToken, InputMethodManager.HIDE_NOT_ALWAYS);
}
이 코드를 @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);
}
kotlin에서는 다음을 수행 할 수 있습니다. 모든 뷰를 반복 할 필요가 없습니다. 조각에도 적용됩니다.
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)
}
이것은 오래되었지만 사용자 정의 클래스를 임박 하여이 작업을 수행했습니다.
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);
}
여기서 모범 사례는 Helper 클래스를 만드는 것이며 모든 컨테이너 Relative / Linear Layouts는이를 구현해야합니다.
**** 메인 컨테이너 만이 클래스를 구현해야합니다 (최적화) ****
다음과 같이 구현하십시오.
Parent.setOnClickListener( new DismissKeyboardListener(this) );
활동에 대한 키워드입니다. 그래서 조각에 있다면 getActivity ()와 같이 사용하십시오.
--- 엄청나게 도와 주면 ... --- Ralph를 응원합니다 ---
이것은 fje의 답변 중 약간 수정 된 버전으로 대부분 완벽하게 작동했습니다.
이 버전은 ACTION_DOWN을 사용하므로 스크롤 동작을 수행하면 키보드도 닫힙니다. 또한 다른 EditText를 클릭하지 않으면 이벤트가 전파되지 않습니다. 즉, EditText 외부의 아무 곳이나 클릭 가능하더라도 클릭하면 키보드가 닫힙니다.
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
if(ev.getAction() == MotionEvent.ACTION_DOWN)
{
final View view = getCurrentFocus();
if(view != null)
{
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))
{
super.dispatchTouchEvent(ev);
return true;
}
}
else if(viewNew instanceof EditText || viewNew instanceof CustomEditText)
{
super.dispatchTouchEvent(ev);
return true;
}
final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0);
viewNew.clearFocus();
return true;
}
}
return super.dispatchTouchEvent(ev);
}
나는 이렇게했다 :
@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);
}
끝난
이 문제를 해결하려면 먼저 해당 Edittext의 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가 호출되면 editext에서 포커스가 지워집니다. 이제 OnFocusChangeListener가 포커스가 변경되었다고 호출됩니다. 여기서 원하는 작업을 수행 할 수 있습니다.
@Override
public boolean onTouchEvent(MotionEvent event) {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.
INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
return true;
}
이 코드를 사용할 수 있습니다. "mainRelativeLayout"대신 기본 레이아웃 ID를 사용하십시오.
//hide Soft keyboard on click outside the input text
findViewById(R.id.mainRelativeLayout).setOnClickListener(new
View.OnClickListener() {
@Override
public void onClick(View v) {
InputMethodManager im = (InputMethodManager)
getSystemService(INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
0);
}
});
'Programming' 카테고리의 다른 글
한 번에 모든 MySQL 데이터베이스 내보내기 및 가져 오기 (0) | 2020.03.05 |
---|---|
객체 배열에서 속성의 최대 값 찾기 (0) | 2020.03.05 |
개인 API를 사용하지 않고 현재 첫 번째 응답자 확보 (0) | 2020.03.05 |
프로덕션 용 Angular 앱 번들 방법 (0) | 2020.03.05 |
자식 커밋 및 태그를 동시에 푸시 (0) | 2020.03.05 |