Settings new dashboard - part 1

- make the Settings dashboard definition be hierarchical (non flat) and use
categories and tiles
- code cleaning: remove mHeaderIndexMap

Change-Id: I16581a736ac5c8388a182d83159161fe3bb04f4b
This commit is contained in:
Fabrice Di Meglio
2014-04-23 16:44:30 -07:00
parent d297a58402
commit 63bbb8e4fe
5 changed files with 969 additions and 3 deletions

View File

@@ -0,0 +1,251 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<dashboard-categories
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- WIRELESS and NETWORKS -->
<dashboard-category
android:id="@+id/wireless_section"
android:title="@string/header_category_wireless_networks" >
<!-- Wifi -->
<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"
/>
<!-- Bluetooth -->
<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"
/>
<!-- Data Usage -->
<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"
/>
<!-- Operator hook -->
<dashboard-tile
android:id="@+id/operator_settings"
android:fragment="com.android.settings.WirelessSettings" >
<intent android:action="com.android.settings.OPERATOR_APPLICATION_SETTING" />
</dashboard-tile>
<!-- Other wireless and network controls -->
<dashboard-tile
android:id="@+id/wireless_settings"
android:title="@string/radio_controls_title"
android:fragment="com.android.settings.WirelessSettings"
/>
</dashboard-category>
<!-- DEVICE -->
<dashboard-category
android:id="@+id/device_section"
android:title="@string/header_category_device" >
<!-- Home -->
<dashboard-tile
android:id="@+id/home_settings"
android:title="@string/home_settings"
android:fragment="com.android.settings.HomeSettings"
android:icon="@drawable/ic_settings_home"
/>
<!-- Sound -->
<dashboard-tile
android:id="@+id/sound_settings"
android:title="@string/sound_settings"
android:fragment="com.android.settings.SoundSettings"
android:icon="@drawable/ic_settings_sound"
/>
<!-- Display -->
<dashboard-tile
android:id="@+id/display_settings"
android:title="@string/display_settings"
android:fragment="com.android.settings.DisplaySettings"
android:icon="@drawable/ic_settings_display"
/>
<!-- Notifications -->
<dashboard-tile
android:id="@+id/notification_settings"
android:title="@string/notification_settings"
android:fragment="com.android.settings.notification.NotificationSettings"
android:icon="@drawable/ic_settings_notifications"
/>
<!-- Storage -->
<dashboard-tile
android:id="@+id/storage_settings"
android:title="@string/storage_settings"
android:fragment="com.android.settings.deviceinfo.Memory"
android:icon="@drawable/ic_settings_storage"
/>
<!-- Battery -->
<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"
/>
<!-- Application Settings -->
<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"
/>
<!-- Manage users -->
<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"
/>
<!-- Manage NFC payment apps -->
<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"
/>
<!-- Manufacturer hook -->
<dashboard-tile
android:id="@+id/manufacturer_settings"
android:fragment="com.android.settings.WirelessSettings">
<intent android:action="com.android.settings.MANUFACTURER_APPLICATION_SETTING" />
</dashboard-tile>
</dashboard-category>
<!-- PERSONAL -->
<dashboard-category
android:id="@+id/personal_section"
android:title="@string/header_category_personal" >
<!-- Location -->
<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"
/>
<!-- Security -->
<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"
/>
<!-- Language -->
<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"
/>
<!-- Backup and reset -->
<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>
<!-- ACCOUNTS section -->
<dashboard-category
android:id="@+id/account_settings"
android:title="@string/account_settings" >
<dashboard-tile
android:id="@+id/account_add"
android:title="@string/add_account_label"
android:icon="@drawable/ic_menu_add_dark">
<intent android:action="android.settings.ADD_ACCOUNT_SETTINGS"/>
</dashboard-tile>
</dashboard-category>
<!-- SYSTEM -->
<dashboard-category
android:id="@+id/system_section"
android:title="@string/header_category_system" >
<!-- Date & Time -->
<dashboard-tile
android:id="@+id/date_time_settings"
android:title="@string/date_and_time_settings_title"
android:fragment="com.android.settings.DateTimeSettings"
android:icon="@drawable/ic_settings_date_time"
/>
<!-- Accessibility feedback -->
<dashboard-tile
android:id="@+id/accessibility_settings"
android:title="@string/accessibility_settings"
android:fragment="com.android.settings.accessibility.AccessibilitySettings"
android:icon="@drawable/ic_settings_accessibility"
/>
<!-- Print -->
<dashboard-tile
android:id="@+id/print_settings"
android:title="@string/print_settings"
android:fragment="com.android.settings.print.PrintSettingsFragment"
android:icon="@*android:drawable/ic_print"
/>
<!-- Development -->
<dashboard-tile
android:id="@+id/development_settings"
android:title="@string/development_settings_title"
android:fragment="com.android.settings.DevelopmentSettings"
android:icon="@drawable/ic_settings_development"
/>
<!-- About Device -->
<dashboard-tile
android:id="@+id/about_settings"
android:title="@string/about_settings"
android:fragment="com.android.settings.DeviceInfoSettings"
android:icon="@drawable/ic_settings_about"
/>
</dashboard-category>
</dashboard-categories>

