Android O Settings界面简介

    在介绍Android O之前,先要介绍Android N的Settings模块,在N上面谷歌对架构做了调整,Settings增加了一个侧滑按钮。

android N Settings中作了一些调整,如上面的截图。

- 增加了侧滑菜单,采用v4下的DrawerLayout来实现;

- Settings主界面增加了Condition,能够在设置列表中显示状态;

- Settings主界面增加了Suggestion

    

    再来看看Android O与N的Setting界面对比:

            (1)去掉7.0增加的侧滑菜单

            (2)去掉了Settings最上面的Condition和Suggestion两个菜单


设置的启动界面: O/packages/apps/Settings/src/com/android/settings/Settings.java

Settings的父类是SettingsActivity,而且其中有很多继承SettingsActivity的内部类,这个地方是很有意思,后续再说,先看下SettingsActivity.java

O/packages/apps/Settings/src/com/android/settings/SettingsActivity.java

SettingsActivity的父类是SettingsDrawerActivity,而SettingsDrawerActivity是在SettingLib中定义

O/frameworks/base/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java

SettingsDrawerActivity名称是沿用N版本的名字,但是侧滑栏功能在O版本上已经移除了,google在这个地方偷了下懒.

  1. SettingsDrawerActivity  
  2.     @Override  
  3.     protected void onCreate(@Nullable Bundle savedInstanceState) {  
  4.         super.onCreate(savedInstanceState);  
  5.         //主要是布局设置  
  6.         super.setContentView(R.layout.settings_with_drawer);  
  7.         mContentHeaderContainer = (FrameLayout) findViewById(R.id.content_header_container);  
  8.   
  9.         Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);  
  10.         if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {  
  11.             toolbar.setVisibility(View.GONE);  
  12.             return;  
  13.         }  
  14.         setActionBar(toolbar);  
  15.     }  
  16.   
  17.   
  18. SettingsActivity  
  19.     @Override  
  20.     protected void onCreate(Bundle savedState) {  
  21.         super.onCreate(savedState);  
  22.        ......   
  23.         //获取的类名,此处获取的可能是在Settings.java中的内部类,或者就是Settings.java  
  24.   
  25.         // Should happen before any call to getIntent()  
  26.         getMetaData();  
  27.         // Getting Intent properties can only be done after the super.onCreate(...)  
  28.         final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);  
  29.         ......  
  30.         final ComponentName cn = intent.getComponent();  
  31.         final String className = cn.getClassName();  
  32.         //mIsShowingDashboard会根据不同的类名布置不同的布局  
  33.         mIsShowingDashboard = className.equals(Settings.class.getName());  
  34.   
  35.         // This is a "Sub Settings" when:  
  36.         // - this is a real SubSettings  
  37.         // - or :settings:show_fragment_as_subsetting is passed to the Intent  
  38.         final boolean isSubSettings = this instanceof SubSettings ||  
  39.                 intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);  
  40.   
  41.         // If this is a sub settings, then apply the SubSettings Theme for the ActionBar content  
  42.         // insets  
  43.         //设置二级界面的主题  
  44.         if (isSubSettings) {  
  45.             setTheme(R.style.Theme_SubSettings);  
  46.         }  
  47.         //布局不同的布置,主要是为了区分一级界面  
  48.         setContentView(mIsShowingDashboard ? R.layout.settings_main_dashboard : R.layout.settings_main_prefs);  
  49.   
  50.         mContent = (ViewGroup) findViewById(R.id.main_content);  
  51.   
  52.         getFragmentManager().addOnBackStackChangedListener(this);  
  53.        ......  
  54.         //跳转到制定的界面  
  55.         launchSettingFragment(initialFragmentName, isSubSettings, intent);  
  56.   
  57.        ......  
  58.     }  

在SettingsActivity的onCreate中去其实会有三个不同布局的加载方向,以下是重点了:

Settings , Settings的内部类 , SubSettings

(a)Settings ---主界面(一级界面)

onCreate函数中会根据类名加载不同的布局,而布尔值:mIsShowingDashboard 就是当前是否为一级界面的判断

[java]  view plain  copy
  1. mIsShowingDashboard = className.equals(Settings.class.getName());  
  2. setContentView(mIsShowingDashboard ?  
  3.         R.layout.settings_main_dashboard : R.layout.settings_main_prefs);  

settings_main_dashboard.xml就很简单了只是一个FrameLayout

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.              android:id="@+id/main_content"  
  4.              android:layout_height="match_parent"  
  5.              android:layout_width="match_parent"  
  6.              />  

在之后的界面跳转即 launchSettingFragment(initialFragmentName, isSubSettings, intent)函数中又做出了区分:

