清除视图中可能具有焦点的所有元素的焦点(likeEditText
-或-
TextView
,其
textIsSelectable="true"
和文本在其中发生clearFocus事件时被选中) . 为什么要问(以防我没有得到上述的一般答复):
我有
很少的片段可以通过导航视图访问。我的主要目标是在导航视图中失去抽屉打开时片段中元素的焦点。我知道可以获取 NavigationDrawer 的 onDrawerSlide
方法,并且实际上已在我的 MainActivity 中设置它,以便在抽屉打开时,如果我的片段之一中的 EditText 打开,我会调用 hideSoftKeyboard 代码,以便它关闭软键盘。
我的代码获取打开抽屉事件
:(在MainActivity的onCreate()方法中)
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
{
//Hide SoftKeyboard on Navigation Drawer Open
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
//Hide SoftKeyboard if it is open
hideSoftKeyboard();
//And Make any view having focus loose focus
//...
//ClearFocus for the whole view is done from here (for whichever Fragment is visible right now)
super.onDrawerSlide(drawerView, slideOffset);
}
};
public void hideSoftKeyboard() //Declared outside onCreate
{
InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
在这里,我的 hideSoftKeyboard() 代码是
generic 并且 可以关闭 SoftKeyboard,无论此时从 MainActivity 本身可见什么 Fragment 。 类似地我想清除所有EditTexts和TextView的焦点(因为打开抽屉时复制/粘贴选项会显示在抽屉中间)。 我知道我可以为每个片段编写代码,调用 onDrawerSlide 函数并单独清除每个元素的焦点,但我想知道是否可以使用通用解决方案,如果可以,如何做到这一点。
(如果可能的话,这可能会产生很多影响,并且在很多情况下可能会有所帮助)
onDrawerSlide
。事实证明,即使这也有点棘手,因为您需要访问工具栏并使用当前抽屉设置抽屉,并且进行一些实验就会引发 NPE! (只是我平常的运气)当我在浏览官方 Android 开发者网站以获取任何见解时,我突然想到了这一点。为什么不使用
getCurrentFocus
来获取我当前的视图,然后使用 clearFocus()
!瞧,它有效。我过于关注复杂的情况,以至于忘记检查简单的部分。
所以这是我自己问题的答案:(在 MainActivity 的 onCreate 中)
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
{
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
hideSoftKeyboard();
getCurrentFocus().clearFocus(); //clear focus - any view having focus
super.onDrawerSlide(drawerView, slideOffset);
}
感谢@keivan Esbati 指出了一个漏洞,由于我使用了虚拟视图(在布局 xml 中使用,因此一旦加载布局,第一个 EditText 就不会获得焦点),我没有注意到这个漏洞。根据 Android 开发者论坛:
clearFocus() :当视图清除焦点时,框架会尝试给予焦点 到从顶部开始的第一个可聚焦视图。因此,如果这个视图是 首先从顶部可以获取焦点,然后是所有相关的回调 清除焦点将被调用,之后框架将给出 关注此视图。
。要从视图中清除焦点,您可以调用对此的一个迂回做法当然是设置一个虚拟变量,该变量在加载布局后立即调用焦点(我使用的方法)或@keivan 共享的
this
EditText
,它将再次获得焦点。
确保视图不会再次获得焦点的一种方法是将此属性添加到 xml 中的根视图中,使根视图能够捕获焦点:
android:focusableInTouchMode="true"
android:descendantFocusability="beforeDescendants"
因此,如果您像下面这样声明根元素,它将在到达子视图之前自动捕获焦点:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusableInTouchMode="true"
android:descendantFocusability="beforeDescendants">
<!-- Rest of Layout -->
<.../>
</LinearLayout>
如果您有多项活动,并且在这些活动中只有一项活动您有导航视图。在这种情况下,如果您想清楚地关注 navView,请使用此代码,
@Override
protected void onResume() {
super.onResume();
int size = navigationView.getMenu().size();
for (int i = 0; i < size; i++) {
navigationView.getMenu().getItem(i).setChecked(false);
}
}
您可以将 checkable="false" 添加到所有您不想获得焦点的项目
<item
android:icon="@drawable/ic_search"
android:id="@+id/nav_search_apps"
android:checkable="false"
android:title="Search Apps"/>
我们也可以通过编程来完成此操作
navView.menu.findItem(R.id.nav_search_apps).isCheckable = false