Android系统Settings设置模块

Settings设置模块UI介绍

FrameWork开发之路首先得玩得转系统APP,个人是在Android5.0的基础上进行定制,Settings模块分为两个部分:
packages\app\Settings 下的APP代码部分
frameworks/base/packages/SettingsProvider/ 数据库
frameworks/base/core/java/android/provider/Settings.java
首先从APP代码部分入手,UI界面架构是有3部分组成实现可配置可扩展,先理解PreferenceFragment, PreferenceScreen,PreferenceCategory, Preference的关系,介绍的最详细的就是谷歌官方文档了,参照链接
我这边首先将的是如何自定义PreferenceCategory和自定义Preference,首先来看系统如何来操作的,参考设置存储部分的界面
Android系统Settings设置模块_第1张图片

packages\apps\Settings\src\com\android\settings\deviceinfo\Memory.java就是fragment界面
###fragment核心代码块

@Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        final Context context = getActivity();
        '''preferenceFragment布局文件'''
        addPreferencesFromResource(R.xml.device_info_memory);

       for (StorageVolume volume : storageVolumes) {
            if (mMemoryExts.isAddPhysicalCategory(volume)) {
                addCategory(StorageVolumePreferenceCategory.buildForPhysical(context, volume));
            }
        }
    }

    private void addCategory(StorageVolumePreferenceCategory category) {
        mCategories.add(category);
        '''add多个category模块'''
        getPreferenceScreen().addPreference(category);
        category.init();
    }
对应的XMl,device_info_xml文件内容:

