我的问题很简单。如何清除视图中可能具有焦点的所有元素的焦点(喜欢 EditText
- 或 - TextView
其textIsSelectable="true"
并且在出现clearFocus事件时中选择了文本。
为什么要问(如果我没有得到上面的通用回复):
我通过导航视图访问少数片段。我的主要目标是在导航视图中的Drawer open 中失去片段中元素的焦点。我知道有可能为NavigationDrawer获取onDrawerSlide
方法,并在我的MainActivity中设置它,以便在抽屉打开时,如果其中一个片段中的我的EditText打开,我调用hideSoftKeyboard代码以便它关闭SoftKeyboard。
我的代码在打开抽屉时获取事件:(在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()代码是 泛型 ,可以关闭SoftKeyboard,无论目前可从MainActivity本身看到什么片段 。 同样我想所有EditTexts和TextView的清晰焦点(因为复制/粘贴选项在打开时显示在抽屉的中间位置。)
我知道我可以为每个片段编写调用onDrawerSlide函数的代码,并为每个元素单独清除Focus,但我想知道是否可以使用通用解决方案,如果可以的话,该怎么做。
(如果有可能,可能会有很多含义,可能会在很多情况下有所帮助)
答案 0 :(得分:9)
好吧,我终于决定不再等待一般性答案,因此决定为每个片段实施onDrawerSlide
。事实证明,即使这有点棘手,因为您需要访问工具栏并使用当前抽屉设置您的抽屉,并且进行了一些实验就是呕吐NPE! (只是我平常的运气)
当这个闪现给我时,正在通过官方Android开发者网站获取任何见解。为什么不使用getCurrentFocus
来获取当前视图,然后使用clearFocus()
!而且,它很有效。我一直专注于复杂的情况,以至于我忘了查看简单的部分。
所以这是我自己问题的答案:(在onCreate for MainActivity中)
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中使用,因此只要加载Layout,第一个EditText就不会得到焦点)。根据Android开发者论坛:
clearFocus():当一个View清除焦点时,框架正试图给予焦点 到顶部的第一个可聚焦的视图。因此,如果这个视图是 首先从顶部开始可以关注,然后所有回调都与之相关 将调用清除焦点,然后框架将给出 专注于这种观点。
对此进行舍入是设置一个虚拟变量,一旦加载布局(我使用的方法)或@keivan共享的this,就会调用焦点。
注意:我已经为它提供了赏金,因为没有人能够回答我自己得到答案,想知道将会发生什么样的赏金:D
更新:Bounty已过期,嗯,什么也没发生。如果你遵循广告理论,那就猜对了。
答案 1 :(得分:5)
要从视图中清除焦点,您可以调用getCurrentFocus().clearFocus()
但请记住,这将简单地将焦点从当前视图移动到视图中的第一个元素,而不是完全从视图中移除焦点;因此,如果布局中的第一个元素是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>
答案 2 :(得分:1)
如果您有多个活动,并且在这些活动中只有一个活动您拥有导航视图。在这种情况下,如果您想清楚地关注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);
}
}