android 7.0中Settings新功能全面解析

Settings N预览

android 7.0中Settings新功能全面解析_第1张图片android 7.0中Settings新功能全面解析_第2张图片

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

  • 增加了侧滑菜单,采用v4下的DrawerLayout来实现;
  • 在Settings主界面增加了Condition,能够在设置列表中显示状态;
  • 在Settings主界面增加了Suggestion。

Dashboard category数据的加载

首先来看下Settings的Dashboard category,dashboard的中文意思指的是仪表板,在Settings中指的是Settings中显示的选项,如WLAN,Bluetooth这样的,参见上面的预览图片。

在android M中,dashboard的加载是放在SettingsActivity中,而且Settings/res/xml/dashboard_categories.xml这个文件专门用来描述dashboard的整体结构,参见下图。
android 7.0中Settings新功能全面解析_第3张图片

在Settings N中,则将dashboard这部分的逻辑抽取了出来,放在/frameworks/base/packages/SettingsLib/目录下。N中不再使用dashboard_categories.xml这个文件来描述Settings各选项的架构,而且将Dashboard的初始化放在SettingsLib中来处理,首先看下面的图片:

Settings AndroidManifest.xml
android 7.0中Settings新功能全面解析_第4张图片

SettingsLib/src/com/android/settingslib/drawer/TileUtils.java

在TileUtils中定义的Actions,用于标记Activity属于哪一个Dashboard category

/**
 * Same as #EXTRA_SETTINGS_ACTION but used for the platform Settings activities.
 */
private static final String SETTINGS_ACTION =
        "com.android.settings.action.SETTINGS";

private static final String OPERATOR_SETTINGS =
        "com.android.settings.OPERATOR_APPLICATION_SETTING";

private static final String OPERATOR_DEFAULT_CATEGORY =
        "com.android.settings.category.wireless";

private static final String MANUFACTURER_SETTINGS =
        "com.android.settings.MANUFACTURER_APPLICATION_SETTING";

private static final String MANUFACTURER_DEFAULT_CATEGORY =
        "com.android.settings.category.device";

Categories定义在Settings/res/values/donottranslate.xml中,分为四个大的Category,如下代码

Settings/res/values/donottranslate.xml

com.android.settings.category.wireless
com.android.settings.category.device
com.android.settings.category.personal
com.android.settings.category.system

TileUtils.java中定义的Meta Data

Name of the meta-data item that should be set in the AndroidManifest.xml
to specify the icon、the title、the summary that should be displayed for the preference.

 public static final String META_DATA_PREFERENCE_ICON = "com.android.settings.icon";

 public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";

  public static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary";

image

Meta data会在AndroidManifest.xml进行配置,在TileUtils.java中加载Dashboard Category的时候,会通过PackageManager获得各个Activity的信息后,再动态的更新到页面上。(另外,我发现对于这些Dashboard的icon,title和Summary有的在AndroidManifest.xml中有配置meta-data有的却没有,我感觉这里应该用的是Activity节点下的icon,title(lablel),这部分如果要彻底搞清楚需要看PackageManager解析AndroidManifest.xml的逻辑,这里不作深究)。

接下来看在TileUtils.java代码中是对于Dashboard是如何处理的
android 7.0中Settings新功能全面解析_第5张图片

上面的getCategories方法主要分为两个部分来看,首先通过PackageManager获得各个Category的信息保存到ArrayList中,接着对ArrayList中的数据按照优先级进行排序,这样主界面拿到这些数据就可以显示了。

Dashboard category的整体布局

android 7.0中Settings新功能全面解析_第6张图片
看上面这幅图,从上而下分别是Condition,Suggestion和各个显示的Item项。

接下来我们来看这部分在代码中是如何构建的?

DashboardAdapter.java中的recountItems方法
private void recountItems() {
        reset();
        boolean hasConditions = false;
        for (int i = 0; mConditions != null && i < mConditions.size(); i++) {
            boolean shouldShow = mConditions.get(i).shouldShow();
            hasConditions |= shouldShow;
            //(1)condition_card.xml
            countItem(mConditions.get(i), R.layout.condition_card, shouldShow, NS_CONDITION);
        }
        boolean hasSuggestions = mSuggestions != null && mSuggestions.size() != 0;
        //(2)dashboard_spacer.xml
        countItem(null, R.layout.dashboard_spacer, hasConditions && hasSuggestions, NS_SPACER);
        //(3)suggestion_header.xml
        countItem(null, R.layout.suggestion_header, hasSuggestions, NS_SPACER);
        resetCount();
        if (mSuggestions != null) {
            int maxSuggestions = getDisplayableSuggestionCount();
            for (int i = 0; i < mSuggestions.size(); i++) {
                 //(3)suggestion_tile.xml
                countItem(mSuggestions.get(i), R.layout.suggestion_tile, i < maxSuggestions,
                        NS_SUGGESTION);
            }
        }
        resetCount();
        for (int i = 0; mCategories != null && i < mCategories.size(); i++) {
            DashboardCategory category = mCategories.get(i);
            //(4)dashboard_category.xml
            countItem(category, R.layout.dashboard_category, mIsShowingAll, NS_ITEMS);
            for (int j = 0; j < category.tiles.size(); j++) {
                Tile tile = category.tiles.get(j);
                //(5)dashboard_tile.xml
                countItem(tile, R.layout.dashboard_tile, mIsShowingAll
                        || ArrayUtils.contains(DashboardSummary.INITIAL_ITEMS,
                        tile.intent.getComponent().getClassName()), NS_ITEMS);
            }
        }
        notifyDataSetChanged();
    }

