即使明确要求也不会出现Android键盘

问题描述 投票:1回答:5

我有一个包含两个活动的应用程序,有时,我需要切换活动,同时在刚恢复的活动的操作栏中打开搜索输入。一切正常,除了我无法拨动键盘。我的代码的相关位如下(注意:如果需要搜索输入,则由于切换活动而将布尔值startsearch设置为true):

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>

正如我说的那样,这在大多数情况下都是可行的,因为在活动恢复时,操作栏搜索确实会获得焦点。但是,键盘没有出现,尽管(我从代码中可以看到)我已经明确要求了它。谁能告诉我我做错了什么,以及让键盘升起我需要做什么?

android android-actionbar android-keypad android-search
5个回答
4
投票

我现在已经能够解决这个问题。通过查看InputMethodManager.showSoftInput(View, int)的代码,我发现我提出键盘的请求被忽略了,因为我传递的视图不是InputMethodManager的活动视图。

为了解决我的问题,我向MyActivity类添加了两个新字段,即:

private EditText search_edit_text;
private boolean mySearchView_editflag;

search_edit_text变量将是SearchView mySearchView内部的视图,该视图实际上是获得焦点并从键盘接收输入的视图。 mySearchView_editflag通常为假,但在应用程序等待正确的时间打开键盘时为true

为了掌握search_edit_text EditText对象,我使用了以下功能

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)为真(这意味着EditText对象正在接收输入),然后调用imm.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()));
    }               
}

如果从未调用ImmResultsReceiver.onReceiveResult(...)方法,则意味着对InputMethodManager.showSoftInput(...)的调用已被忽略,因为传递给InputMethodManager.showSoftInput(...)的视图不是InputMethodManager的活动视图。


2
投票

在清单文件中,尝试将以下内容添加到MyActivity活动部分,以在活动开始时显示键盘:

android:windowSoftInputMode="stateVisible"

这应该使键盘在活动开始时变得可见。

edit

然后在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;
}

0
投票

我最后输入的后记。在我延迟切换之前,我检查了InputMethodManager.isActive()是否为false。一切正常,只是在350毫秒后不再应用。因此,在postDelayed中,当延迟的代码运行时,再次检查InputMethodManager.isActive(),如果为true,则不要切换showSoftInput,否则新显示的键盘将消失,这根本不是您想要的。


0
投票

[糟糕,我认为我的帖子是发布到相关主题的,而不是原始主题的,但是,我所说的是,例如当某个应用被电话打入后台并且当它再次返回时,即使您明确找到具有焦点的EditText并尝试调出它根本不会出现的软键盘。因此,这是我在阅读有关发布Toggle之后使用的代码段...

[请注意,此处引用的“ 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);
    }

0
投票

这是一个古老的问题,但是我遇到了一个类似的问题,该视图具有焦点,但是在InputMethodManager中未激活。通过在requestFocus()之后添加一个延迟,我从上面的一些答案中获取了一个队列。由于我使用的是Kotlin,因此我使用了协程来实现延迟。这样我们就不会阻塞主线程。相关代码如下所示。

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

}
© www.soinside.com 2019 - 2024. All rights reserved.