• Android 修复在 Settings 首页,按键盘方向键逐个单选


    Android 修复在 Settings 首页,按键盘方向键逐个单选

    问题现象

    在 Settings 主界面,按键盘方向键上下会直接整个选中,无法单条选中变色,而在二级页面中按方向键上下是正常的。

    没有遥控器可以通过 adb 指令模拟下键

    adb shell input keyevent 20

    在这里插入图片描述

    问题分析

    Settings 中都是用的 Preference 控件来显示界面的,既然二级页面可以,主界面不行的话,那应该是主界面布局有问题。

    盲猜和焦点占用有关系,找到主界面布局文件 settings_homepage_container.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/settings_homepage_container"
        android:fitsSystemWindows="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
    	<androidx.core.widget.NestedScrollView
            android:id="@+id/main_content_scrollable_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior"> 
    
            <LinearLayout
                android:id="@+id/homepage_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">
    
                <FrameLayout
                    android:id="@+id/contextual_cards_content"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="@dimen/contextual_card_side_margin"
                    android:layout_marginEnd="@dimen/contextual_card_side_margin"/>
    
                <FrameLayout
                    android:id="@+id/main_content"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:animateLayoutChanges="true"
                    android:background="?android:attr/windowBackground"/>
    
          </LinearLayout>
        </androidx.core.widget.NestedScrollView>
    
        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:touchscreenBlocksFocus="false"
            android:keyboardNavigationCluster="false">
            <include layout="@layout/search_bar"/>
        </com.google.android.material.appbar.AppBarLayout>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    可以看到主界面加载的 Preference 最终都是在 main_content 中

    层级结构
    NestedScrollView
    LinearLayout
    FrameLayout
    Preference

    经过验证发现,焦点被最外层 NestedScrollView 处理了,无法传递到 Preference 中,所以就无法单条选中

    分析了下 PreferenceScreen 本身就具有屏幕显示不全时可滚动的机制,

    谷歌在这最外面又包了一个 NestedScrollView 岂不是多此一举,其实不是这样的,是因为里面还有其它数据,

    看到 contextual_cards_content 这个,是用来装 Suggestion 菜单的,为了整体能够滚动,所以套了一个 NestedScrollView

    为了事件能过直接被 PreferenceScreen 捕获,

    参考了这篇 https://blog.51cto.com/u_15073486/5363888 发现没啥用,而且还浪费时间。。

    一开始尝试了通过事件传递回调的方式,试了好几种发现都不行(如果你能成功可以反馈给我),

    后来直接将外层的 NestedScrollView 和 LinearLayout 干掉,

    这样做虽然可以让主界面单条选中,但弊端是牺牲了 Suggestion 功能。

    解决办法

    干掉 NestedScrollView,将 homepage_container 和 contextual_cards_content 都设置成 gone,避免编译报错

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/settings_homepage_container"
        android:fitsSystemWindows="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
    <!--     <androidx.core.widget.NestedScrollView
            android:id="@+id/main_content_scrollable_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior"> -->
    
            <LinearLayout
                android:visibility="gone"
                android:id="@+id/homepage_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"/>
    
                <FrameLayout
                    android:visibility="gone"
                    android:id="@+id/contextual_cards_content"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="@dimen/contextual_card_side_margin"
                    android:layout_marginEnd="@dimen/contextual_card_side_margin"/>
    
                <FrameLayout
                    android:id="@+id/main_content"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:animateLayoutChanges="true"
                    android:background="?android:attr/windowBackground"/>
    
           <!--  </LinearLayout>
        </androidx.core.widget.NestedScrollView> -->
    
        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:touchscreenBlocksFocus="false"
            android:keyboardNavigationCluster="false">
            <include layout="@layout/search_bar"/>
        </com.google.android.material.appbar.AppBarLayout>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
  • 相关阅读:
    Vue源码学习(十五):diff算法(二)交叉比对(双指针)
    2023北京市人工智能大模型场景融合与产业发展专场活动盛大召开
    JavaScript sort() 方法你真的了解吗?
    理解记忆相关
    01-RocketMQ整体理解与快速实战
    SpringBoot--WEB技术基础
    Linux centos7安装部署KETTLE-9.3.0
    Ai-WB2-32S在window下使用vs 和 msys2编译以及烧录
    简单易懂的C++类的友元教程(friend)。全局函数做类友元,一个类做另一个类的友元,一个类中某个成员函数做友元。过程中顺序很重要哦。最后附有完整实现代码
    OJ练习第182题——字典树(前缀树)
  • 原文地址:https://blog.csdn.net/u012932409/article/details/132872305