1

2 つのアクティビティを含むアプリを使用していますが、アクティビティを切り替えると同時に、再開されたばかりのアクティビティのアクションバーで検索入力を開く必要がある場合があります。キーボードを起動できないことを除いて、すべて正常に動作します。true私のコードの関連ビットは以下のとおりです(注:検索入力が必要な場合、アクティビティの切り替えの結果としてブール値の startsearch が設定されます):

public class MyActivity extends Activity {

    private InputMethodManager imm;
    public  boolean startsearch;
    private MenuItem DestinationTxt;
    private SearchView mySearchView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // various initialisation, and then:
        startsearch = false;
        imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.action_menu, menu);     
        DestinationTxt = menu.findItem(R.id.actionbar_search);
        mySearchView = (SearchView)DestinationTxt.getActionView();
        // more menu create stuff appears here      
    }

    @Override
    public void onResume() {
        super.onResume();
        if (startsearch) {
            DestinationTxt.expandActionView();
            imm.showSoftInput(mySearchView, 0);
        }
    }
}

action_menu.xml の関連ビットは

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:id="@+id/actionbar_search"
        android:orderInCategory="1"
        android:showAsAction="always|withText|collapseActionView"
        android:actionViewClass="android.widget.SearchView"
        android:icon="@drawable/earth_2508858_search_en"
        android:inputType="textPostalAddress"
        android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"></item>
</menu>

前述したように、アクティビティが再開されたときにアクション バーの検索がフォーカスされるため、これはほとんど機能します。しかし、(コードからわかるように) 明示的に要求したにもかかわらず、キーボードは表示されません。誰が私が間違っているのか、キーボードを起動するために何をする必要があるのか​​教えてもらえますか?

4

5 に答える 5

6

私は今、これを理解することができました。のコードを見て、InputMethodManager.showSoftInput(View, int)渡したビューが InputMethodManager のアクティブなビューではないため、キーボードを表示する要求が無視されていることがわかりました。

私の問題を解決するために、MyActivityクラスに次の 2 つの新しいフィールドを追加しました。

private EditText search_edit_text;
private boolean mySearchView_editflag;

search_edit_text変数はSearchView mySearchView、実際にフォーカスを取得し、キーボードからの入力を受け取るビューである内のビューになります。はmySearchView_editflag通常 false になりますがtrue、アプリがキーボードを起動する適切なタイミングを待っているときです。

search_edit_textEditText オブジェクトを取得するために、次の関数を使用しました

public static EditText GetEditText(ViewGroup vg) {
    for(int i=0; i< vg.getChildCount(); i++) {
        View v = vg.getChildAt(i);
        if (v instanceof EditText) {
            return (EditText)v;
        } else if (v instanceof ViewGroup) {
            EditText et = GetEditText((ViewGroup)v);
            if (et != null) return et;
        }
    }       
    return null;
}

私のonCreateOptionsMenu(Menu)機能を次のように変更しました

DestinationTxt = menu.findItem(R.id.actionbar_search);
mySearchView = (SearchView)DestinationTxt.getActionView();
search_edit_text = GetEditText(mySearchView);
mySearchView_editflag = false;

これにより、変数search_edit_textmySearchView_editflag変数が初期化されます。私のonResume()方法はに変更されました

@Override
public void onResume() {
    super.onResume();
    if (startsearch) {
        DestinationTxt.expandActionView();
        mySearchView_editflag = true;
    }
}

そして、次のメソッドを高頻度で呼び出すコードを含めました。

public void CheckStatus() {
    if (mySearchView_editflag && imm.isActive(search_edit_text)) {
        imm.showSoftInput(search_edit_text, 0);
        mySearchView_editflag=false;
    }
}

このアプリは、アクションバーでの検索入力が必要なときにアクティビティ スイッチに続いて、キーボードが表示されていることを確認するために呼び出す前にimm.isActive(search_edit_text)true (オブジェクトが入力を受信して​​いることを意味します) になるまで待機するため、希望どおりに動作するようになりました。 .EditTextimm.showSoftInput(search_edit_text, 0)

これらすべてを解決するために、InputMethodManager.showSoftInput(View, int, ResultReceiver)代わりにを使用しました。InputMethodManager.showSoftInput(View, int)

imm.showSoftInput(search_edit_text, 0);

私が持っていた

ImmResultsReceiver irr = new ImmResultsReceiver();
imm.showSoftInput(search_edit_text, 0, irr);

ImmResultsReceiverクラスはどこですか

public class ImmResultsReceiver extends ResultReceiver {        
    public ImmResultsReceiver() { super(null); }        
    @Override
    protected void onReceiveResult (int resultCode, Bundle resultData) {
        String descrip;
        switch(resultCode) {
            case InputMethodManager.RESULT_UNCHANGED_SHOWN: descrip = "RESULT_UNCHANGED_SHOWN"; break;
            case InputMethodManager.RESULT_UNCHANGED_HIDDEN: descrip = "RESULT_UNCHANGED_HIDDEN"; break;
            case InputMethodManager.RESULT_SHOWN: descrip = "RESULT_SHOWN"; break;
            case InputMethodManager.RESULT_HIDDEN: descrip = "RESULT_HIDDEN"; break;
            default:descrip="InputMethodManager("+resultCode+")"; break;
        }
        Log.d("MyLog", "ImmResultsReceiver,"+descrip+","+(resultData == null?"":"resultData.size()="+resultData.size()));
    }               
}

