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

问题描述 投票:0回答:4
我的问题很简单。如何

清除视图中可能具有焦点的所有元素的焦点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 函数并单独清除每个元素的焦点,但我想知道是否可以使用通用解决方案,如果可以,如何做到这一点。

(如果可能的话,这可能会产生很多影响,并且在很多情况下可能会有所帮助)

android focus navigation-drawer android-view
4个回答
11
投票
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

要从视图中清除焦点,您可以调用

9
投票
但请记住,这只会将焦点从当前视图移动到视图中的第一个元素,而不是完全从视图中移除焦点;因此,如果布局中的第一个元素是

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,请使用此代码,

1
投票
@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" 添加到所有您不想获得焦点的项目

0
投票
示例->

<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


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