Program Club

소프트 키보드에서 뒤로 버튼 차단

proclub 2020. 10. 11. 11:32
반응형

소프트 키보드에서 뒤로 버튼 차단


여러 입력 필드가있는 활동이 있습니다. 활동이 시작되면 소프트 키보드가 표시됩니다. 뒤로 버튼을 누르면 소프트 키보드가 닫히고 활동을 닫으려면 뒤로 버튼을 한 번 더 눌러야합니다.

그래서 질문 : 소프트 키보드를 닫고 사용자 정의를 만들지 않고 뒤로 버튼을 한 번 눌러 작업을 완료하기 위해 뒤로 버튼을 가로 챌 수 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);
   }
}

I found out, that overriding the dispatchKeyEventPreIme method of the Layout Class also works well. Just set your main Activity as an attribute and launch a predefined method.

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);
    }
}

I had success by overriding dispatchKeyEvent:

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
        finish();
        return true;
    }
    return super.dispatchKeyEvent(event);
}

It hides the keyboard and finishes the activity.


How are you showing the soft keyboard?

If you are using InputMethodManager.showSoftInput(), you can try passing in a ResultReceiver and implementing onReceiveResult() to handle RESULT_HIDDEN

http://developer.android.com/reference/android/view/inputmethod/InputMethodManager.html


I had the same problem but got around it by intercepting the back key press. In my case (HTC Desire, Android 2.2, Application API Level 4) it closes the Keyboard and immediately finishes the Activity. Don't know why this should not work for you too:

@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();
}

Use onKeyPreIme(int keyCode, KeyEvent event) method and check for KeyEvent.KEYCODE_BACK event. It's very simple without doing any fancy coding.


Try this code in your BackPressed implementation(Block Back Button in android):

InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);

I suggest you to have a look @ Close/hide the Android Soft Keyboard

참고URL : https://stackoverflow.com/questions/3940127/intercept-back-button-from-soft-keyboard

반응형