[java]  view plain  copy
  1. void launchSettingFragment(String initialFragmentName, boolean isSubSettings, Intent intent) {  
  2.     if (!mIsShowingDashboard && initialFragmentName != null) {  
  3.         ......  
  4.     } else {  
  5.         // No UP affordance if we are displaying the main Dashboard  
  6.         mDisplayHomeAsUpEnabled = false;  
  7.         // Show Search affordance  
  8.         mDisplaySearch = true;  
  9.         mInitialTitleResId = R.string.dashboard_title;  
  10. p;           //此处是真正显示一级界面的操作  
  11.         switchToFragment(DashboardSummary.class.getName(), null /* args */falsefalse,  
  12.             mInitialTitleResId, mInitialTitle, false);  
  13.     }  
  14. }  

在launchSettingFragment函数中正式加载了设置的一级界面DashboardSummary.java,DashboardSummary是一个Fragment,而内部布局是使用的R.layout.dashboard,dashboard.xml包含了一个自定义的RecyclerView类FocusRecyclerView,此处就不再详细说明了.

(b)Settings的内部类

Settings的内部类的启动一版都是通过activity 中的action属性启动的,而判断的依据也是通过mIsShowingDashboard,加载的布局为R.layout.settings_main_prefs,而settings_main_prefs.xml比dashboard.xml来说就增加了一个switchBar:

[html]  view plain  copy
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.               android:orientation="vertical"  
  3.               android:layout_height="match_parent"  
  4.               android:layout_width="match_parent">  
  5.   
  6.     <LinearLayout  
  7.             android:orientation="vertical"  
  8.             android:layout_height="0px"  
  9.             android:layout_width="match_parent"  
  10.             android:layout_weight="1">  
  11.   
  12.         <com.android.settings.widget.SwitchBar android:id="@+id/switch_bar"  
  13.                   android:layout_height="?android:attr/actionBarSize"  
  14.                   android:layout_width="match_parent"  
  15.                   android:background="@drawable/switchbar_background"  
  16.                   android:theme="?attr/switchBarTheme"  
  17.                 />  
  18.   
  19.         <FrameLayout  
  20.                 android:id="@+id/main_content"  
  21.                 android:layout_width="match_parent"  
  22.                 android:layout_height="match_parent"  
  23.                 />  
  24.   
  25.     </LinearLayout>  
  26.   
  27.     <RelativeLayout /><!--没怎么研究过,此处代码就省略了-->  
  28.   
  29. </LinearLayout>  

Settings的内部类的主体显示内容依然是一个Fragment,而这个Fragment已经在AndroidManifest.xml中定义好了.拿StorageDashboardActivity为例:

[html]  view plain  copy
  1. <activity android:name=".Settings$StorageDashboardActivity"  
  2.         android:label="@string/storage_settings"  
  3.         android:icon="@drawable/ic_settings_storage"  
  4.         android:taskAffinity="com.android.settings"  
  5.         android:parentActivityName="Settings">  
  6.     <intent-filter android:priority="1">  
  7.         <action android:name="android.settings.INTERNAL_STORAGE_SETTINGS" />  
  8.         <action android:name="android.settings.MEMORY_CARD_SETTINGS" />  
  9.         <category android:name="android.intent.category.DEFAULT" />  
  10.     </intent-filter>  
  11.     <intent-filter>  
  12.         <action android:name="android.intent.action.MAIN" />  
  13.         <category android:name="android.intent.category.DEFAULT" />  
  14.         <category android:name="android.intent.category.VOICE_LAUNCH" />  
  15.     </intent-filter>  
  16.     <intent-filter android:priority="5">  
  17.         <action android:name="com.android.settings.action.SETTINGS" />  
  18.     </intent-filter>  
  19.     <meta-data android:name="com.android.settings.category"  
  20.         android:value="com.android.settings.category.ia.homepage" />  
  21.     <meta-data android:name="com.android.settings.title"  
  22.         android:resource="@string/storage_usb_settings" />  
  23.     <meta-data android:name="com.android.settings.FRAGMENT_CLASS"  
  24.         android:value="com.android.settings.deviceinfo.StorageSettings" />  
  25.     <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"  
  26.         android:value="true" />  
  27. </activity>  

这个地方很容易会让人迷糊的,主要是里面的属性太多,看第一眼估计就会晕掉,这些属性是在SettingLib中的O/frameworks/base/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java有用到的,后续有时间的话可以总结一下,TileUtils主要目录加载的工具类.

言归正传,内部类StorageDashboardActivity的Fragment显示内容为:com.android.settings.FRAGMENT_CLASS,即com.android.settings.deviceinfo.StorageSettings
(c)SubSettings

和内部类就很相似了,不过是做了主题的切换:

[java]  view plain  copy
  1. if (isSubSettings) {  
  2.     setTheme(R.style.Theme_SubSettings);  
  3. }  

