如何在不将焦点设置到另一个控件的情况下删除焦点?


95

我喜欢界面直观。每个屏幕都应该自然而顺畅地将用户引导至应用程序的下一步。除非如此,否则我将努力使事情变得尽可能混乱和困惑。

开玩笑 :-)

我有3个TableRows,每个s包含一个只读且不可聚焦的EditText控件,然后在其右侧有一个按钮。每个按钮启动相同的活动,但带有不同的参数。用户在那里进行选择,子活动结束,EditText并使用用户的选择填充相应内容。

这是经典的级联价值机制。每个选择都会缩小下一个选择的可用选项,以此类推。因此,我禁用了下一行每一行的两个控件,直到当前行的EditText包含一个值为止。

我需要按照优先顺序执行以下两项操作之一:

  1. 单击某个按钮后,请立即移开焦点,而无需将焦点设置为其他按钮
  2. 活动开始时将焦点设置到第一个按钮

问题在子活动返回后出现;单击的按钮保持焦点。

回复:上面的#1-似乎没有removeFocus()方法或类似的东西

回复:上面的#2-我可以requestFocus()用来将焦点设置到下一行的按钮上,并且在子活动返回后可以使用,但是由于某种原因,它在父活动的中不起作用onCreate()

我需要在两个方向上都具有UI一致性-子活动完成后没有按钮具有焦点,或者每个按钮是否获得焦点取决于其在逻辑流程中的位置,包括在选择之前的第一个(也是唯一的)活动按钮。

Answers:


173

正如您发现的那样,使用clearFocus()似乎对我也不起作用(在注释中看到了另一个答案),但最终对我有用的是添加:

<LinearLayout 
    android:id="@+id/my_layout" 
    android:focusable="true" 
    android:focusableInTouchMode="true" ...>

到我最顶层的布局视图(线性布局)。要从所有Button / EditTexts等中移开焦点,则可以

LinearLayout myLayout = (LinearLayout) activity.findViewById(R.id.my_layout);
myLayout.requestFocus();

除非我将视图设置为可聚焦的,否则请求聚焦没有任何作用。


短暂的一刻,我认为这可能有效。“简单而美丽!” 我对自己说。las,不是。即使当我删除requestFocus()时,下一行的按钮也会获得焦点。作为第二个首选项,这是可以的,但前提是我可以以某种方式将焦点设置在onCreate()中的第一个按钮上。
InteXX

@InteXX:我今天再次遇到了这个问题,找到了解决方案。我知道您现在走了一条不同的路线,但是如果您再次发现自己在同一条船上,请尝试一下!
动作虾

“我知道您现在走了一条不同的路线”备份备份还为时不晚:-)我将尝试一下,谢谢。
InteXX

真是 差不多,但是不完全是。是的,它使焦点从最后单击的按钮上移开,但同时也阻止了任何按钮获得焦点。这意味着我的非触摸用户将无法单击按钮。对你来说也一样吗?
2011年

6
这在ScrollView上不起作用。如果您的顶视图是ScrollView,请在其子视图上使用它。
乌罗什Podkrižnik

79

旧的问题,但是当我遇到类似的问题时,我碰到了这个问题,并认为我会分享自己最终要做的事情。

每次获得关注的观点都不相同,因此我使用了非常通用的观点:

View current = getCurrentFocus();
if (current != null) current.clearFocus();

12
优雅的方式做到这一点。有人可能会想调用clearFocus()之前检查null从getCurrentFocus()的值
Vering

4
+1是,您将必须进行空检查!-为什么Java不能仅实现安全遍历运算符?它会很简单getCurrentFocus()?.clearFocus();,那么漂亮又优雅:-/
Levite

1
@willlma:是的,这正是我的意思。
Vering 2014年

5
@Levit非常像Swift。:-)但是,即使Java确实实现了这种运算符,Android仍需要4年的时间才能赶上。
格雷格·布朗

2
@Levit,到目前为止,您可能已经找到了,但是Kotlin。
prodaea

9
  1. 您可以使用View.clearFocus()

  2. 使用View.requestFocus()来自的调用onResume()


@siliconeagle:现在这非常奇怪。(由于没有指向clearFocus()的指针,所以我没有意识到。)单击第一个按钮,进行选择,然后返回时,第一个按钮不再能获得焦点。我没有在代码中的任何地方设置此按钮的焦点。我想向您展示我的代码,但是在此编辑窗口中没有足够的字符可用,因此对于SO来说是新手,所以我不确定是否应该输入另一个答案才能发布代码。
InteXX

@siliconeagle:不幸的是,clearFocus()不起作用-当子活动返回时,按钮将保持焦点。
InteXX 2011年

@siliconeagle:好的,不要介意第一条评论。我在按钮的click事件中使用了setFocusable(false),却忘记在子活动返回后将其重新打开。clearFocus()仍然没有作用-我想知道为什么吗?我在onActivityResult()的所有按钮上调用它,但是单击的按钮仍然保持焦点。奇。
InteXX

@siliconeagle:@actionshrimp:我决定取消所有与焦点相关的命令和设置。我本来的目的是防止将注意力集中在禁用的按钮上,但是如果这是要花的钱,那是不值得的。没有requestFocus(),clearFocus()或setFocusable(),子活动返回后,没有按钮会保持焦点。它是两个象鼻虫中的较小者-我想我必须忍受用户能够将焦点设置为禁用按钮。
InteXX

禁用的元素不是可聚焦的AFAIK ...使用setEnabled(false)
Siliconeagle

8

android:descendantFocusability="beforeDescendants"

