如何清除视图中所有可选元素的焦点?

时间:2017-02-26 19:51:13

标签: android focus navigation-drawer android-view

我的问题很简单。如何清除视图中可能具有焦点的所有元素的焦点喜欢 EditText - 或 - TextViewtextIsSelectable="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,但我想知道是否可以使用通用解决方案,如果可以的话,该怎么做。

(如果有可能,可能会有很多含义,可能会在很多情况下有所帮助)

3 个答案:

答案 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);
    }

}