SubSettings的启动方式是很隐蔽的这里把启动的顺序贴下,各位有时间的话可以自己研究一下:

之前N的启动子界面都是在SubSettings为Activity的,不过O好像换掉了,都是以Settings为Activity

[java]  view plain  copy
  1. android.support.v7.preference.Preference$1.onClick()  
  2. android.support.v7.preference.Preference.performClick()  
  3. com.android.settings.fuelgauge.PowerUsageSummary.onPreferenceTreeClick()  
  4. com.android.settings.dashboard.DashboardFragment.onPreferenceTreeClick()  
  5. android.support.v14.preference.PreferenceFragment.onPreferenceTreeClick()  
  6. com.android.settings.SettingsActivity.onPreferenceStartFragment()  
  7. com.android.settings.SettingsActivity.startPreferencePanel()  
  8. com.android.settings.Utils.startWithFragment()  
  9. com.android.settings.Utils.onBuildStartFragmentIntent()  

   接下来看一看主界面的加载

packages\apps\Settings\src\com\android\settings\dashboard\DashboardSummary.java

DashboardSummary界面很简单,只有一个自定的RecyclerView,这里我们主要看看他的数据是如何加载的

进入DashboardAdapter看加载的数据:

Tile实现了Parcelable接口,DashboardCategory里面包含着Tile,所以我们看看后者如何获取的


DashboardCategory的获取是在DashboardSummary中的updateCategoryAndSuggestion方法中,获取之后在DashboardAdapter设置


在DashboardSummary的onCreate函数中有获取的有两个很重要参数:mDashboardFeatureProvider,mSuggestionFeatureProvider.这两个是主要的数据提供者,mSuggestionFeatureProvider和mDashboardFeatureProvider的数据获取是有所不同的,这里就不再说明mSuggestionFeatureProvider了,重点说明下mDashboardFeatureProvider.

mDashboardFeatureProvider提供的数据是一级菜单如"电池","显示","网络和互联网"等,实现类为DashboardFeatureProviderImpl.java,而DashboardFeatureProviderImpl中的具体的数据是通过函数getTilesForCategory()从CategoryManager获取的.

这里具体的获取过程我就不去深究了,有需要的话可以参考下面这篇博客

https://blog.csdn.net/qq_26825819/article/details/80272644

最后获取的数据是从AndroidManifest.xml中配置的,比如:



配置完之后会在onCategoriesChanged()中进行界面的加载。


二级界面的加载

    以上我们知道第一级菜单是完全动态的加载,但二级菜单则是动态加载和静态xml布局文件,就拿“系统”这项为例。

packages\apps\Settings\AndroidManifest.xml:

[html]  view plain  copy
  1. <activity android:name=".Settings$SystemDashboardActivity"  
  2.                   android:label="@string/header_category_system"  
  3.                   android:icon="@drawable/ic_settings_about">  
  4.             <intent-filter android:priority="-1">  
  5.                 <action android:name="com.android.settings.action.SETTINGS"/>  
  6.             </intent-filter>  
  7.             <meta-data android:name="com.android.settings.category"  
  8.                        android:value="com.android.settings.category.ia.homepage"/>  
  9.             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"  
  10.                        android:value="com.android.settings.system.SystemDashboardFragment"/>  
  11.             <meta-data android:name="com.android.settings.summary"  
  12.                        android:resource="@string/system_dashboard_summary"/>  
  13.         </activity>  

SystemDashboardFragment.java继承DashboardFragment.java。DashboardFragment继承于PreferenceFragment

后者是通过xml文件来进行加载的,它是所有二级界面的基类。

packages\apps\Settings\src\com\android\settings\dashboard\DashboardFragment.java:

1,静态加载部分:

静态加载部分的实现方法为displayResourceTiles()->

[java]  view plain  copy
  1. /** 
  2.     * Displays resource based tiles. 
  3.     */  
  4.    private void displayResourceTiles() {  
  5.     //获取xml布局文件的id(DashboardFragment.java实现该方法)  
  6.        final int resId = getPreferenceScreenResId();  
  7.        if (resId <= 0) {  
  8.            return;  
  9.        }  
  10.        addPreferencesFromResource(resId);  
  11.        final PreferenceScreen screen = getPreferenceScreen();  
  12.     /** 实现布局文件中的子项控件的业务逻辑 
  13.      *  DashboardFragment.java的子类实现getPreferenceControllers()方法,该方法加载继承于AbstractPreferenceController.java的实现业务逻辑类 
  14.      */  
  15.        Collection<AbstractPreferenceController> controllers = mPreferenceControllers.values();  
  16.        for (AbstractPreferenceController controller : controllers) {  
  17.            controller.displayPreference(screen);  
  18.        }  
  19.    }  

