여러 입력 필드가있는 활동이 있습니다. 활동이 시작되면 소프트 키보드가 표시됩니다. 뒤로 버튼을 누르면 소프트 키보드가 닫히고 활동을 닫으려면 뒤로 버튼을 한 번 더 눌러야합니다.
그래서 질문 : 소프트 키보드를 닫고 사용자 정의를 만들지 않고 뒤로 버튼을 한 번 눌러 작업을 완료하기 위해 뒤로 버튼을 가로 챌 수 InputMethodService
있습니까?
추신 : 다른 경우에 뒤로 버튼을 가로채는 방법을 알고 있습니다. onKeyDown()
또는 onBackPressed()
이 경우에는 작동하지 않습니다. 뒤로 버튼을 두 번 누르는 것만 차단됩니다.
답변
예, 키보드를 표시하거나 숨기고 뒤로 버튼에 대한 호출을 가로 챌 수 있습니다. API에서이를 수행하는 직접적인 방법이 없다고 언급 했으므로 약간의 추가 노력이 필요합니다. 핵심은 boolean dispatchKeyEventPreIme(KeyEvent)
레이아웃 내 에서 재정의 하는 것입니다. 우리가하는 일은 레이아웃을 만드는 것입니다. 내 활동의 기반이기 때문에 RelativeLayout을 선택했습니다.
<?xml version="1.0" encoding="utf-8"?>
<com.michaelhradek.superapp.utilities.SearchLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.michaelhradek.superapp"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/white">
활동 내에서 입력 필드를 설정하고 setActivity(...)
함수를 호출합니다 .
private void initInputField() {
mInputField = (EditText) findViewById(R.id.searchInput);
InputMethodManager imm =
(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,
InputMethodManager.HIDE_IMPLICIT_ONLY);
mInputField.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
performSearch();
return true;
}
return false;
}
});
// Let the layout know we are going to be overriding the back button
SearchLayout.setSearchActivity(this);
}
분명히이 initInputField()
함수는 입력 필드를 설정합니다. 또한 Enter 키를 사용하여 기능을 실행할 수 있습니다 (제 경우에는 검색).
@Override
public void onBackPressed() {
// It's expensive, if running turn it off.
DataHelper.cancelSearch();
hideKeyboard();
super.onBackPressed();
}
따라서 onBackPressed()
레이아웃 내에서이 호출되면 키보드를 숨기는 등 원하는대로 할 수 있습니다.
private void hideKeyboard() {
InputMethodManager imm = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mInputField.getWindowToken(), 0);
}
어쨌든, 여기에 RelativeLayout의 재정의가 있습니다.
package com.michaelhradek.superapp.utilities;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.RelativeLayout;
/**
* The root element in the search bar layout. This is a custom view just to
* override the handling of the back button.
*
*/
public class SearchLayout extends RelativeLayout {
private static final String TAG = "SearchLayout";
private static Activity mSearchActivity;;
public SearchLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SearchLayout(Context context) {
super(context);
}
public static void setSearchActivity(Activity searchActivity) {
mSearchActivity = searchActivity;
}
/**
* Overrides the handling of the back key to move back to the
* previous sources or dismiss the search dialog, instead of
* dismissing the input method.
*/
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
Log.d(TAG, "dispatchKeyEventPreIme(" + event + ")");
if (mSearchActivity != null &&
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
KeyEvent.DispatcherState state = getKeyDispatcherState();
if (state != null) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0) {
state.startTracking(event, this);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP
&& !event.isCanceled() && state.isTracking(event)) {
mSearchActivity.onBackPressed();
return true;
}
}
}
return super.dispatchKeyEventPreIme(event);
}
}
불행히도 모든 신용을받을 수는 없습니다. 빠른 검색 대화 상자 에서 Android 소스를 확인 하면 아이디어의 출처를 볼 수 있습니다.
답변
이 경우 onKeyDown () 및 onBackPressed () 가 작동하지 않습니다. onKeyPreIme 를 사용해야 합니다 .
처음에는 EditText를 확장하는 사용자 정의 편집 텍스트를 만들어야합니다. 그리고 KeyEvent.KEYCODE_BACK 을 제어하는 onKeyPreIme 메소드를 구현해야 합니다 . 그 후, 문제를 해결하기에 충분한 백 프레스. 이 솔루션은 저에게 완벽하게 작동합니다.
CustomEditText.java
public class CustomEditText extends EditText {
public CustomEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// User has pressed Back key. So hide the keyboard
InputMethodManager mgr = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
mgr.hideSoftInputFromWindow(this.getWindowToken(), 0);
// TODO: Hide your view as you do it in your activity
}
return false;
}
XML에서
<com.YOURAPP.CustomEditText
android:id="@+id/CEditText"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
당신의 활동에서
public class MainActivity extends Activity {
private CustomEditText editText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (CustomEditText) findViewById(R.id.CEditText);
}
}
답변
레이아웃 클래스 의 dispatchKeyEventPreIme 메서드 를 재정의하는 것도 잘 작동 한다는 것을 알았습니다 . 기본 활동을 속성으로 설정하고 사전 정의 된 방법을 시작하기 만하면됩니다.
public class LinearLayoutGradient extends LinearLayout {
MainActivity a;
public void setMainActivity(MainActivity a) {
this.a = a;
}
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if (a != null) {
InputMethodManager imm = (InputMethodManager) a
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isActive() && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
a.launchMethod;
}
}
return super.dispatchKeyEventPreIme(event);
}
}
답변
dispatchKeyEvent 를 재정 의하여 성공했습니다 .
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
finish();
return true;
}
return super.dispatchKeyEvent(event);
}
키보드를 숨기고 활동을 완료합니다.
답변
소프트 키보드를 어떻게 보여주고 있습니까?
을 사용 InputMethodManager.showSoftInput()
하는 경우을 전달 ResultReceiver
하고 구현 onReceiveResult()
하여RESULT_HIDDEN
http://developer.android.com/reference/android/view/inputmethod/InputMethodManager.html
답변
나는 같은 문제가 있었지만 뒤로 키 누름을 가로 채서 문제를 해결했습니다. 제 경우에는 (HTC Desire, Android 2.2, Application API 레벨 4) 키보드를 닫고 즉시 활동을 완료합니다. 이것이 왜 당신에게도 효과가 없어야하는지 모르겠습니다.
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
onBackPressed();
return true;
}
return super.onKeyUp(keyCode, event);
}
/**
* Called when the activity has detected the user's press of the back key
*/
private void onBackPressed() {
Log.e(TAG, "back pressed");
finish();
}
답변
onKeyPreIme(int keyCode, KeyEvent event)
방법을 사용 하고 KeyEvent.KEYCODE_BACK
이벤트를 확인하십시오 . 멋진 코딩을하지 않고도 매우 간단합니다.