1.首先通过layout inspector 获取页面布局情况;
定位到对应的Fragment 和activity
android\packages\apps\Settings\src\com\android\settings\homepage\TopLevelSettings.java
android\packages\apps\Settings\src\com\android\settings\homepage\SettingsHomepageActivity.java
初步推断可能是对应的item没有配置setFocusable(true)导致的;
但是Preference解析里面没有配置Focusable的属性(TopLevelSettings <--- DashboardFragment <---------SettingsPreferenceFragment)
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import android.view.View;
import android.graphics.Color;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
=======================================================================
android\packages\apps\Settings\src\com\android\settings\SettingsPreferenceFragment.java
=======================================================================
RecyclerView mRecyclerView1;
protected void onDataSetChanged() {
highlightPreferenceIfNeeded();
updateEmptyView();
Log.e(TAG,"=============onDataSetChanged=============="+(mRecyclerView1==null));
if (mRecyclerView1 == null){
mRecyclerView1= getActivity().findViewById(R.id.recycler_view);
Log.e(TAG,"=============findViewById=============="+(mRecyclerView1==null));
}
if (mRecyclerView1 !=null){
Log.e(TAG,"mRecyclerView getChildCount="+mRecyclerView1.getChildCount());
mRecyclerView1.setFocusable(false);
mRecyclerView1.setFocusableInTouchMode(false);
mRecyclerView1.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
for (int i=0;i<mRecyclerView1.getChildCount();i++){
View view= mRecyclerView1.getChildAt(i);
view.setFocusable(true);
view.setFocusableInTouchMode(true);
//view.setBackgroundColor(Color.GREEN);
// if (i==0) {
// view.requestFocus();
// view.setBackgroundColor(Color.GREEN);
// }
}
}
}
测试无效,初步排除是因为item没有配置焦点属性所致;
再看android\packages\apps\Settings\res\layout\settings_homepage_container.xml 布局
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<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"
android:descendantFocusability="blocksDescendants">
<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">
<include layout="@layout/search_bar"/>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
那么基本可以确定是因为 android:descendantFocusability="blocksDescendants"属性导致的了
该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。
属性的值有三种:
beforeDescendants:viewgroup会优先其子类控件而获取到焦点
afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点
改为afterDescendants 重新打包发现确实因为该属性导致的
Toolbar按键无法获取焦点和触发点击事件
Index: android/packages/apps/Settings/src/com/android/settings/homepage/SettingsHomepageActivity.java
===================================================================
@@ -36,6 +36,8 @@
import com.android.settings.core.HideNonSystemOverlayMixin;
import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
import com.android.settings.overlay.FeatureFactory;
+import android.view.KeyEvent;
+import android.graphics.Color;
public class SettingsHomepageActivity extends FragmentActivity {
@@ -91,4 +93,25 @@
final int paddingTop = searchBarHeight + searchBarMargin * 2;
view.setPadding(0 /* left */, paddingTop, 0 /* right */, 0 /* bottom */);
}
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ View view=getCurrentFocus();
+ if (view !=null){
+ //view.setBackgroundColor(Color.GREEN);
+ //android.util.Log.e("TAG","getId="+view.getId());
+ //android.util.Log.e("TAG","search_bar getId="+R.id.search_bar);
+ //android.util.Log.e("TAG","keyCode ="+keyCode);
+ if (view.getId() == R.id.search_action_bar || view.getId() == R.id.search_bar) {
+ if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
+ findViewById(R.id.homepage_container).requestFocus();
+ }else if ( keyCode == KeyEvent.KEYCODE_ENTER) {
+ Toolbar toolbar = findViewById(R.id.search_action_bar);
+ toolbar.performClick();
+ }else if ( keyCode == KeyEvent.KEYCODE_BACK) {
+ finish();
+ }
+ return false;
+ }
+
+ }
+ return super.onKeyDown(keyCode, event);
+ }
}
\ No newline at end of file
Index: android/packages/apps/Settings/res/layout/settings_homepage_container.xml
===================================================================
@@ -34,7 +34,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:descendantFocusability="blocksDescendants">
+ android:descendantFocusability="afterDescendants">
<FrameLayout
android:id="@+id/contextual_cards_content"
Index: android/packages/apps/Settings/res/layout/search_bar.xml
===================================================================
@@ -22,7 +22,10 @@
style="@style/SearchBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- app:layout_scrollFlags="scroll|enterAlways">
+ app:layout_scrollFlags="scroll|enterAlways"
+ android:touchscreenBlocksFocus="false"
+ android:focusable="true"
+ android:focusableInTouchMode="true">
<Toolbar
android:id="@+id/search_action_bar"
android:layout_width="match_parent"
@@ -30,7 +33,10 @@
android:layout_marginStart="-2dp"
android:background="@drawable/search_bar_selected_background"
android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset"
- android:navigationIcon="@drawable/ic_homepage_search">
+ android:navigationIcon="@drawable/ic_homepage_search"
+ android:touchscreenBlocksFocus="false"
+ android:focusable="true"
+ android:focusableInTouchMode="true">
<TextView
android:id="@+id/search_action_bar_title"
style="@style/TextAppearance.SearchBar"