View File

@@ -76,7 +76,9 @@ import com.android.settings.applications.InstalledAppDetails;
import com.android.settings.applications.ManageApplications;
import com.android.settings.applications.ProcessStatsUi;
import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.dashboard.DashboardCategory;
import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.dashboard.DashboardTile;
import com.android.settings.dashboard.Header;
import com.android.settings.dashboard.HeaderAdapter;
import com.android.settings.dashboard.NoHomeDialogFragment;
@@ -323,10 +325,11 @@ public class SettingsActivity extends Activity
private String mSearchQuery;
// Headers
protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
private final ArrayList<Header> mHeaders = new ArrayList<Header>();
private HeaderAdapter mHeaderAdapter;
private List<DashboardCategory> mCategories = new ArrayList<DashboardCategory>();
private static final int MSG_BUILD_HEADERS = 1;
private Handler mHandler = new Handler() {
@Override
@@ -999,7 +1002,6 @@ public class SettingsActivity extends Activity
int i = 0;
final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
mHeaderIndexMap.clear();
while (i < target.size()) {
Header header = target.get(i);
// Ids are integers, so downcasting
@@ -1075,7 +1077,6 @@ public class SettingsActivity extends Activity
// Increment if the current one wasn't removed by the Utils code.
if (i < target.size() && target.get(i) == header) {
mHeaderIndexMap.put(id, i);
i++;
}
}
@@ -1175,6 +1176,351 @@ public class SettingsActivity extends Activity
return true;
}
/**
* Called when the activity needs its list of categories/tiles build.
*
* @param categories The list in which to place the tiles categories.
*/
private void onBuildDashboardCategories(List<DashboardCategory> categories) {
loadCategoriesFromResource(R.xml.dashboard_categories, categories);
updateTilesList(categories);
}
/**
* Parse the given XML file as a categories description, adding each
* parsed categories and tiles into the target list.
*
* @param resid The XML resource to load and parse.
* @param target The list in which the parsed categories and tiles should be placed.
*/
private void loadCategoriesFromResource(int resid, List<DashboardCategory> target) {
XmlResourceParser parser = null;
try {
parser = getResources().getXml(resid);
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
// Parse next until start tag is found
}
String nodeName = parser.getName();
if (!"dashboard-categories".equals(nodeName)) {
throw new RuntimeException(
"XML document must start with <preference-categories> tag; found"
+ nodeName + " at " + parser.getPositionDescription());
}
Bundle curBundle = null;
final int outerDepth = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
nodeName = parser.getName();
if ("dashboard-category".equals(nodeName)) {
DashboardCategory category = new DashboardCategory();
TypedArray sa = obtainStyledAttributes(
attrs, com.android.internal.R.styleable.PreferenceHeader);
category.id = sa.getResourceId(
com.android.internal.R.styleable.PreferenceHeader_id,
(int)DashboardCategory.CAT_ID_UNDEFINED);
TypedValue tv = sa.peekValue(
com.android.internal.R.styleable.PreferenceHeader_title);
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
if (tv.resourceId != 0) {
category.titleRes = tv.resourceId;
} else {
category.title = tv.string;
}
}
sa.recycle();
final int innerDepth = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String innerNodeName = parser.getName();
if (innerNodeName.equals("dashboard-tile")) {
DashboardTile tile = new DashboardTile();
sa = obtainStyledAttributes(
attrs, com.android.internal.R.styleable.PreferenceHeader);
tile.id = sa.getResourceId(
com.android.internal.R.styleable.PreferenceHeader_id,
(int)HEADER_ID_UNDEFINED);
tv = sa.peekValue(
com.android.internal.R.styleable.PreferenceHeader_title);
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
if (tv.resourceId != 0) {
tile.titleRes = tv.resourceId;
} else {
tile.title = tv.string;
}
}
tv = sa.peekValue(
com.android.internal.R.styleable.PreferenceHeader_summary);
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
if (tv.resourceId != 0) {
tile.summaryRes = tv.resourceId;
} else {
tile.summary = tv.string;
}
}
tile.iconRes = sa.getResourceId(
com.android.internal.R.styleable.PreferenceHeader_icon, 0);
tile.fragment = sa.getString(
com.android.internal.R.styleable.PreferenceHeader_fragment);
sa.recycle();
if (curBundle == null) {
curBundle = new Bundle();
}
final int innerDepth2 = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth2)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String innerNodeName2 = parser.getName();
if (innerNodeName2.equals("extra")) {
getResources().parseBundleExtra("extra", attrs, curBundle);
XmlUtils.skipCurrentTag(parser);
} else if (innerNodeName2.equals("intent")) {
tile.intent = Intent.parseIntent(getResources(), parser, attrs);
} else {
XmlUtils.skipCurrentTag(parser);
}
}
if (curBundle.size() > 0) {
tile.fragmentArguments = curBundle;
curBundle = null;
}
category.addTile(tile);
} else {
XmlUtils.skipCurrentTag(parser);
}
}
target.add(category);
} else {
XmlUtils.skipCurrentTag(parser);
}
}
} catch (XmlPullParserException e) {
throw new RuntimeException("Error parsing categories", e);
} catch (IOException e) {
throw new RuntimeException("Error parsing categories", e);
} finally {
if (parser != null) parser.close();
}
}
private void updateTilesList(List<DashboardCategory> target) {
final boolean showDev = mDevelopmentPreferences.getBoolean(
DevelopmentSettings.PREF_SHOW,
android.os.Build.TYPE.equals("eng"));
final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
final int size = target.size();
for (int i = 0; i < size; i++) {
DashboardCategory category = target.get(i);
// Ids are integers, so downcasting is ok
int id = (int) category.id;
if (id == R.id.account_settings) {
insertAccountsTiles(category);
continue;
}
int n = category.getTilesCount() - 1;
while (n >= 0) {
DashboardTile tile = category.getTile(n);
id = (int) tile.id;
if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
Utils.updateTileToSpecificActivityFromMetaDataOrRemove(this, category, tile);
} else if (id == R.id.wifi_settings) {
// Remove WiFi Settings if WiFi service is not available.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
category.removeTile(n);
}
} else if (id == R.id.bluetooth_settings) {
// Remove Bluetooth Settings if Bluetooth service is not available.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
category.removeTile(n);
}
} else if (id == R.id.data_usage_settings) {
// Remove data usage when kernel module not enabled
final INetworkManagementService netManager = INetworkManagementService.Stub
.asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
try {
if (!netManager.isBandwidthControlEnabled()) {
category.removeTile(n);
}
} catch (RemoteException e) {
// ignored
}
} else if (id == R.id.battery_settings) {
// Remove battery settings when battery is not available. (e.g. TV)
if (!mBatteryPresent) {
category.removeTile(n);
}
} else if (id == R.id.home_settings) {
if (!updateHomeSettingTiles(tile)) {
category.removeTile(n);
}
} else if (id == R.id.user_settings) {
if (!UserHandle.MU_ENABLED
|| !UserManager.supportsMultipleUsers()
|| Utils.isMonkeyRunning()) {
category.removeTile(n);
}
} else if (id == R.id.nfc_payment_settings) {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) {
category.removeTile(n);
} else {
// Only show if NFC is on and we have the HCE feature
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
if (!adapter.isEnabled() || !getPackageManager().hasSystemFeature(
PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
category.removeTile(n);
}
}
} else if (id == R.id.development_settings) {
if (!showDev) {
category.removeTile(n);
}
} else if (id == R.id.account_add) {
if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
category.removeTile(n);
}
}
if (UserHandle.MU_ENABLED && UserHandle.myUserId() != 0
&& !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
category.removeTile(n);
}
n--;
}
}
}
private boolean updateHomeSettingTiles(DashboardTile tile) {
// Once we decide to show Home settings, keep showing it forever
SharedPreferences sp = getSharedPreferences(HomeSettings.HOME_PREFS, Context.MODE_PRIVATE);
if (sp.getBoolean(HomeSettings.HOME_PREFS_DO_SHOW, false)) {
return true;
}
try {
final ArrayList<ResolveInfo> homeApps = new ArrayList<ResolveInfo>();
getPackageManager().getHomeActivities(homeApps);
if (homeApps.size() < 2) {
// When there's only one available home app, omit this settings
// category entirely at the top level UI. If the user just
// uninstalled the penultimate home app candidiate, we also
// now tell them about why they aren't seeing 'Home' in the list.
if (sShowNoHomeNotice) {
sShowNoHomeNotice = false;
NoHomeDialogFragment.show(this);
}
return false;
} else {
// Okay, we're allowing the Home settings category. Tell it, when
// invoked via this front door, that we'll need to be told about the
// case when the user uninstalls all but one home app.
if (tile.fragmentArguments == null) {
tile.fragmentArguments = new Bundle();
}
tile.fragmentArguments.putBoolean(HomeSettings.HOME_SHOW_NOTICE, true);
}
} catch (Exception e) {
// Can't look up the home activity; bail on configuring the icon
Log.w(LOG_TAG, "Problem looking up home activity!", e);
}
sp.edit().putBoolean(HomeSettings.HOME_PREFS_DO_SHOW, true).apply();
return true;
}
private void insertAccountsTiles(DashboardCategory target) {
String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
List<DashboardTile> dashboardTiles = new ArrayList<DashboardTile>(accountTypes.length);
for (String accountType : accountTypes) {
CharSequence label = mAuthenticatorHelper.getLabelForType(this, accountType);
if (label == null) {
continue;
}
Account[] accounts = AccountManager.get(this).getAccountsByType(accountType);
boolean skipToAccount = accounts.length == 1
&& !mAuthenticatorHelper.hasAccountPreferences(accountType);
DashboardTile accountTile = new DashboardTile();
accountTile.title = label;
if (accountTile.extras == null) {
accountTile.extras = new Bundle();
}
if (skipToAccount) {
accountTile.fragment = AccountSyncSettings.class.getName();
accountTile.fragmentArguments = new Bundle();
// Need this for the icon
accountTile.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
accountTile.extras.putParcelable(AccountSyncSettings.ACCOUNT_KEY, accounts[0]);
accountTile.fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
accounts[0]);
} else {
accountTile.fragment = ManageAccountsSettings.class.getName();
accountTile.fragmentArguments = new Bundle();
accountTile.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
accountTile.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE,
accountType);
accountTile.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
label.toString());
}
dashboardTiles.add(accountTile);
mAuthenticatorHelper.preloadDrawableForType(this, accountType);
}
// Sort by label
Collections.sort(dashboardTiles, new Comparator<DashboardTile>() {
@Override
public int compare(DashboardTile t1, DashboardTile t2) {
return t1.title.toString().compareTo(t2.title.toString());
}
});
int index = 0;
for (DashboardTile tile : dashboardTiles) {
target.addTile(index, tile);
index++;
}
if (!mListeningToAccountUpdates) {
AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);
mListeningToAccountUpdates = true;
}
}
private void getMetaData() {
try {
ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),

View File

@@ -55,6 +55,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TabWidget;
import com.android.settings.dashboard.DashboardCategory;
import com.android.settings.dashboard.DashboardTile;
import com.android.settings.dashboard.Header;
import java.io.IOException;
@@ -297,6 +299,66 @@ public class Utils {
return false;
}
public static boolean updateTileToSpecificActivityFromMetaDataOrRemove(Context context,
DashboardCategory target, DashboardTile tile) {
Intent intent = tile.intent;
if (intent != null) {
// Find the activity that is in the system image
PackageManager pm = context.getPackageManager();
List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
int listSize = list.size();
for (int i = 0; i < listSize; i++) {
ResolveInfo resolveInfo = list.get(i);
if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
!= 0) {
Drawable icon = null;
String title = null;
String summary = null;
// Get the activity's meta-data
try {
Resources res = pm.getResourcesForApplication(
resolveInfo.activityInfo.packageName);
Bundle metaData = resolveInfo.activityInfo.metaData;
if (res != null && metaData != null) {
icon = res.getDrawable(metaData.getInt(META_DATA_PREFERENCE_ICON));
title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
}
} catch (NameNotFoundException e) {
// Ignore
} catch (NotFoundException e) {
// Ignore
}
// Set the preference title to the activity's label if no
// meta-data is found
if (TextUtils.isEmpty(title)) {
title = resolveInfo.loadLabel(pm).toString();
}
// Set icon, title and summary for the preference
// TODO:
//tile.icon = icon;
tile.title = title;
tile.summary = summary;
// Replace the intent with this specific activity
tile.intent = new Intent().setClassName(resolveInfo.activityInfo.packageName,
resolveInfo.activityInfo.name);
return true;
}
}
}
// Did not find a matching activity, so remove the preference
target.removeTile(tile);
return false;
}
/**
* Returns true if Monkey is running.
*/

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.dashboard;
import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.List;
public class DashboardCategory implements Parcelable {
/**
* Default value for {@link com.android.settings.dashboard.DashboardCategory#id DashboardCategory.id}
* indicating that no identifier value is set. All other values (including those below -1)
* are valid.
*/
public static final long CAT_ID_UNDEFINED = -1;
/**
* Identifier for this tile, to correlate with a new list when
* it is updated. The default value is
* {@link com.android.settings.dashboard.DashboardTile#TILE_ID_UNDEFINED}, meaning no id.
* @attr ref android.R.styleable#PreferenceHeader_id
*/
public long id = CAT_ID_UNDEFINED;
/**
* Resource ID of title of the category that is shown to the user.
*/
public int titleRes;
/**
* Title of the category that is shown to the user.
*/
public CharSequence title;
/**
* List of the category's children
*/
public List<DashboardTile> tiles = new ArrayList<DashboardTile>();
public DashboardCategory() {
// Empty
}
public void addTile(DashboardTile tile) {
tiles.add(tile);
}
public void addTile(int n, DashboardTile tile) {
tiles.add(n, tile);
}
public void removeTile(DashboardTile tile) {
tiles.remove(tile);
}
public void removeTile(int n) {
tiles.remove(n);
}
public int getTilesCount() {
return tiles.size();
}
public DashboardTile getTile(int n) {
return tiles.get(n);
}
/**
* Return the currently set title. If {@link #titleRes} is set,
* this resource is loaded from <var>res</var> and returned. Otherwise
* {@link #title} is returned.
*/
public CharSequence getTitle(Resources res) {
if (titleRes != 0) {
return res.getText(titleRes);
}
return title;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(titleRes);
TextUtils.writeToParcel(title, dest, flags);
final int count = tiles.size();
dest.writeInt(count);
for (int n = 0; n < count; n++) {
DashboardTile tile = tiles.get(n);
tile.writeToParcel(dest, flags);
}
}
public void readFromParcel(Parcel in) {
titleRes = in.readInt();
title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
final int count = in.readInt();
for (int n = 0; n < count; n++) {
DashboardTile tile = DashboardTile.CREATOR.createFromParcel(in);
tiles.add(tile);
}
}
}

