一、问题描述
因为产品是要用遥控器操作的但是又非TV产品,不能使用TV版本的settings,只能对原生的pad版本Settings进行添加焦点选择操作。
在客制化过程中,发现Connected devices页面进去后无法获取到焦点,导致控器操作不起作用。用鼠标点击页面中的一个条目,进入下一级菜单然后再返回,此时是可以用遥控操作的,但是退出到home页面再进入后又不行了。
二、问题分析
在出问题的时候,执行dumpsys activity com.android.settings/.SubSettings,发现focus焦点在recyler_view上,而不是在item上。
正常的时候,执行执行dumpsys activity com.android.settings/.SubSettings,发现focus焦点在item上。
经过各种对比试验,发现问题原因应该是因为Connected devices页面里的条目都是动态构建的,耗时比较长,在view初始focus的时候,条目还没有加载完,所以导致条目无法获取焦点。
三、解决方案
知道问题原因后就好处理了了,可以在条目加载完后重新初始化一次焦点。
具体方案:在切换完fragment后,起一个handler延时300ms去触发系统重新获取焦点,这里用clearFocus()函数来清理掉recyler_view中的焦点,触发系统重新寻找合适的焦点条目。
--- a/Android/packages/apps/Settings/src/com/android/settings/SettingsActivity.java
+++ b/Android/packages/apps/Settings/src/com/android/settings/SettingsActivity.java
@@ -80,9 +80,12 @@ import com.android.settingslib.development.DevelopmentSettingsEnabler;
import com.android.settingslib.drawer.DashboardCategory;
import com.google.android.setupcompat.util.WizardManagerHelper;
+import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
+import android.os.Handler;
+import android.os.Message;
public class SettingsActivity extends SettingsBaseActivity
@@ -176,6 +179,9 @@ public class SettingsActivity extends SettingsBaseActivity
private CharSequence mInitialTitle;
private int mInitialTitleResId;
+ private static String curFragment;
+ private final static int MSG_HANDLE_CLEAR_FOCUS = 1;
+
private BroadcastReceiver mDevelopmentSettingsListener;
private boolean mBatteryPresent = true;
@@ -714,6 +720,15 @@ public class SettingsActivity extends SettingsBaseActivity
transaction.commitAllowingStateLoss();
getSupportFragmentManager().executePendingTransactions();
Log.d(LOG_TAG, "Executed frag manager pendingTransactions");
+
+ curFragment = fragmentName;
+ if (curFragment.equals("com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment")) {
+ mHandler handler = new mHandler();
+ handler.sendEmptyMessageDelayed(MSG_HANDLE_CLEAR_FOCUS, 300);
+ }
+
}
private void updateTilesList() {
@@ -860,4 +875,28 @@ public class SettingsActivity extends SettingsBaseActivity
public Button getNextButton() {
return mNextButton;
}
+
+ class mHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_HANDLE_CLEAR_FOCUS:
+ if (curFragment.equals("com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment")) {
+ View focus = getCurrentFocus();
+ if(focus != null){
+ int listRootId = R.id.recycler_view;
+ if(listRootId == focus.getId()){
+ RecyclerView frv = (RecyclerView)findViewById(listRootId);
+ frv.clearFocus();
+ }
+ } else {
+ }
+ }
+ break;
+ }
+ }
+ }
+