recountItems方法会在构建布局的时候多次调用,这个方法里面会在这里加入多个layout布局文件。

如上面的代码的注释标明部分

//(1)condition_card.xml
//(2)dashboard_spacer.xml
//(3)suggestion_header.xml
//(4)dashboard_category.xml
//(5)dashboard_tile.xml
 

这里使用countItem方法将各个布局加入到List中去,分别是下面三个集合

private final List mItems = new ArrayList<>();
private final List mTypes = new ArrayList<>();
private final List mIds = new ArrayList<>();
 
  

在将这些布局文件加入到List中去后,然后在onBindViewHolder去获取List中的内容,从而展示在页面上,这部分的逻辑就不再介绍了,大家有兴趣的可以去看看。

Settings Drawer的实现

android 7.0中Settings新功能全面解析_第7张图片

N中的Settings使用DrawerLayout为Settings界面加入了侧滑菜单的功能。我们对比下M平台和N平台的Settings Activity的结构就大概明白了。
android 7.0中Settings新功能全面解析_第8张图片

android N在在SettingsActivity上面构建了一个SettingsDrawerActivity,侧滑的功能则是在SettingsDrawerActivity中实现的,SettingsActivity位于SettingsLib下面。

接下来我们看看SettingsDrawerActivity这个类:
android 7.0中Settings新功能全面解析_第9张图片
在SettingsDrawerActivity的onCreate方法中会加载settings_with_drawer这个文件。这个文件则是对左侧Drawer的布局文件的描述。如下code:


    
    
        
            
        
        
        
    
    
    

接着来看左侧Drawer的ListView的数据是如何加载的,这部分的逻辑由SettingsDrawerAdapter来实现。
android 7.0中Settings新功能全面解析_第10张图片

如上截图,在SettingsDrawerAdapter的updateCategories方法中,添加最上面的home的图片和文件后,然后遍历装有DashboardCategory的集合,取出里面的DashboardCategory和其中的Tile存放到对应的集合中去,用于显示到页面上去。

Settings中的Condition

7.0中的Settings加入的Condition可以显示设置有些item的状态,并且提供快捷开关,在单击后,可以跳转到相应的Settings 页面。

在上文介绍DashboardCategory的整体布局的时候,介绍了Condition部分加载的文件是condition_card.xml文件
android 7.0中Settings新功能全面解析_第11张图片

如上图和xml文件相对应,分别表明了各个控件的id。
condition_card.xml



   

       

           

           

           

       

       

           
           

           
           

           

                

接着来看看Condition的继承层次:
android 7.0中Settings新功能全面解析_第12张图片

我们拿AirplaneModeCondition来举例,在Settings的AndroidManifest.xml中注册了如下的Receiver:


    
         
    

默认情况下这些Condition是关闭的,即enabled的。在这个Receiver中,会去接收这个广播,当Condition的状态改变的时候会去更新状态。

//AirplaneModeCondition.java
@Override
public void refreshState() {
    setActive(WirelessUtils.isAirplaneModeOn(mManager.getContext()));
}

public static class Receiver extends BroadcastReceiver {
   @Override
   public void onReceive(Context context, Intent intent) {
       if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
           ConditionManager.get(context).getCondition(AirplaneModeCondition.class)
                   .refreshState();
       }
   }
}

Settings中的Suggestion

suggestion能够在设置的主页面显示一些建议项,相当于为一些常用的功能界面添加入口,用户通过点击这些建议项可以跳到相应的页面进行操作,并且用户可以手动移除这些建议项。

如下面的截图,Suggestion页面分为两个
suggestion_header.xml和suggestion_tile.xml两个布局组成。
android 7.0中Settings新功能全面解析_第13张图片

关于Suggestion的配置信息:
Suggestion默认的数量为2个,如上图所示,这个常量的设置是在DashboardAdapter.java里面。

 private static final int DEFAULT_SUGGESTION_COUNT = 2;

另外这些Suggestion是以一种顺序来显示的,这个部分的配置是在suggestion_ordering.xml中配置的。


    
    
    
    
    
    

这里会通过SuggestionParser.java中new出来的SuggestionOrderInflater来解析这个文件,Suggestion相关的很多解析操作都是由SuggestionParser.java来处理的。

在SuggestionParser有以下的配置:
android 7.0中Settings新功能全面解析_第14张图片

这个类中定义的常量会在Settings的AndroidManifest.xml使用。
android 7.0中Settings新功能全面解析_第15张图片

如上图中定义的com.android.settings.require_feature的meta-data节点表示该Suggestion的显示需要特定的feature支持,对于FingerprintEnrollSuggestionActivity这个Suggestion的显示则需要指纹的支持。

另外对于META_DATA_DISMISS_CONTROL则控制着当前Suggestion的显示时机。正如上面截图的注释描述。

Allows suggestions to appear after a certain number of days, and to re-appear if dismissed.
For instance:
 0,10
 Will appear immediately, but if the user removes it, it will come back after 10 days.

Another example:
10,30
 Will only show up after 10 days, and then again after 30.
这个属性允许Suggestion在特定的天数后显示,并且在被拒绝后重新显示。

0,10表示该Suggestion会立即显示,但是如果用户删除后,会在10天后再次显示。
10,30则表示在10天后显示,然后在30天之后再次显示。

以上就是对于android7.0Settings的一些新功能的分析,其实这部分还有很多东西没有详细地去分析,这部分只是做了简单的介绍。

另外,再去看源码的时候,发现Google的设计真的是厉害,而且自己很多时候都是从源码的功能去理解,其实从架构,性能方面考虑,源码都是非常优秀的,有很多值得学习的地方。

你可能感兴趣的:(android源码分析)