View File

@@ -0,0 +1,177 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.dashboard;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
/**
* Description of a single dashboard tile that the user can select.
*/
public class DashboardTile implements Parcelable {
/**
* Default value for {@link com.android.settings.dashboard.DashboardTile#id DashboardTile.id}
* indicating that no identifier value is set. All other values (including those below -1)
* are valid.
*/
public static final long TILE_ID_UNDEFINED = -1;
/**
* Identifier for this tile, to correlate with a new list when
* it is updated. The default value is
* {@link com.android.settings.dashboard.DashboardTile#TILE_ID_UNDEFINED}, meaning no id.
* @attr ref android.R.styleable#PreferenceHeader_id
*/
public long id = TILE_ID_UNDEFINED;
/**
* Resource ID of title of the tile that is shown to the user.
* @attr ref android.R.styleable#PreferenceHeader_title
*/
public int titleRes;
/**
* Title of the tile that is shown to the user.
* @attr ref android.R.styleable#PreferenceHeader_title
*/
public CharSequence title;
/**
* Resource ID of optional summary describing what this tile controls.
* @attr ref android.R.styleable#PreferenceHeader_summary
*/
public int summaryRes;
/**
* Optional summary describing what this tile controls.
* @attr ref android.R.styleable#PreferenceHeader_summary
*/
public CharSequence summary;
/**
* Optional icon resource to show for this tile.
* @attr ref android.R.styleable#PreferenceHeader_icon
*/
public int iconRes;
/**
* Full class name of the fragment to display when this tile is
* selected.
* @attr ref android.R.styleable#PreferenceHeader_fragment
*/
public String fragment;
/**
* Optional arguments to supply to the fragment when it is
* instantiated.
*/
public Bundle fragmentArguments;
/**
* Intent to launch when the preference is selected.
*/
public Intent intent;
/**
* Optional additional data for use by subclasses of the activity
*/
public Bundle extras;
public DashboardTile() {
// Empty
}
/**
* Return the currently set title. If {@link #titleRes} is set,
* this resource is loaded from <var>res</var> and returned. Otherwise
* {@link #title} is returned.
*/
public CharSequence getTitle(Resources res) {
if (titleRes != 0) {
return res.getText(titleRes);
}
return title;
}
/**
* Return the currently set summary. If {@link #summaryRes} is set,
* this resource is loaded from <var>res</var> and returned. Otherwise
* {@link #summary} is returned.
*/
public CharSequence getSummary(Resources res) {
if (summaryRes != 0) {
return res.getText(summaryRes);
}
return summary;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeInt(titleRes);
TextUtils.writeToParcel(title, dest, flags);
dest.writeInt(summaryRes);
TextUtils.writeToParcel(summary, dest, flags);
dest.writeInt(iconRes);
dest.writeString(fragment);
dest.writeBundle(fragmentArguments);
if (intent != null) {
dest.writeInt(1);
intent.writeToParcel(dest, flags);
} else {
dest.writeInt(0);
}
dest.writeBundle(extras);
}
public void readFromParcel(Parcel in) {
id = in.readLong();
titleRes = in.readInt();
title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
summaryRes = in.readInt();
summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
iconRes = in.readInt();
fragment = in.readString();
fragmentArguments = in.readBundle();
if (in.readInt() != 0) {
intent = Intent.CREATOR.createFromParcel(in);
}
extras = in.readBundle();
}
DashboardTile(Parcel in) {
readFromParcel(in);
}
public static final Creator<DashboardTile> CREATOR = new Creator<DashboardTile>() {
public DashboardTile createFromParcel(Parcel source) {
return new DashboardTile(source);
}
public DashboardTile[] newArray(int size) {
return new DashboardTile[size];
}
};
}