addPreferencesFromResource(resId)加载界面的布局


子类会添加Controller,它可以用来控制二级界面中item的显示。

2,动态加载部分:

动态加载部分的实现方法refreshDashboardTiles()->

[java]  view plain  copy
  1. /** 
  2.      * Refresh preference items backed by DashboardCategory. 
  3.      */  
  4.     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)  
  5.     void refreshDashboardTiles(final String TAG) {  
  6.         final PreferenceScreen screen = getPreferenceScreen();  
  7.         /* 获取子项  
  8.          * getCategoryKey()从DashboardFragmentRegistry.PARENT_TO_CATEGORY_KEY_MAP中获取Category值。 
  9.          * 该值通过类名获取 
  10.          * 存:PARENT_TO_CATEGORY_KEY_MAP.put(SystemDashboardFragment.class.getName(), CategoryKey.CATEGORY_SYSTEM); 
  11.          * CATEGORY_SYSTEM = "com.android.settings.category.ia.system"; 
  12.          */  
  13.         final DashboardCategory category =  
  14.                 mDashboardFeatureProvider.getTilesForCategory(getCategoryKey());  
  15.         ... ...  
  16.         // Install dashboard tiles.  
  17.         for (Tile tile : tiles) {  
  18.             ... ...  
  19.             if (mDashboardTilePrefKeys.contains(key)) {  
  20.                 ... ...  
  21.             } else {  
  22.                 // Don't have this key, add it.  
  23.                 final Preference pref = new Preference(getPrefContext());  
  24.                 /*在这里进行绑定,加载 
  25.                  *packages\apps\Settings\src\com\android\settings\dashboard\DashboardFeatureProviderImpl.java->bindPreferenceToTile() 
  26.                  */  
  27.                 mDashboardFeatureProvider.bindPreferenceToTile(getActivity(), getMetricsCategory(),  
  28.                         pref, tile, key, mPlaceholderPreferenceController.getOrder());  
  29.                 mProgressiveDisclosureMixin.addPreference(screen, pref);  
  30.                 mDashboardTilePrefKeys.add(key);  
  31.             }  
  32.             remove.remove(key);  
  33.         }  
  34.         // Finally remove tiles that are gone.  
  35.         for (String key : remove) {  
  36.             mDashboardTilePrefKeys.remove(key);  
  37.             mProgressiveDisclosureMixin.removePreference(screen, key);  
  38.         }  
  39.         mSummaryLoader.setListening(true);  
  40.     }  

该文的Settings加载流程就差不多到这里了。

四,顺便说说

下拉菜单栏时长按设置图标进入设置,在系统项里面会多一个《系统界面调节工具》。那么这是怎么显示和隐藏的了?

frameworks\base\packages\SystemUI\src\com\android\systemui\tuner\TunerService.java

->setTunerEnabled():

[java]  view plain  copy
  1. public static final void setTunerEnabled(Context context, boolean enabled) {  
  2.         //隐藏应用图标,隐藏某个组件启动也可以使用该方法  
  3.         userContext(context).getPackageManager().setComponentEnabledSetting(  
  4.                 new ComponentName(context, TunerActivity.class),  
  5.                 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED  
  6.                         : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,  
  7.                 PackageManager.DONT_KILL_APP);  
  8.     }  


  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 13是Android操作系统的一个版本,通过“settings”可以访问设备的各种设置选项。在Android 13的设置中,用户可以对设备进行个性化的配置和管理。 首先,用户可以在设置中调整设备的显示设置。包括屏幕亮度、分辨率、字体大小等选项,用户可以根据自己的喜好和需求进行调整。此外,还可以设置壁纸、锁屏样式和桌面图标等,为手机带来更好的视觉体验。 其次,用户可以在设置中管理网络连接。可以设置Wi-Fi网络和移动数据的开关,连接到可用的Wi-Fi网络,管理保存的Wi-Fi网络和移动数据的使用情况,以避免流量浪费。此外,还可以进行蓝牙、NFC等无线通信功能的管理。 除此之外,设置还提供了安全和隐私选项。用户可以设置屏幕锁定方式,如图案、密码、指纹等,保护手机中的个人信息。还可以管理应用程序权限,决定哪些应用可以访问相机、麦克风、联系人等敏感信息。 设置还涵盖了音频、电池、存储、应用管理等方面。用户可以调整音量和声音模式、查看电池使用情况、管理内部存储和外部存储设备等。此外,还可以管理应用程序,包括安装、卸载、更新和权限管理等选项。 总而言之,Android 13的设置提供了全面的设备管理选项,用户可以根据自己的需要进行个性化配置和管理。无论是调整显示设置、管理网络连接还是保护个人信息,用户都可以通过设置轻松地完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值