누구나 키보드를 숨기려면 구현해야한다는 것을 모두 알고 있습니다.
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
위 함수의 Kotlin 버전은 다음과 같습니다.
@file:JvmName("KeyboardUtils")
fun Activity.hideSoftKeyboard() {
currentFocus?.let {
val inputMethodManager = ContextCompat.getSystemService(this, InputMethodManager::class.java)!!
inputMethodManager.hideSoftInputFromWindow(it.windowToken, 0)
}
}
답변
다음 단계를 수행하여이를 달성 할 수 있습니다.
-
다음 속성을 추가하여 상위보기 (활동의 컨텐츠보기)를 클릭 가능하고 집중 가능하게하십시오.
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 바로 아래의보기에 추가 될 수 있습니다.
답변
활동에서 아래 코드를 재정의하십시오.
@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);
}
답변
수락 된 답변이 약간 복잡하다는 것을 알았습니다.
여기 내 해결책이 있습니다. 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
. 소프트 키보드가 강제로 닫힙니다.
답변
글쎄, 나는 다소 문제를 해결하고, 활동에 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 외부에 있으면 키보드를 숨 깁니다.