1. ホーム
  2. android

[解決済み] ソフトキーボードの戻るボタンを遮断する

2023-05-04 02:36:59

質問

いくつかの入力フィールドを持つアクティビティがあります。アクティビティが開始されると、ソフトキーボードが表示されます。戻るボタンが押されるとソフトキーボードが閉じ、アクティビティを閉じるにはもう一回戻るボタンを押す必要があります。

そこで質問ですが、ソフトキーボードを閉じるためにバックボタンをインターセプトし、カスタム InputMethodService ?

追伸:他のケースで戻るボタンをインターセプトする方法は知っています。 onKeyDown() または onBackPressed() のように記述することもできますが、この場合はうまくいきません:バックボタンの2回目だけがインターセプトされます。

どのように解決するのですか?

はい、キーボードの表示/非表示と、戻るボタンの呼び出しを傍受することは完全に可能です。API でこれを行う直接的な方法がないことが言及されているように、少し余分な労力がかかります。キーは boolean dispatchKeyEventPreIme(KeyEvent) をレイアウト内でオーバーライドすることです。まず、レイアウトを作成します。私はRelativeLayoutを選んだので、これが私のActivityのベースになっています。

<?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">

Activityの内部で入力フィールドを設定し、その上で 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の のソースを確認すると、クイック検索ダイアログボックス のソースを確認すると、このアイデアがどこから来たのかがわかります。