settings源码路径:packages/app/Settings/
一、settings设置首页
Settings 模块中的 AndroidManifest.xml 文件
<activity android:name=".homepage.SettingsHomepageActivity"
android:label="@string/settings_label_launcher"
android:theme="@style/Theme.Settings.Home"
android:taskAffinity="com.android.settings.root"
android:launchMode="singleTask"
android:configChanges="keyboard|keyboardHidden">
<intent-filter android:priority="1">
<action android:name="android.settings.SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
.....
<!-- Alias for launcher activity only, as this belongs to each profile. -->
<activity-alias android:name="Settings"
android:label="@string/settings_label_launcher"
android:taskAffinity="com.android.settings.root"
android:launchMode="singleTask"
android:targetActivity=".homepage.SettingsHomepageActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts"/>
</activity-alias>
settings的主界面是com.android.settings.Settings,但它是一个activity-alias,指向的是.homepage.SettingsHomepageActivity
activity-alias可用来设置某个Activity的快捷入口,可以放在桌面上或者通过该别名被其他组件快速调起。 android:targetActivity为目标Activity.
从SettingsHomepageActivity.java中可以看出,onCreate()方法加载的layout是settings_homepage_container.xml
在onCreate()方法中调用了showFragment(new TopLevelSettings(), R.id.main_content);
可以看到一级菜单启动的是TopLevelSettings,TopLevelSettings继承于DashboardFragment.java。
TopLevelSettings的构造方法:
public TopLevelSettings() {
final Bundle args = new Bundle();
// Disable the search icon because this page uses a full search view in actionbar.
args.putBoolean(NEED_SEARCH_ICON_IN_ACTION_BAR, false);
setArguments(args);
}
可以看到通过构造方法传递了一个参数,从注释中可以看出,该参数的用意是由于主界面使用完整的搜索视图所以在主界面的actionbar中隐藏了搜索图标。然后再根据framgments生命周期先来看onAttach()方法:
public void onAttach(Context context) {
super.onAttach(context);
use(SupportPreferenceController.class).setActivity(getActivity());
}
调用了父类的onAttach()方法,完成preference controllers的加载,DashboardFragment.java的onCreate()方法:
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
//设置ComparisonCallback,以便在列表更改时获得更好的动画效果。
getPreferenceManager().setPreferenceComparisonCallback(
new PreferenceManager.SimplePreferenceComparisonCallback());
if (icicle != null) {
//在旋转配置更改后,我们需要在执行任何操作之前更新首选项状态
//重新创建编辑对话框(这将在调用onResume之前发生)。
updatePreferenceStates();
}
}
设置ComparisonCallback,以便在列表更改时获得更好的动画效果。
第一次进入时,icicle为null,其后调用Dashboardfragment.java的onCreatePreferences()方法:
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
checkUiBlocker(mControllers);
refreshAllPreferences(getLogTag());
mControllers.stream()
.map(controller -> (Preference) findPreference(controller.getPreferenceKey()))
.filter(Objects::nonNull)
.forEach(preference -> {
//给所有控制器一个处理点击的机会。
preference.getExtras().putInt(CATEGORY, getMetricsCategory());
});
}
调用refreshAllPreferences():
// 刷新所有首选项,包括来自xml的静态首选项和来自DashboardCategory的动态项。
private void refreshAllPreferences(final String tag) {
final PreferenceScreen screen = getPreferenceScreen();
//首先删除旧的首选项。
if (screen != null) {
//有意不要缓存PreferenceScreen,因为它将在稍后重新创建。
screen.removeAll();
}
//添加基于资源的互动程序。
displayResourceTiles();
refreshDashboardTiles(tag);
final Activity activity = getActivity();
if (activity != null) {
Log.d(tag, "All preferences added, reporting fully drawn");
activity.reportFullyDrawn();
}
updatePreferenceVisibility(mPreferenceControllers);
}
刷新所有preference items,包括来自xml的静态preference和来自DashboardCategory的动态preference,静态xml定义的prefs(调用displayResourceTiles()方法),动态DashboardCategory动态加载(调用refreshDashboardTiles(TAG)方法,其中TAG为 “TopLevelSettings”)。
二、静态加载
首先调用getpreferenceScreenResId()方法获取所要加载的xml的id,然后调用子类TopLevelSettings.java的getPerferenceScreenResId()方法,返回主界面top_level-settings,因此settings的主界面加载的是top_level_settings。
主界面主要是一些preference菜单项,如网络、通知、电池、应用等等,Preference的配置含义:
- key:唯一性id;
- title:标题;
- summary:简介;
- ico:图标;
- order:加载显示优先级,order为负数时,绝对值越高
总结
- Settings的主Activity实质实现是在SettingsHomepageActivity.java内;
- Settings的主界面设置item的显示是在fragment上,fragment为TopLevelSettings.java,加载显示的布局为top_level_settings.xml;
- Settings主界面设置项item的加载显示主要分为两部分,一部分是xml定义的静态加载,xml为top_level_settings.xml;一部分是dashboardCategory来获取动态加载;
- 每个设置项item均为一个preference,通过xml定义加载时,必须要有一个controller,可以是在xml中定义“settings:controller”属性声明,名称必须与类的包名路径相同;也可以直接在相关fragment中实现createPreferenceController()方法去调用构造相关controller。此二者存一即可。
- xml中配置preference时,必须定义“android;key”属性。
如果我的文章对您有帮助,还请您多多支持我。支付宝帮忙扫一下吧