メソッドが呼び出されない場合は、渡されたビューがInputMethodManager のアクティブなビューではないため、ImmResultsReceiver.onReceiveResult(...)への呼び出しが無視されたことを意味します。InputMethodManager.showSoftInput(...)InputMethodManager.showSoftInput(...)

于 2013-06-02T12:25:37.693 に答える
2

マニフェスト ファイル内で、MyActivityアクティビティ セクションに次を追加して、アクティビティの開始時にキーボードを表示してみてください。

android:windowSoftInputMode="stateVisible"

これにより、アクティビティの開始時にキーボードが表示されるようになります。

編集

次に、これを内部で試してくださいonCreateOptionsMenu..

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.action_menu, menu);
    MenuItem menu_search = menu.findItem(actionbar_search);


    menu_search.setOnActionExpandListener(new OnActionExpandListener() {
        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            // Do something when collapsed
            return true;  // Return true to collapse action view
        }

        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            //get focus
            item.getActionView().requestFocus();
            //get input method
            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
            return true;  // Return true to expand action view
        }
    });
    return true;
}
于 2013-06-01T14:11:35.040 に答える
0

私の最後の入力への追記。トグルを postDelayed する前に、InputMethodManager.isActive() で false をチェックしました。350ミリ秒後に適用されなくなったことを除いて、すべて順調です。したがって、postDelayed で、遅延コードが実行されるときに、InputMethodManager.isActive() を再度確認します。true の場合は、showSoftInput だけを切り替えないでください。そうしないと、新しく表示されたキーボードが消えてしまいます。これは、まったく望んでいるものではありません。

于 2015-08-05T17:41:16.367 に答える
0

おっと、元のスレッドではなく、関連するスレッドに追記を投稿したと思いますが、私が話しているのは、たとえば電話によってアプリがバックグラウンドに強制されたとき、および明示的に見つけた場合でも戻ってきたときです。フォーカスを持っていた EditText は、ソフト キーボードを起動しようとしても起動しません。そこで、トグルの投稿について読んだ後に採用したコードのスニペットを次に示します...

ここで参照されている「O」は、アプリで使用する静的オブジェクトの単なるクラスであり、imeListener は、Fragments に何が起こっているかを伝えるために使用するコールバックであることに注意してください...

    if (O.mInputMethodManager.isActive()) {
        if (imeListener != null) {
            O.mInputMethodManager.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT,
                    new ResultReceiver(handler) {
                        protected void onReceiveResult(int resultCode, Bundle resultData) {
                            if (resultCode == InputMethodManager.RESULT_SHOWN || resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN) {
                                imeListener.onSoftKeyboardShown(filenameEditText);
                            }
                        }
                    }
            );
        }
        else {
            O.mInputMethodManager.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
        }
    }
    else { // there will be a slight delay...
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (!O.mInputMethodManager.isActive()) { // come right?
                    O.mInputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
                }
                if (imeListener != null) {
                    O.mInputMethodManager.showSoftInput(filenameEditText, InputMethodManager.SHOW_IMPLICIT,
                            new ResultReceiver(handler) {
                                protected void onReceiveResult(int resultCode, Bundle resultData) {
                                    if (resultCode == InputMethodManager.RESULT_SHOWN || resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN) {
                                        imeListener.onSoftKeyboardShown(filenameEditText);
                                    }
                                }
                            }
                    );
                } else {
                    O.mInputMethodManager.showSoftInput(filenameEditText, InputMethodManager.SHOW_IMPLICIT);
                }
            }
        }, 350);
    }
于 2015-08-07T01:44:45.277 に答える
0

This is an old question, but I ran into a similar problem where the view has focus, but is not active in the InputMethodManager. I took a queue from some of the answers above by simply adding a delay after requestFocus(). Since I'm using Kotlin, I used a coroutine to implement the delay. That way we are not blocking the main thread. Relevant code is shown below.

Class SomeActivity : AppCompatActivity(), CoroutineScope {

    // Create a coroutine job
    private val job = Job()

    // Implement CoroutineScope
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

    // Cancel the job when the activity is destroyed
    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }

    // Shows the keyboard when view has focus
    private fun showKeyboard(view: View) {
        // start a coroutine
        launch {
            withContext(Dispatchers.Main) {
                // add delay of 300ms
                delay(300)
                if (currentFocus == view) {
                    // show the keyboard if view still has focus
                    (getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
                        .showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
                }
            }
        }
    }

}
于 2019-12-30T20:31:30.343 に答える