`
 


可以看出默认存储器,遥控存储器,总容量都是作为preference合并到一个category,然后add到preferenceScreen里面,下面来看PreferenceCategory怎么自定义,packages\apps\Settings\src\com\android\settings\deviceinfo下的StorageVolumePreferenceCategory.java

public class StorageVolumePreferenceCategory extends PreferenceCategory {
 private StorageVolumePreferenceCategory(Context context, StorageVolume volume) {
        super(context);

        mVolume = volume;
        mMeasure = StorageMeasurement.getInstance(context, volume);
        mResources = context.getResources();
        mStorageManager = StorageManager.from(context);
        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);

        mCategoryExts = new StorageVolumePreferenceCategoryExts(context, mVolume);
        mCategoryExts.setVolumeTitle(this);
    }

    private StorageItemPreference buildItem(int titleRes, int colorRes) {
        return new StorageItemPreference(getContext(), titleRes, colorRes);
    }

    public void init() {
        final Context context = getContext();
        '''遥控器存储作为自定义的Preference'''
        mUsageBarPreference = new UsageBarPreference(context);
        mUsageBarPreference.setOrder(ORDER_USAGE_BAR);
        addPreference(mUsageBarPreference);
        '''总容量作为自定义的Preference'''
        mItemTotal = buildItem(R.string.memory_size, 0);
        mItemAvailable = buildItem(R.string.memory_available, R.color.memory_avail);
        addPreference(mItemTotal);
        addPreference(mItemAvailable);
        '''各个类别文件存储作为自定义的Preference'''
        mItemApps = buildItem(R.string.memory_apps_usage, R.color.memory_apps_usage);
        mItemDcim = buildItem(R.string.memory_dcim_usage, R.color.memory_dcim);
        mItemMusic = buildItem(R.string.memory_music_usage, R.color.memory_music);
        mItemDownloads = buildItem(R.string.memory_downloads_usage, R.color.memory_downloads);
        mItemCache = buildItem(R.string.memory_media_cache_usage, R.color.memory_cache);
        mItemMisc = buildItem(R.string.memory_media_misc_usage, R.color.memory_misc);

        mItemCache.setKey(KEY_CACHE);

        /** M: CR ALPS01309473, Set storageItem keys.@{*/
        mItemApps.setKey(KEY_APPS);
        mItemDcim.setKey(KEY_DCIM);
        mItemMusic.setKey(KEY_MUSIC);
        mItemDownloads.setKey(KEY_DOWNLOADS);
        mItemMisc.setKey(KEY_MISC);
        /** @} */

        final boolean showDetails = mVolume == null || mVolume.isPrimary();
        if (showDetails) {
            if (showUsers) {
                addPreference(new PreferenceHeader(context, currentUser.name));
            }
           '''Preference 添加到Category的过程'''
            addPreference(mItemApps);
            addPreference(mItemDcim);
            addPreference(mItemMusic);
            addPreference(mItemDownloads);
            addPreference(mItemCache);
            addPreference(mItemMisc);
        }
     }

}

下面看如何自定义各种UI效果的Preference,本质就是自定义View披上一层外套,从简单的入手,音量设置的preference个人认为好理解
\packages\apps\Settings\src\com\android\audioprofile\AudioProfilePreference.java

public class AudioProfilePreference extends Preference {
 public AudioProfilePreference(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);

        mContext = context;

        mInflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        // get the title from audioprofile_settings.xml
         '''Preference属性Title的设置'''
        if (super.getTitle() != null) {
            mPreferenceTitle = super.getTitle().toString();
        }

        // get the summary from audioprofile_settings.xml
          '''Preference属性Summary副标题的设置'''
        if (super.getSummary() != null) {
            mPreferenceSummary = super.getSummary().toString();
        }

        mProfileManager = (AudioProfileManager) context
                .getSystemService(Context.AUDIO_PROFILE_SERVICE);
      '''Preference属性Key本质就是SharedPreference种的Key设置'''
        mKey = getKey();

        mExt = UtilsExt.getAudioProfilePlgin(context);
    }
    '''PreferenceUI效果'''
    @Override
    public View onCreateView(ViewGroup parent) {
        Xlog.d(XLOGTAG, TAG + "onCreateView " + getKey());
        View view = mExt.createView(R.layout.audio_profile_item);

        mCheckboxButton = (RadioButton) mExt
                .getPrefRadioButton(R.id.radiobutton);
        mTextView = (TextView) mExt.getPreferenceTitle(R.id.profiles_text);
        mSummary = (TextView) mExt.getPreferenceSummary(R.id.profiles_summary);
      }

}

看一下Preference的UI xml文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    >

    <LinearLayout android:id="@android:id/widget_frame"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"/>  
        <RadioButton 
            android:id="@+id/radiobutton" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:layout_gravity="center"
            android:orientation="vertical"
            android:focusable="false"/>
     />

哈哈,本质就是自定义View了
还有一个小的知识点:官方文档介绍PreferenceScreen跳转Activity的时候没有介绍到Intent怎么给Activity传值,所以我就贴上这个小的知识点

<PreferenceScreen android:key="toggle_storage_settings"
                      android:title="@string/storage_settings">
            <intent android:action="settings.advanced.fragment"
                    android:targetPackage="com.android.settings">
            <extra android:name="Zhongqi.Shao" android:value="com.android.settings.deviceinfo.Memory"/>
            intent>
    PreferenceScreen> 

到这应该理解Settings UI效果中的每一个元素关系,现在可以看Settings布局UI效果的实现原理

Android系统Settings设置模块_第2张图片

packages\apps\Settings\src\com\android\settings\SettingsActivity.java
启动的Activity是继承SettingsActivity的Settings.java,参见SettingsActivity.onCreate()函数本质就是Framelayout切换Fragment的效

    @Override
    protected void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        '''就是空空的FrameLayout'''
         setContentView(mIsShowingDashboard ?
                R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
           '''中间代码省略'''       
          switchToFragment(DashboardSummary.class.getName(), null, false, false,
                        mInitialTitleResId, mInitialTitle, false);
      }

下面来看packages\apps\Settings\src\com\android\settings\dashboardDashboardSummary.java的代码

private void rebuildUI(Context context) {
        long start = System.currentTimeMillis();
        final Resources res = getResources();

        mDashboard.removeAllViews();
        '''又回到SettingsActivity.getDashboardCategories()'''  
        List categories =
                ((SettingsActivity) context).getDashboardCategories(true);
 }

'''SettingsActivity中getDashboardCategories()实现'''  
public List getDashboardCategories(boolean forceRefresh) {
        if (forceRefresh || mCategories.size() == 0) {
            buildDashboardCategories(mCategories);
        }
        return mCategories;
 }

  private void buildDashboardCategories(List categories) {
        categories.clear();
        '''重点 通过解析xml来实现配置加载fragment'''  
        loadCategoriesFromResource(R.xml.dashboard_categories, categories);
        updateTilesList(categories);
    }



<dashboard-categories
        xmlns:android="http://schemas.android.com/apk/res/android">

    
    <dashboard-category
            android:id="@+id/wireless_section"
            android:title="@string/header_category_wireless_networks" >

        
        <dashboard-tile
                android:id="@+id/wifi_settings"
                android:title="@string/wifi_settings_title"
                android:fragment="com.android.settings.wifi.WifiSettings"
                android:icon="@drawable/ic_settings_wireless"
                />

        
        <dashboard-tile
                android:id="@+id/hetcomm_settings"
                android:icon="@drawable/ic_settings_hetcomm"
                android:title="@string/hetcom_setting_title">
            <intent android:action="com.android.settings.HETCOMM_SETTINGS" />
        dashboard-tile>

        
        <dashboard-tile
                android:id="@+id/bluetooth_settings"
                android:title="@string/bluetooth_settings_title"
                android:fragment="com.android.settings.bluetooth.BluetoothSettings"
                android:icon="@drawable/ic_settings_bluetooth2"
                />

        
        <dashboard-tile
                android:id="@+id/hotknot_settings"
                android:title="@string/hotknot_settings_title"
                android:fragment="com.mediatek.settings.hotknot.HotKnotSettings"
                android:icon="@drawable/ic_settings_hotknot" 
                />

        
        <dashboard-tile
                android:id="@+id/sim_settings"
                android:title="@string/sim_settings_title"
                android:fragment="com.android.settings.sim.SimSettings"
                android:icon="@drawable/ic_sim_sd"
                />

        
        <dashboard-tile
                android:id="@+id/data_usage_settings"
                android:title="@string/data_usage_summary_title"
                android:fragment="com.android.settings.DataUsageSummary"
                android:icon="@drawable/ic_settings_data_usage"
                />

        
        

    dashboard-category>

    
    <dashboard-category
            android:id="@+id/device_section"
            android:title="@string/header_category_device" >

        
        <dashboard-tile
                android:id="@+id/home_settings"
                android:title="@string/home_settings"
                android:fragment="com.android.settings.HomeSettings"
                android:icon="@drawable/ic_settings_home"
                />

        
        <dashboard-tile
                android:id="@+id/display_settings"
                android:title="@string/display_settings"
                android:fragment="com.android.settings.DisplaySettings"
                android:icon="@drawable/ic_settings_display"
                />

        
        <dashboard-tile
                android:id="@+id/notification_settings"
                android:title="@string/notification_settings"
                android:fragment="com.mediatek.audioprofile.AudioProfileSettings"
                android:icon="@drawable/ic_settings_notifications"
                />

        
        
        
        

        
        <dashboard-tile
                android:id="@+id/battery_settings"
                android:title="@string/power_usage_summary_title"
                android:fragment="com.android.settings.fuelgauge.PowerUsageSummary"
                android:icon="@drawable/ic_settings_battery"
                />

        
        <dashboard-tile
                android:id="@+id/application_settings"
                android:title="@string/applications_settings"
                android:fragment="com.android.settings.applications.ManageApplications"
                android:icon="@drawable/ic_settings_applications"
                />

        
        <dashboard-tile
                android:id="@+id/user_settings"
                android:title="@string/user_settings_title"
                android:fragment="com.android.settings.users.UserSettings"
                android:icon="@drawable/ic_settings_multiuser"
                />

        
        <dashboard-tile
                android:id="@+id/nfc_payment_settings"
                android:title="@string/nfc_payment_settings_title"
                android:fragment="com.android.settings.nfc.PaymentSettings"
                android:icon="@drawable/ic_settings_nfc_payment"
                />

        
        

    dashboard-category>

    
    <dashboard-category
            android:id="@+id/personal_section"
            android:title="@string/header_category_personal" >

        
        <dashboard-tile
                android:id="@+id/location_settings"
                android:title="@string/location_settings_title"
                android:fragment="com.android.settings.location.LocationSettings"
                android:icon="@drawable/ic_settings_location"
                />

        
        <dashboard-tile
                android:id="@+id/security_settings"
                android:title="@string/security_settings_title"
                android:fragment="com.android.settings.SecuritySettings"
                android:icon="@drawable/ic_settings_security"
                />

        
        <dashboard-tile
                android:id="@+id/account_settings"
                android:title="@string/account_settings_title"
                android:fragment="com.android.settings.accounts.AccountSettings"
                android:icon="@drawable/ic_settings_accounts"
                />

        
        <dashboard-tile
                android:id="@+id/language_settings"
                android:title="@string/language_settings"
                android:fragment="com.android.settings.inputmethod.InputMethodAndLanguageSettings"
                android:icon="@drawable/ic_settings_language"
                />

        
        <dashboard-tile
                android:id="@+id/privacy_settings"
                android:title="@string/privacy_settings"
                android:fragment="com.android.settings.PrivacySettings"
                android:icon="@drawable/ic_settings_backup"
                />

    dashboard-category>


dashboard-categories>

到这基本UI可以说是过来一遍,下面会来记录我这边是怎么来深度定制

你可能感兴趣的:(FrameWork)