搜索了一些控制规则记录一下
- 默认的焦点控制规则
- 寻焦规则、调用流程(链接)
- Android中的焦点控制方法
- 一、与焦点相关的属性(API 26及以上版本可用)
- 二、在代码中控制焦点的方法
- 三、设置焦点移动方向(已知控件ID的情况下)
- 四、请求焦点的方法
- 五、View和Activity获取焦点的回调
- 六、如何设置View支持聚焦和不支持聚焦,是否所有View都支持焦点?可以做到只获取点击事件不要焦点么?
- 不太懂焦点控制,记录一下,不见的好用
- 在支持遥控器和触摸的 RecyclerView 嵌套场景下内层 item 获取焦点问题分析(豆包分析)
- 参考地址
默认的焦点控制规则
-
布局顺序规则
-
LinearLayout:
- 在垂直方向的LinearLayout中,焦点顺序是按照子View在布局文件中的添加顺序从上到下排列的。例如,以下布局中焦点会从
button1
开始,按顺序转移到button2
和button3
。
<?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:orientation="vertical"> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 1"/> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 2"/> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 3"/> </LinearLayout>
- 在水平方向的LinearLayout中,焦点顺序是从左到右,同样是基于子View的添加顺序。
- 在垂直方向的LinearLayout中,焦点顺序是按照子View在布局文件中的添加顺序从上到下排列的。例如,以下布局中焦点会从
-
RelativeLayout:
- 焦点顺序相对复杂。它会考虑View之间的相对位置和添加顺序等因素。一般先从添加到布局中的较早的可聚焦View开始。如果有明确的相对位置设置,如
android:layout_below
、android:layout_toRightOf
等属性,会影响焦点的转移顺序。例如:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 4"/> <Button android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 5" android:layout_below="@+id/button4"/> </RelativeLayout>
- 在这里,焦点可能先在
button4
上,当按“下”方向键时,由于button5
在button4
的下方,焦点会转移到button5
。
- 焦点顺序相对复杂。它会考虑View之间的相对位置和添加顺序等因素。一般先从添加到布局中的较早的可聚焦View开始。如果有明确的相对位置设置,如
-
FrameLayout和其他布局:
- FrameLayout通常会将焦点给予第一个可聚焦的子View,不过其主要用于堆叠View,焦点规则相对简单。其他布局(如GridLayout等)也有各自基于布局结构和添加顺序的焦点规则。在GridLayout中,焦点通常按照从左到右、从上到下的顺序在单元格中的可聚焦View之间转移。
-
LinearLayout:
-
View类型规则
-
可聚焦和不可聚焦View:
- 像Button、EditText等默认是可聚焦的,而一些用于装饰或者不具有交互功能的View(如普通的TextView,在没有特殊设置下)通常是不可聚焦的。可以通过
android:focusable
属性来设置一个View是否可聚焦。例如,将一个TextView设置为可聚焦:
<TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is a text view" android:focusable="true"/>
- 像Button、EditText等默认是可聚焦的,而一些用于装饰或者不具有交互功能的View(如普通的TextView,在没有特殊设置下)通常是不可聚焦的。可以通过
-
输入框(EditText)特殊规则:
- 当EditText获得焦点时,系统会自动弹出软键盘(如果设备有软键盘且配置为自动弹出)。可以通过在
AndroidManifest.xml
文件中的对应的Activity标签中设置android:windowSoftInputMode
属性来控制软键盘的行为。例如,设置为stateHidden
可以让EditText获得焦点时不弹出软键盘:
<activity android:name=".MainActivity" android:windowSoftInputMode="stateHidden"> </activity>
- EditText在获得焦点后,会有光标闪烁等视觉提示,表示可以进行输入操作。并且在软键盘弹出后,可以通过软键盘上的按键进行文本输入等操作。
- 当EditText获得焦点时,系统会自动弹出软键盘(如果设备有软键盘且配置为自动弹出)。可以通过在
-
按钮(Button)特殊规则:
- 按钮在获得焦点时,会有一个淡淡的焦点边框(具体样式可以通过主题等进行修改)。当用户使用导航键(如方向键)移动焦点时,焦点会按照既定顺序在按钮之间切换,按钮会呈现出被选中的视觉效果,并且可以通过点击确定键(如回车键)来触发按钮的点击事件。
-
可聚焦和不可聚焦View:
-
焦点转移规则
-
通过导航键转移:
- 通常使用导航键(如上下左右方向键)来转移焦点。在触摸屏设备上,如果开启了辅助功能中的方向键导航功能,也可以通过屏幕上虚拟的方向键来控制焦点转移。当用户按下导航键时,焦点会按照布局中定义的顺序或者相对位置关系移动到下一个合适的可聚焦View。如果到达布局的最后一个可聚焦View,再次按下“下”方向键,焦点可能会返回到布局中的第一个可聚焦View(具体行为也可能因设备和系统设置略有不同)。
-
代码控制焦点转移:
- 可以在代码中通过
requestFocus()
方法来让一个View获取焦点。例如,在一个Activity中:
import android.os.Bundle; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.button); button.requestFocus(); } }
- 这里通过
findViewById
找到按钮,然后使用requestFocus
方法让按钮获取焦点。同时,也可以使用clearFocus()
方法来清除一个View的焦点。例如,在某个事件处理方法中:
public void clearButtonFocus(View view) { Button button = findViewById(R.id.button); button.clearFocus(); }
- 可以在代码中通过
-
触摸事件与焦点关系:
- 在触摸屏设备上,当用户点击一个可聚焦的View时,焦点通常会转移到被点击的View。不过,这种行为也可以通过设置
android:clickable
和android:focusable
属性来调整。如果一个View设置为clickable = true
但focusable = false
,那么用户点击它时不会获得焦点,但点击事件仍然会触发。例如:
<Button android:id="@+id/button6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 6" android:clickable="true" android:focusable="false"/>
- 在触摸屏设备上,当用户点击一个可聚焦的View时,焦点通常会转移到被点击的View。不过,这种行为也可以通过设置
-
通过导航键转移:
寻焦规则、调用流程(链接)
https://blog.51cto.com/u_16099225/11818445
在 Android 中,是有一套自己的焦点查找的算法,简单来说,就近原则,就是按方向就近查找下一个符合条件的 View。
寻址调用流程:
不推荐重写 focusSearch() 方法,只使用属性控制也能满足我们的需求。
Android中的焦点控制方法
https://blog.****.net/2401_84537540/article/details/138227635
一、与焦点相关的属性(API 26及以上版本可用)
-
android:focusedByDefault="true"
-
功能:
- 此属性用于指定某个视图(View)在界面加载时自动获取焦点。例如,在一个包含多个按钮的布局中,如果你希望某个特定按钮在界面一显示出来就获得焦点,就可以在该按钮的XML布局定义中添加这个属性。
-
版本兼容性:
- 在Android版本低于26的系统中,使用此属性会导致应用在运行时出现错误。如果你的应用需要兼容低版本系统,就不能使用这个属性。在这种情况下,可以考虑在代码中使用
requestFocus()
方法来实现类似的功能。例如,在Activity
或Fragment
的onCreate
方法中:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.button); button.requestFocus(); } }
- 在Android版本低于26的系统中,使用此属性会导致应用在运行时出现错误。如果你的应用需要兼容低版本系统,就不能使用这个属性。在这种情况下,可以考虑在代码中使用
-
功能:
-
android:defaultFocusHighlightEnabled="true"
-
功能:
- 当这个属性设置为
true
时,原生的Android控件在获取焦点时会显示高亮效果。这种高亮效果可以让用户直观地看到当前哪个控件具有焦点,从而提升用户体验。例如,按钮在获得焦点时可能会显示一个边框或者改变背景颜色等高亮效果。
- 当这个属性设置为
-
版本兼容性:
- 与
android:focusedByDefault="true"
类似,此属性也仅在API 26及以上版本可用。如果在低版本系统中使用,会引发错误。当此属性设置为false
时,相应的控件在获得焦点时将不会显示高亮效果,这在某些特定的界面设计需求下可能会用到,例如为了实现自定义的焦点视觉效果而禁用原生的高亮显示。
- 与
-
功能:
二、在代码中控制焦点的方法
-
setFocusable(boolean focusable)
-
功能:
- 使用
btnTest.setFocusable(true);
这种方式可以在代码中动态地设置一个控件是否能够获得焦点。当focusable
参数为true
时,控件具备获得焦点的能力;当设置为false
时,控件将不能获得焦点。例如,在某些情况下,你可能希望根据用户的操作或者应用的状态来决定某个控件是否可以被聚焦。假设btnTest
是一个按钮,在用户未完成某个前置操作时,你可以将按钮设置为不可聚焦:
public class MainActivity extends AppCompatActivity { private Button btnTest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnTest = findViewById(R.id.btnTest); // 假设用户未登录时按钮不可聚焦 if (!isUserLoggedIn()) { btnTest.setFocusable(false); } } private boolean isUserLoggedIn() { // 这里返回用户是否登录的真实状态 return false; } }
- 使用
-
功能:
-
setFocusableInTouchMode(boolean focusableInTouchMode)
-
功能:
- 此方法用于设置在触摸模式下控件是否能够获得焦点。在一些设备上,特别是那些支持多种交互方式(如遥控器操作和触摸操作)的设备(例如智能电视)上非常有用。例如,当
focusableInTouchMode
设置为true
时,即使在触摸操作模式下,控件也能够获得焦点,这样用户无论是通过遥控器的方向键还是直接触摸屏幕都可以使控件获得焦点。假设你正在开发一个适用于智能电视的应用,并且有一个列表视图(ListView),你希望用户在触摸屏幕时列表项也能获得焦点:
public class MainActivity extends AppCompatActivity { private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = findViewById(R.id.listView); listView.setFocusableInTouchMode(true); } }
- 此方法用于设置在触摸模式下控件是否能够获得焦点。在一些设备上,特别是那些支持多种交互方式(如遥控器操作和触摸操作)的设备(例如智能电视)上非常有用。例如,当
-
功能:
-
setFocusedByDefault(boolean focusedByDefault)
(API 26及以上版本可用)-
功能:
- 与
android:focusedByDefault="true"
属性类似,此方法用于在代码中设置控件是否在界面加载时默认获得焦点。同样,在低版本系统(低于API 26)中使用此方法会出现错误。如果需要在低版本兼容的情况下实现类似功能,可以考虑在Activity
或Fragment
的生命周期方法中使用requestFocus()
方法。例如:
public class MainActivity extends AppCompatActivity { private Button btnTest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnTest = findViewById(R.id.btnTest); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { btnTest.setFocusedByDefault(true); } else { btnTest.requestFocus(); } } }
- 与
-
功能:
-
setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled)
(API 26及以上版本可用)-
功能:
- 用于在代码中设置控件是否显示原生的焦点高亮效果。当
defaultFocusHighlightEnabled
设置为true
时,控件在获得焦点时将显示原生的高亮效果(如果在API 26及以上版本);当设置为false
时,将不显示原生高亮效果。这在你想要自定义焦点视觉效果时非常有用。例如:
public class MainActivity extends AppCompatActivity { private Button btnTest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnTest = findViewById(R.id.btnTest); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { btnTest.setDefaultFocusHighlightEnabled(false); } } }
- 用于在代码中设置控件是否显示原生的焦点高亮效果。当
-
功能:
三、设置焦点移动方向(已知控件ID的情况下)
-
android:nextFocusUp="@id/tv_test"
-
功能:
- 此属性用于在XML布局中定义当用户按下方向键中的“上”键时,焦点应该转移到哪个控件。在上述示例中,当在当前控件上按下“上”键时,焦点将转移到
id
为tv_test
的控件上。这种方式可以帮助你精确地控制焦点在界面中的移动路径,确保用户在使用方向键导航时能够按照你期望的顺序在各个控件之间切换焦点。例如,在一个表单布局中,你可以通过这种方式设置当用户在某个输入框按下“上”键时,焦点转移到上一个相关的输入框或者提示标签上。
- 此属性用于在XML布局中定义当用户按下方向键中的“上”键时,焦点应该转移到哪个控件。在上述示例中,当在当前控件上按下“上”键时,焦点将转移到
-
功能:
-
android:nextFocusDown="@id/tv_test"
-
功能:
- 与
android:nextFocusUp
类似,当用户按下方向键中的“下”键时,焦点将转移到id
为tv_test
的控件。这在垂直排列的多个控件之间控制焦点移动非常有用。例如,在一个垂直排列的按钮组中,通过设置这个属性,可以确保焦点按照按钮的排列顺序从上到下(或从下到上)依次移动。
- 与
-
功能:
-
android:nextFocusLeft="@id/tv_test"
-
功能:
- 当用户按下方向键中的“左”键时,焦点将转移到
id
为tv_test
的控件。在水平排列的控件布局中,这个属性可以帮助你控制焦点在水平方向上的移动。例如,在一个游戏界面中,有多个水平排列的可交互元素,通过设置nextFocusLeft
和nextFocusRight
属性,可以让用户方便地通过方向键在这些元素之间切换焦点。
- 当用户按下方向键中的“左”键时,焦点将转移到
-
功能:
-
android:nextFocusRight="@id/tv_test"
-
功能:
- 当用户按下方向键中的“右”键时,焦点将转移到
id
为tv_test
的控件。与android:nextFocusLeft
属性配合使用,可以完整地控制焦点在水平方向上的移动路径。例如,在一个菜单界面中,有多个水平排列的菜单项,通过合理设置这两个属性,可以让用户通过方向键流畅地在菜单项之间切换焦点,提升用户体验。
- 当用户按下方向键中的“右”键时,焦点将转移到
-
功能:
四、请求焦点的方法
-
requestFocus()
-
功能:
-
requestFocus()
方法是在代码中手动请求焦点的常用方式。它可以应用于各种可聚焦的视图(View)。例如,在一个包含多个输入框(EditText)的表单中,当用户点击某个按钮后,你可能希望特定的输入框立即获得焦点以便用户进行输入。假设editText
是一个输入框,在按钮的点击事件处理方法中可以这样使用:
public class MainActivity extends AppCompatActivity { private EditText editText; private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = findViewById(R.id.editText); button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { editText.requestFocus(); } }); } }
-
-
使用场景和注意事项:
- 此方法在很多场景下都非常有用,比如在界面初始化后引导用户输入、在某些操作完成后将焦点切换到特定控件等。需要注意的是,在一些复杂的布局结构或者存在多个可聚焦控件竞争焦点的情况下,
requestFocus()
的效果可能会受到布局规则和其他相关属性(如focusable
、focusableInTouchMode
等)的影响。如果在调用requestFocus()
后发现焦点没有正确地转移到目标控件,可以检查相关的属性设置和布局结构是否正确。
- 此方法在很多场景下都非常有用,比如在界面初始化后引导用户输入、在某些操作完成后将焦点切换到特定控件等。需要注意的是,在一些复杂的布局结构或者存在多个可聚焦控件竞争焦点的情况下,
-
功能:
-
requestFocusFromTouch()
-
功能:
- 与
requestFocus()
类似,但requestFocusFromTouch()
方法主要用于处理触摸事件相关的焦点请求。在触摸操作模式下,当你希望某个控件在被触摸后获得焦点时,可以使用这个方法。例如,在一个自定义的视图(CustomView)中,当用户触摸该视图时,你希望它获得焦点:
public class CustomView
相关文章
- Android View 的焦点控制基础
- Android学习之基础知识七—碎片的使用
- Android学习之基础知识四-Activity活动3讲(Intent的使用)
- Android学习之基础知识四-Activity活动6讲(体验Activity的生命周期)
- 042 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 04 案例演示while循环的使用——循环输出英文字母
- iOS开发——UI进阶篇(十)导航控制器、微博详情页、控制器的View的生命周期
- 微课程--Android--基础控件的使用
- ios 仿新浪微博 UINavigationController 向左滑动时显示上一个控制器的View.
- SaltStack介绍——SaltStack是一种新的基础设施管理方法开发软件,简单易部署,可伸缩的足以管理成千上万的服务器,和足够快的速度控制,与他们交流
- (Android)View.getHeight或getWidth为0时的一些解决方案
- 与
-
功能: