【问题标题】:How to remove focus without setting focus to another control?如何在不将焦点设置到另一个控件的情况下移除焦点?
【发布时间】:2011-05-24 23:17:41
【问题描述】:

我喜欢直观的 UI;每个屏幕都应该自然而隐蔽地引导用户进入应用程序的下一步。除此之外,我努力让事情尽可能地令人困惑和困惑。

开个玩笑:-)

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

这是经典的级联值机制;每个选择都会缩小下一个选择的可用选项,等等。因此,我将禁用下每一行上的两个控件,直到当前行上的 EditText 包含一个值。

我需要按照以下优先顺序做两件事之一:

  1. 单击按钮时,立即移除焦点,而不将焦点设置到其他按钮
  2. 在活动开始时将焦点设置到第一个按钮

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

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

Re: 上面的#2 - 我可以使用requestFocus() 将焦点设置到下一行的按钮上,这在子活动返回后有效,但由于某种原因它在父活动的 @ 中不起作用987654325@.

我需要在任一方向上保持 UI 一致性——在子活动完成后没有按钮具有焦点,或者每个按钮根据其在逻辑流中的位置获得焦点,包括在任何按钮之前的第一个(也是唯一的)活动按钮选择。

【问题讨论】:

    标签: android android-layout


    【解决方案1】:

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

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

    到我最顶层的布局视图(线性布局)。要从所有 Buttons/EditTexts 等中移除焦点,您可以这样做

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

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

    【讨论】:

    • 有那么一瞬间,我认为这可能会奏效。 “它的朴素多么美丽!”我对自己说。唉,事实并非如此。即使我删除 requestFocus() 下一行的按钮也会获得焦点。这可以作为第二个偏好,但前提是我可以以某种方式将焦点设置在 onCreate() 中的第一个按钮上。
    • @InteXX:我今天再次遇到这个问题并找到了解决方案。我知道你现在走了一条不同的路,但如果你再次发现自己在同一条船上,试试这个吧!
    • “我知道你现在走的是另一条路”现在备份还为时不晚 :-) 我会试一试并告诉你,谢谢。
    • 该死。差不多,但不完全。是的,它将焦点从最后单击的按钮上移开,但它也会阻止任何按钮获得焦点。这意味着我的非触摸用户将无法单击按钮。它对你也一样吗?
    • 这不适用于 ScrollView。如果您的顶视图是 ScrollView,请在其子视图上使用它。
    【解决方案2】:

    老问题,但当我遇到类似问题并想分享我最终做了什么时,我遇到了这个问题。

    每次获得焦点的视图都不一样,所以我使用了非常通用的:

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

    【讨论】:

    • 优雅的做法。有人可能想在调用 clearFocus() 之前检查 getCurrentFocus() 中的值是否为 null
    • +1 是的,您必须输入空检查! - 为什么Java不能只实现一个安全遍历操作符?就像getCurrentFocus()?.clearFocus(); 一样简单,非常漂亮和优雅:-/
    • @willlma:是的,这正是我的意思。
    • @Levit 非常像 Swift。 :-) 但即使 Java 确实实现了这样的运算符,Android 仍然需要 4 年才能赶上。
    • @Levit,你现在可能已经找到了,但是 Kotlin。
    【解决方案3】:
    1. 您可以使用View.clearFocus()

    2. 使用从onResume()调用的View.requestFocus()

    【讨论】:

    • @siliconeagle:现在这很奇怪。 (顺便说一句,感谢指向 clearFocus() 的指针——我不知道这一点。)当我单击第一个按钮,进行选择,然后返回时,第一个按钮无法再获得焦点。我没有在我的代码中的任何地方为这个按钮设置焦点。我想向您展示我的代码,但此编辑窗口中没有足够的字符可用并且是新手所以我不确定是否应该输入另一个答案才能发布代码。
    • @siliconeagle:不幸的是,clearFocus() 不起作用——当子活动返回时,按钮保持焦点。
    • @siliconeagle:好的,别在意第一条评论。我在按钮的单击事件中使用了 setFocusable(false) 并且在子活动返回后忘记将其重新打开。 clearFocus() 仍然没有效果——我想知道为什么?我在 onActivityResult() 的所有按钮上调用它,但单击的按钮仍保持焦点。奇数。
    • @siliconeagle:@actionshrimp:我决定取消所有与焦点相关的命令和设置。我最初的意图是防止将注意力集中在禁用的按钮上,但如果这是它的成本,那就不值得了。如果没有 requestFocus()、clearFocus() 或 setFocusable(),子活动返回后没有按钮保持焦点。这是两个象鼻虫中较小的一个——我想我将不得不忍受用户能够将焦点设置为禁用按钮。
    • 禁用的元素无法聚焦 AFAIK...使用 setEnabled(false)
    【解决方案4】:

    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 会自动将初始焦点分配给第一个 EditText 或 Activity 中的可聚焦控件。很自然地, InputMethod(通常是软键盘)会响应焦点 事件通过展示自己。中的 windowSoftInputMode 属性 AndroidManifest.xml,当设置为 stateAlwaysHidden 时,指示 键盘忽略这个自动分配的初始焦点。

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

    great reference

    【讨论】:

      【解决方案5】:
      <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"
      

      【讨论】:

        【解决方案6】:

        在清单中的活动中添加android:windowSoftInputMode="stateHidden" 怎么样。

        取自一位对此评论的聪明人:https://stackoverflow.com/a/2059394/956975

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

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

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

            【讨论】:

              【解决方案9】:
              android:focusableInTouchMode="true"
              android:focusable="true"
              android:clickable="true"
              

              将它们添加到包含 EditTextView 的 ViewGroup 中。 它适用于我的约束布局。希望对您有所帮助

              【讨论】:

                【解决方案10】:

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

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

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

                【讨论】:

                • 再想一想...尝试首先使用 View.post() 东西,而不是关闭 Activity 的保存状态。这可能对你们所有人都有效。
                • 唉,我不再有一个简单的方法来为我们测试这个。从那以后,我决定放弃原生代码模型并为移动应用程序使用 HTML5/CSS3,因此我相应地重新调整了我的系统。但是,感谢您提供的似乎非常深入的答案。我投了赞成票。
                【解决方案11】:

                你不需要清除焦点,只需将这段代码添加到你想要焦点的地方

                 time_statusTV.setFocusable(true);
                 time_statusTV.requestFocus();
                 InputMethodManager imm = (InputMethodManager)this.getSystemService(Service.INPUT_METHOD_SERVICE);
                 imm.showSoftInput( time_statusTV, 0);
                

                【讨论】:

                  【解决方案12】:

                  尝试以下方法(致电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();
                      }
                  
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 2012-05-14
                    • 2016-10-22
                    • 1970-01-01
                    • 2014-06-30
                    • 2010-11-25
                    • 2022-12-11
                    • 1970-01-01
                    • 2017-05-08
                    • 1970-01-01
                    相关资源
                    最近更新 更多