在活动中使用以下内容以及以下一些布局选项似乎可以正常工作。

 getWindow().getDecorView().findViewById(android.R.id.content).clearFocus();

在根视图上结合以下参数。

<?xml
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:descendantFocusability="beforeDescendants" />

https://developer.android.com/reference/android/view/ViewGroup#attr_android:descendantFocusability

回答感谢:https : //forums.xamarin.com/discussion/1856/how-to-disable-auto-focus-on-edit-text

关于windowSoftInputMode

还有另一点需要注意。默认情况下,Android会自动将初始焦点分配给Activity中的第一个EditText或可焦点控件。当然,InputMethod(通常是软键盘)将通过显示自身来响应焦点事件。设置为stateAlwaysHidden时,AndroidManifest.xml中的windowSoftInputMode属性指示键盘忽略此自动分配的初始焦点。

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

很好的参考


6
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          android:id="@+id/ll_root_view"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

LinearLayout llRootView = findViewBindId(R.id.ll_root_view);
llRootView.clearFocus();

我已经完成更新配置文件信息并从布局中的EditText移走所有焦点时使用它

====>更新:在父布局内​​容中,我的EditText添加行:

android:focusableInTouchMode="true"


2

首先,它将100%工作........

  1. 创建onResume()方法。
  2. 在此内部,onResume()找到一次又一次聚焦的视图findViewById()
  3. 在此onResume()设置requestFocus()此视图内部。
  4. 在此onResume()设置clearFocus此视图内部。
  5. 进入相同布局的xml,找到要聚焦的顶视图并设置focusabletrue和focusableInTuchtrue。
  6. 在这个里面onResume()找到上面的顶视图findViewById
  7. 在这个里面最后onResume()设置requestFocus()这个视图。
  8. 现在享受……

2

我试图禁用和启用视图的可聚焦性,它对我有用(焦点已重置):

focusedView.setFocusable(false);
focusedView.setFocusableInTouchMode(false);
focusedView.setFocusable(true);
focusedView.setFocusableInTouchMode(true);

1

您可以尝试关闭主要Activity的保存状态的功能(从而使它忘记了哪个控件具有文本以及哪些具有焦点)。您将需要采取其他方式来记住EditText的内容,并在onResume()中重新填充它们。使用startActivityForResult()启动子活动,并在主活动中创建一个onActivityResult()处理程序,该处理程序将正确更新EditText。这样,您可以通过使用myButton.post(new Runnable(){run(){myButton.requestFocus();}})来重新填充EditText的同时,设置要集中在Resume()上的适当按钮。

View.post()方法对于最初设置焦点很有用,因为该runnable将在创建窗口并确定下来之后执行,从而允许焦点机制在那时正常运行。我发现尝试在onCreate / Start / Resume()期间设置焦点通常会遇到问题。

请注意,这是伪代码,未经测试,但这是您可以尝试的方向。


再三考虑……尝试先使用View.post()而不是关闭Activity的保存状态。这可能会自己解决所有问题。
叔叔密码猴子

las,我不再有一种简单的方法可以为我们进行测试。从那以后,我决定放弃本机代码模型,而将HTML5 / CSS3用于移动应用程序,因此相应地重新设计了我的系统。但是,谢谢您提供了非常深入的答案。我投票了。
InteXX 2011年

1
android:focusableInTouchMode="true"
android:focusable="true"
android:clickable="true"

将它们添加到包含EditTextView的ViewGroup中。它可以按照我的约束布局正常工作。希望这个帮助


0

尝试以下方法(调用clearAllEditTextFocuses();

private final boolean clearAllEditTextFocuses() {
    View v = getCurrentFocus();
    if(v instanceof EditText) {
        final FocusedEditTextItems list = new FocusedEditTextItems();
        list.addAndClearFocus((EditText) v);

        //Focus von allen EditTexten entfernen
        boolean repeat = true;
        do {
            v = getCurrentFocus();
            if(v instanceof EditText) {
                if(list.containsView(v))
                    repeat = false;
                else list.addAndClearFocus((EditText) v);
            } else repeat = false;
        } while(repeat);

        final boolean result = !(v instanceof EditText);
        //Focus wieder setzen
        list.reset();
        return result;
    } else return false;
}

private final static class FocusedEditTextItem {

    private final boolean focusable;

    private final boolean focusableInTouchMode;

    @NonNull
    private final EditText editText;

    private FocusedEditTextItem(final @NonNull EditText v) {
        editText = v;
        focusable = v.isFocusable();
        focusableInTouchMode = v.isFocusableInTouchMode();
    }

    private final void clearFocus() {
        if(focusable)
            editText.setFocusable(false);
        if(focusableInTouchMode)
            editText.setFocusableInTouchMode(false);
        editText.clearFocus();
    }

    private final void reset() {
        if(focusable)
            editText.setFocusable(true);
        if(focusableInTouchMode)
            editText.setFocusableInTouchMode(true);
    }

}

private final static class FocusedEditTextItems extends ArrayList<FocusedEditTextItem> {

    private final void addAndClearFocus(final @NonNull EditText v) {
        final FocusedEditTextItem item = new FocusedEditTextItem(v);
        add(item);
        item.clearFocus();
    }

    private final boolean containsView(final @NonNull View v) {
        boolean result = false;
        for(FocusedEditTextItem item: this) {
            if(item.editText == v) {
                result = true;
                break;
            }
        }
        return result;
    }

    private final void reset() {
        for(FocusedEditTextItem item: this)
            item.reset();
    }

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.