Loading src/com/android/settings/dashboard/DashboardFeatureProvider.java +7 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.settings.dashboard; import android.content.Context; import android.support.v7.preference.Preference; import com.android.settingslib.drawer.DashboardCategory; Loading Loading @@ -53,4 +54,10 @@ public interface DashboardFeatureProvider { * Returns an unique string key for the tile. */ String getDashboardKeyForTile(Tile tile); /** * Returns a {@link ProgressiveDisclosureMixin} for specified fragment. */ ProgressiveDisclosureMixin getProgressiveDisclosureMixin(Context context, DashboardFragment fragment); } src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java +6 −0 Original line number Diff line number Diff line Loading @@ -72,4 +72,10 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { sb.append(component.getClassName()); return sb.toString(); } @Override public ProgressiveDisclosureMixin getProgressiveDisclosureMixin(Context context, DashboardFragment fragment) { return new ProgressiveDisclosureMixin(context, this, fragment); } } src/com/android/settings/dashboard/DashboardFragment.java +85 −54 Original line number Diff line number Diff line Loading @@ -22,7 +22,9 @@ import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import android.util.ArrayMap; Loading @@ -41,6 +43,7 @@ import com.android.settingslib.drawer.DashboardCategory; import com.android.settingslib.drawer.SettingsDrawerActivity; import com.android.settingslib.drawer.Tile; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; Loading Loading @@ -69,7 +72,8 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment super.onAttach(context); mDashboardFeatureProvider = FeatureFactory.getFactory(context).getDashboardFeatureProvider(context); mProgressiveDisclosureMixin = new ProgressiveDisclosureMixin(context, this); mProgressiveDisclosureMixin = mDashboardFeatureProvider .getProgressiveDisclosureMixin(context, this); getLifecycle().addObserver(mProgressiveDisclosureMixin); final List<PreferenceController> controllers = getPreferenceControllers(context); Loading @@ -81,6 +85,24 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment } } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); // Set ComparisonCallback so we get better animation when list changes. getPreferenceManager().setPreferenceComparisonCallback( new PreferenceManager.SimplePreferenceComparisonCallback()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = super.onCreateView(inflater, container, savedInstanceState); if (mDashboardFeatureProvider.isEnabled()) { getListView().addItemDecoration(mDividerDecoration); } return view; } @Override public void onCategoriesChanged() { final DashboardCategory category = Loading @@ -98,6 +120,18 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment refreshAllPreferences(getLogTag()); } @Override public void setDivider(Drawable divider) { if (mDashboardFeatureProvider.isEnabled()) { // Intercept divider and set it transparent so system divider decoration is disabled. // We will use our decoration to draw divider more intelligently. mDividerDecoration.setDivider(divider); super.setDivider(new ColorDrawable(Color.TRANSPARENT)); } else { super.setDivider(divider); } } @Override public void onStart() { super.onStart(); Loading Loading @@ -210,16 +244,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = super.onCreateView(inflater, container, savedInstanceState); if (mDashboardFeatureProvider.isEnabled()) { getListView().addItemDecoration(mDividerDecoration); } return view; } /** * Update state of each preference managed by PreferenceController. */ Loading @@ -238,18 +262,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment } } @Override public void setDivider(Drawable divider) { if (mDashboardFeatureProvider.isEnabled()) { // Intercept divider and set it transparent so system divider decoration is disabled. // We will use our decoration to draw divider more intelligently. mDividerDecoration.setDivider(divider); super.setDivider(new ColorDrawable(Color.TRANSPARENT)); } else { super.setDivider(divider); } } /** * Refresh all preference items, including both static prefs from xml, and dynamic items from * DashboardCategory. Loading @@ -275,18 +287,15 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment /** * Refresh preference items backed by DashboardCategory. */ private void refreshDashboardTiles(final String TAG) { @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void refreshDashboardTiles(final String TAG) { final PreferenceScreen screen = getPreferenceScreen(); for (String key : mDashboardTilePrefKeys) { // Remove tiles from screen mProgressiveDisclosureMixin.removePreference(screen, key); } mDashboardTilePrefKeys.clear(); final Context context = getContext(); final DashboardCategory category = mDashboardFeatureProvider.getTilesForCategory(getCategoryKey()); if (category == null) { Log.d(TAG, "NO dynamic tiles for " + TAG); Log.d(TAG, "NO dashboard tiles for " + TAG); return; } List<Tile> tiles = category.tiles; Loading @@ -294,6 +303,9 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment Log.d(TAG, "tile list is empty, skipping category " + category.title); return; } // Create a list to track which tiles are to be removed. final List<String> remove = new ArrayList<>(mDashboardTilePrefKeys); // There are dashboard tiles, so we need to install SummaryLoader. if (mSummaryLoader != null) { mSummaryLoader.release(); Loading @@ -307,8 +319,29 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment Log.d(TAG, "tile does not contain a key, skipping " + tile); continue; } mDashboardTilePrefKeys.add(key); if (mDashboardTilePrefKeys.contains(key)) { // Have the key already, will rebind. final Preference preference = mProgressiveDisclosureMixin.findPreference( screen, key); bindPreferenceToTile(context, preference, tile, key); } else { // Don't have this key, add it. final Preference pref = new DashboardTilePreference(context); bindPreferenceToTile(context, pref, tile, key); mProgressiveDisclosureMixin.addPreference(screen, pref); mDashboardTilePrefKeys.add(key); } remove.remove(key); } // Finally remove tiles that are gone. for (String key : remove) { mDashboardTilePrefKeys.remove(key); mProgressiveDisclosureMixin.removePreference(screen, key); } } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void bindPreferenceToTile(Context context, Preference pref, Tile tile, String key) { pref.setTitle(tile.title); pref.setKey(key); pref.setSummary(tile.summary); Loading @@ -332,7 +365,5 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment // (larger value has higher priority). However pref order defines smaller value has // higher priority. pref.setOrder(-tile.priority); mProgressiveDisclosureMixin.addPreference(screen, pref); } } } src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java +45 −20 Original line number Diff line number Diff line Loading @@ -28,9 +28,9 @@ import android.util.Log; import com.android.settings.core.lifecycle.LifecycleObserver; import com.android.settings.core.lifecycle.events.OnCreate; import com.android.settings.core.lifecycle.events.OnSaveInstanceState; import com.android.settings.overlay.FeatureFactory; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickListener, Loading @@ -43,18 +43,19 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL private int mTileLimit = DEFAULT_TILE_LIMIT; private final DashboardFeatureProvider mDashboardFeatureProvider; private final List<Preference> collapsedPrefs = new ArrayList<>(); // Collapsed preference sorted by order. private final List<Preference> mCollapsedPrefs = new ArrayList<>(); private final ExpandPreference mExpandButton; private final PreferenceFragment mFragment; private boolean mUserExpanded; public ProgressiveDisclosureMixin(Context context, PreferenceFragment fragment) { public ProgressiveDisclosureMixin(Context context, DashboardFeatureProvider dashboardFeatureProvider, PreferenceFragment fragment) { mFragment = fragment; mExpandButton = new ExpandPreference(context); mExpandButton.setOnPreferenceClickListener(this); mDashboardFeatureProvider = FeatureFactory.getFactory(context) .getDashboardFeatureProvider(context); mDashboardFeatureProvider = dashboardFeatureProvider; } @Override Loading @@ -75,10 +76,10 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL final PreferenceScreen screen = mFragment.getPreferenceScreen(); if (screen != null) { screen.removePreference(preference); for (Preference pref : collapsedPrefs) { for (Preference pref : mCollapsedPrefs) { screen.addPreference(pref); } collapsedPrefs.clear(); mCollapsedPrefs.clear(); mUserExpanded = true; } } Loading @@ -96,7 +97,7 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL * Whether the controller is in collapsed state. */ public boolean isCollapsed() { return !collapsedPrefs.isEmpty(); return !mCollapsedPrefs.isEmpty(); } /** Loading @@ -115,7 +116,7 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL if (!shouldCollapse(screen)) { return; } if (!collapsedPrefs.isEmpty()) { if (!mCollapsedPrefs.isEmpty()) { Log.w(TAG, "collapsed list should ALWAYS BE EMPTY before collapsing!"); } Loading @@ -134,12 +135,27 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL public void addPreference(PreferenceScreen screen, Preference pref) { // Either add to screen, or to collapsed list. if (isCollapsed()) { // Already collapsed, add to collapsed list. // insert the preference to right position. final int lastPreferenceIndex = screen.getPreferenceCount() - 2; if (lastPreferenceIndex >= 0) { final Preference lastPreference = screen.getPreference(lastPreferenceIndex); if (lastPreference.getOrder() > pref.getOrder()) { // insert to screen and move the last pref to collapsed list. screen.removePreference(lastPreference); screen.addPreference(pref); addToCollapsedList(lastPreference); } else { // Insert to collapsed list. addToCollapsedList(pref); } } else { // Couldn't find last preference on screen, just add to collapsed list. addToCollapsedList(pref); } } else if (shouldCollapse(screen)) { // About to have too many tiles on scree, collapse and add pref to collapsed list. screen.addPreference(pref); collapse(screen); addToCollapsedList(pref); } else { // No need to collapse, add to screen directly. screen.addPreference(pref); Loading @@ -158,11 +174,11 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL return; } // Didn't find on screen, try removing from collapsed list. for (int i = 0; i < collapsedPrefs.size(); i++) { final Preference pref = collapsedPrefs.get(i); for (int i = 0; i < mCollapsedPrefs.size(); i++) { final Preference pref = mCollapsedPrefs.get(i); if (TextUtils.equals(key, pref.getKey())) { collapsedPrefs.remove(pref); if (collapsedPrefs.isEmpty()) { mCollapsedPrefs.remove(pref); if (mCollapsedPrefs.isEmpty()) { // Removed last element, remove expand button too. screen.removePreference(mExpandButton); } Loading @@ -179,8 +195,8 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL if (preference != null) { return preference; } for (int i = 0; i < collapsedPrefs.size(); i++) { final Preference pref = collapsedPrefs.get(i); for (int i = 0; i < mCollapsedPrefs.size(); i++) { final Preference pref = mCollapsedPrefs.get(i); if (TextUtils.equals(key, pref.getKey())) { return pref; } Loading @@ -192,9 +208,18 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL /** * Add preference to collapsed list. */ @VisibleForTesting @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void addToCollapsedList(Preference preference) { collapsedPrefs.add(preference); // Insert preference based on it's order. int insertionIndex = Collections.binarySearch(mCollapsedPrefs, preference); if (insertionIndex < 0) { insertionIndex = insertionIndex * -1 - 1; } mCollapsedPrefs.add(insertionIndex, preference); } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) List<Preference> getCollapsedPrefs() { return mCollapsedPrefs; } } tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java +35 −3 Original line number Diff line number Diff line Loading @@ -16,10 +16,13 @@ package com.android.settings.dashboard; import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Icon; import android.os.Bundle; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import com.android.settings.SettingsActivity; import com.android.settings.TestConfig; import com.android.settings.core.PreferenceController; import com.android.settings.overlay.FeatureFactory; Loading @@ -44,6 +47,7 @@ import java.util.List; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; Loading @@ -59,6 +63,8 @@ public class DashboardFragmentTest { private DashboardCategory mDashboardCategory; @Mock private FakeFeatureFactory mFakeFeatureFactory; @Mock private ProgressiveDisclosureMixin mDisclosureMixin; private TestFragment mTestFragment; @Before Loading @@ -69,9 +75,12 @@ public class DashboardFragmentTest { mDashboardCategory.tiles = new ArrayList<>(); mDashboardCategory.tiles.add(new Tile()); mTestFragment = new TestFragment(ShadowApplication.getInstance().getApplicationContext()); mTestFragment.onAttach(ShadowApplication.getInstance().getApplicationContext()); when(mFakeFeatureFactory.dashboardFeatureProvider .getProgressiveDisclosureMixin(any(Context.class), eq(mTestFragment))) .thenReturn(mDisclosureMixin); when(mFakeFeatureFactory.dashboardFeatureProvider.getTilesForCategory(anyString())) .thenReturn(mDashboardCategory); mTestFragment.onAttach(ShadowApplication.getInstance().getApplicationContext()); } @Test Loading @@ -87,11 +96,14 @@ public class DashboardFragmentTest { @Test public void displayTilesAsPreference_shouldAddTilesWithIntent() { when(mFakeFeatureFactory.dashboardFeatureProvider.getTilesForCategory(anyString())) .thenReturn(mDashboardCategory); when(mFakeFeatureFactory.dashboardFeatureProvider.getDashboardKeyForTile(any(Tile.class))) .thenReturn("test_key"); mTestFragment.onCreatePreferences(new Bundle(), "rootKey"); verify(mTestFragment.mScreen).addPreference(any(DashboardTilePreference.class)); verify(mDisclosureMixin).addPreference(any(PreferenceScreen.class), any(DashboardTilePreference.class)); } @Test Loading @@ -109,6 +121,27 @@ public class DashboardFragmentTest { verify(mTestFragment.mScreen, never()).addPreference(any(DashboardTilePreference.class)); } @Test public void bindPreference_shouldBindAllData() { final Preference preference = new Preference( ShadowApplication.getInstance().getApplicationContext()); final Tile tile = new Tile(); tile.title = "title"; tile.summary = "summary"; tile.icon = Icon.createWithBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565)); tile.metaData = new Bundle(); tile.metaData.putString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS, "HI"); tile.priority = 10; mTestFragment.bindPreferenceToTile(mContext, preference, tile, "123"); assertThat(preference.getTitle()).isEqualTo(tile.title); assertThat(preference.getSummary()).isEqualTo(tile.summary); assertThat(preference.getIcon()).isNotNull(); assertThat(preference.getFragment()) .isEqualTo(tile.metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS)); assertThat(preference.getOrder()).isEqualTo(-tile.priority); } public static class TestPreferenceController extends PreferenceController { public TestPreferenceController(Context context) { Loading Loading @@ -139,7 +172,6 @@ public class DashboardFragmentTest { public static class TestFragment extends DashboardFragment { private final Context mContext; @Mock public PreferenceScreen mScreen; public TestFragment(Context context) { Loading Loading
src/com/android/settings/dashboard/DashboardFeatureProvider.java +7 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.settings.dashboard; import android.content.Context; import android.support.v7.preference.Preference; import com.android.settingslib.drawer.DashboardCategory; Loading Loading @@ -53,4 +54,10 @@ public interface DashboardFeatureProvider { * Returns an unique string key for the tile. */ String getDashboardKeyForTile(Tile tile); /** * Returns a {@link ProgressiveDisclosureMixin} for specified fragment. */ ProgressiveDisclosureMixin getProgressiveDisclosureMixin(Context context, DashboardFragment fragment); }
src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java +6 −0 Original line number Diff line number Diff line Loading @@ -72,4 +72,10 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { sb.append(component.getClassName()); return sb.toString(); } @Override public ProgressiveDisclosureMixin getProgressiveDisclosureMixin(Context context, DashboardFragment fragment) { return new ProgressiveDisclosureMixin(context, this, fragment); } }
src/com/android/settings/dashboard/DashboardFragment.java +85 −54 Original line number Diff line number Diff line Loading @@ -22,7 +22,9 @@ import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import android.util.ArrayMap; Loading @@ -41,6 +43,7 @@ import com.android.settingslib.drawer.DashboardCategory; import com.android.settingslib.drawer.SettingsDrawerActivity; import com.android.settingslib.drawer.Tile; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; Loading Loading @@ -69,7 +72,8 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment super.onAttach(context); mDashboardFeatureProvider = FeatureFactory.getFactory(context).getDashboardFeatureProvider(context); mProgressiveDisclosureMixin = new ProgressiveDisclosureMixin(context, this); mProgressiveDisclosureMixin = mDashboardFeatureProvider .getProgressiveDisclosureMixin(context, this); getLifecycle().addObserver(mProgressiveDisclosureMixin); final List<PreferenceController> controllers = getPreferenceControllers(context); Loading @@ -81,6 +85,24 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment } } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); // Set ComparisonCallback so we get better animation when list changes. getPreferenceManager().setPreferenceComparisonCallback( new PreferenceManager.SimplePreferenceComparisonCallback()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = super.onCreateView(inflater, container, savedInstanceState); if (mDashboardFeatureProvider.isEnabled()) { getListView().addItemDecoration(mDividerDecoration); } return view; } @Override public void onCategoriesChanged() { final DashboardCategory category = Loading @@ -98,6 +120,18 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment refreshAllPreferences(getLogTag()); } @Override public void setDivider(Drawable divider) { if (mDashboardFeatureProvider.isEnabled()) { // Intercept divider and set it transparent so system divider decoration is disabled. // We will use our decoration to draw divider more intelligently. mDividerDecoration.setDivider(divider); super.setDivider(new ColorDrawable(Color.TRANSPARENT)); } else { super.setDivider(divider); } } @Override public void onStart() { super.onStart(); Loading Loading @@ -210,16 +244,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = super.onCreateView(inflater, container, savedInstanceState); if (mDashboardFeatureProvider.isEnabled()) { getListView().addItemDecoration(mDividerDecoration); } return view; } /** * Update state of each preference managed by PreferenceController. */ Loading @@ -238,18 +262,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment } } @Override public void setDivider(Drawable divider) { if (mDashboardFeatureProvider.isEnabled()) { // Intercept divider and set it transparent so system divider decoration is disabled. // We will use our decoration to draw divider more intelligently. mDividerDecoration.setDivider(divider); super.setDivider(new ColorDrawable(Color.TRANSPARENT)); } else { super.setDivider(divider); } } /** * Refresh all preference items, including both static prefs from xml, and dynamic items from * DashboardCategory. Loading @@ -275,18 +287,15 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment /** * Refresh preference items backed by DashboardCategory. */ private void refreshDashboardTiles(final String TAG) { @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void refreshDashboardTiles(final String TAG) { final PreferenceScreen screen = getPreferenceScreen(); for (String key : mDashboardTilePrefKeys) { // Remove tiles from screen mProgressiveDisclosureMixin.removePreference(screen, key); } mDashboardTilePrefKeys.clear(); final Context context = getContext(); final DashboardCategory category = mDashboardFeatureProvider.getTilesForCategory(getCategoryKey()); if (category == null) { Log.d(TAG, "NO dynamic tiles for " + TAG); Log.d(TAG, "NO dashboard tiles for " + TAG); return; } List<Tile> tiles = category.tiles; Loading @@ -294,6 +303,9 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment Log.d(TAG, "tile list is empty, skipping category " + category.title); return; } // Create a list to track which tiles are to be removed. final List<String> remove = new ArrayList<>(mDashboardTilePrefKeys); // There are dashboard tiles, so we need to install SummaryLoader. if (mSummaryLoader != null) { mSummaryLoader.release(); Loading @@ -307,8 +319,29 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment Log.d(TAG, "tile does not contain a key, skipping " + tile); continue; } mDashboardTilePrefKeys.add(key); if (mDashboardTilePrefKeys.contains(key)) { // Have the key already, will rebind. final Preference preference = mProgressiveDisclosureMixin.findPreference( screen, key); bindPreferenceToTile(context, preference, tile, key); } else { // Don't have this key, add it. final Preference pref = new DashboardTilePreference(context); bindPreferenceToTile(context, pref, tile, key); mProgressiveDisclosureMixin.addPreference(screen, pref); mDashboardTilePrefKeys.add(key); } remove.remove(key); } // Finally remove tiles that are gone. for (String key : remove) { mDashboardTilePrefKeys.remove(key); mProgressiveDisclosureMixin.removePreference(screen, key); } } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void bindPreferenceToTile(Context context, Preference pref, Tile tile, String key) { pref.setTitle(tile.title); pref.setKey(key); pref.setSummary(tile.summary); Loading @@ -332,7 +365,5 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment // (larger value has higher priority). However pref order defines smaller value has // higher priority. pref.setOrder(-tile.priority); mProgressiveDisclosureMixin.addPreference(screen, pref); } } }
src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java +45 −20 Original line number Diff line number Diff line Loading @@ -28,9 +28,9 @@ import android.util.Log; import com.android.settings.core.lifecycle.LifecycleObserver; import com.android.settings.core.lifecycle.events.OnCreate; import com.android.settings.core.lifecycle.events.OnSaveInstanceState; import com.android.settings.overlay.FeatureFactory; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickListener, Loading @@ -43,18 +43,19 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL private int mTileLimit = DEFAULT_TILE_LIMIT; private final DashboardFeatureProvider mDashboardFeatureProvider; private final List<Preference> collapsedPrefs = new ArrayList<>(); // Collapsed preference sorted by order. private final List<Preference> mCollapsedPrefs = new ArrayList<>(); private final ExpandPreference mExpandButton; private final PreferenceFragment mFragment; private boolean mUserExpanded; public ProgressiveDisclosureMixin(Context context, PreferenceFragment fragment) { public ProgressiveDisclosureMixin(Context context, DashboardFeatureProvider dashboardFeatureProvider, PreferenceFragment fragment) { mFragment = fragment; mExpandButton = new ExpandPreference(context); mExpandButton.setOnPreferenceClickListener(this); mDashboardFeatureProvider = FeatureFactory.getFactory(context) .getDashboardFeatureProvider(context); mDashboardFeatureProvider = dashboardFeatureProvider; } @Override Loading @@ -75,10 +76,10 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL final PreferenceScreen screen = mFragment.getPreferenceScreen(); if (screen != null) { screen.removePreference(preference); for (Preference pref : collapsedPrefs) { for (Preference pref : mCollapsedPrefs) { screen.addPreference(pref); } collapsedPrefs.clear(); mCollapsedPrefs.clear(); mUserExpanded = true; } } Loading @@ -96,7 +97,7 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL * Whether the controller is in collapsed state. */ public boolean isCollapsed() { return !collapsedPrefs.isEmpty(); return !mCollapsedPrefs.isEmpty(); } /** Loading @@ -115,7 +116,7 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL if (!shouldCollapse(screen)) { return; } if (!collapsedPrefs.isEmpty()) { if (!mCollapsedPrefs.isEmpty()) { Log.w(TAG, "collapsed list should ALWAYS BE EMPTY before collapsing!"); } Loading @@ -134,12 +135,27 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL public void addPreference(PreferenceScreen screen, Preference pref) { // Either add to screen, or to collapsed list. if (isCollapsed()) { // Already collapsed, add to collapsed list. // insert the preference to right position. final int lastPreferenceIndex = screen.getPreferenceCount() - 2; if (lastPreferenceIndex >= 0) { final Preference lastPreference = screen.getPreference(lastPreferenceIndex); if (lastPreference.getOrder() > pref.getOrder()) { // insert to screen and move the last pref to collapsed list. screen.removePreference(lastPreference); screen.addPreference(pref); addToCollapsedList(lastPreference); } else { // Insert to collapsed list. addToCollapsedList(pref); } } else { // Couldn't find last preference on screen, just add to collapsed list. addToCollapsedList(pref); } } else if (shouldCollapse(screen)) { // About to have too many tiles on scree, collapse and add pref to collapsed list. screen.addPreference(pref); collapse(screen); addToCollapsedList(pref); } else { // No need to collapse, add to screen directly. screen.addPreference(pref); Loading @@ -158,11 +174,11 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL return; } // Didn't find on screen, try removing from collapsed list. for (int i = 0; i < collapsedPrefs.size(); i++) { final Preference pref = collapsedPrefs.get(i); for (int i = 0; i < mCollapsedPrefs.size(); i++) { final Preference pref = mCollapsedPrefs.get(i); if (TextUtils.equals(key, pref.getKey())) { collapsedPrefs.remove(pref); if (collapsedPrefs.isEmpty()) { mCollapsedPrefs.remove(pref); if (mCollapsedPrefs.isEmpty()) { // Removed last element, remove expand button too. screen.removePreference(mExpandButton); } Loading @@ -179,8 +195,8 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL if (preference != null) { return preference; } for (int i = 0; i < collapsedPrefs.size(); i++) { final Preference pref = collapsedPrefs.get(i); for (int i = 0; i < mCollapsedPrefs.size(); i++) { final Preference pref = mCollapsedPrefs.get(i); if (TextUtils.equals(key, pref.getKey())) { return pref; } Loading @@ -192,9 +208,18 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL /** * Add preference to collapsed list. */ @VisibleForTesting @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void addToCollapsedList(Preference preference) { collapsedPrefs.add(preference); // Insert preference based on it's order. int insertionIndex = Collections.binarySearch(mCollapsedPrefs, preference); if (insertionIndex < 0) { insertionIndex = insertionIndex * -1 - 1; } mCollapsedPrefs.add(insertionIndex, preference); } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) List<Preference> getCollapsedPrefs() { return mCollapsedPrefs; } }
tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java +35 −3 Original line number Diff line number Diff line Loading @@ -16,10 +16,13 @@ package com.android.settings.dashboard; import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Icon; import android.os.Bundle; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import com.android.settings.SettingsActivity; import com.android.settings.TestConfig; import com.android.settings.core.PreferenceController; import com.android.settings.overlay.FeatureFactory; Loading @@ -44,6 +47,7 @@ import java.util.List; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; Loading @@ -59,6 +63,8 @@ public class DashboardFragmentTest { private DashboardCategory mDashboardCategory; @Mock private FakeFeatureFactory mFakeFeatureFactory; @Mock private ProgressiveDisclosureMixin mDisclosureMixin; private TestFragment mTestFragment; @Before Loading @@ -69,9 +75,12 @@ public class DashboardFragmentTest { mDashboardCategory.tiles = new ArrayList<>(); mDashboardCategory.tiles.add(new Tile()); mTestFragment = new TestFragment(ShadowApplication.getInstance().getApplicationContext()); mTestFragment.onAttach(ShadowApplication.getInstance().getApplicationContext()); when(mFakeFeatureFactory.dashboardFeatureProvider .getProgressiveDisclosureMixin(any(Context.class), eq(mTestFragment))) .thenReturn(mDisclosureMixin); when(mFakeFeatureFactory.dashboardFeatureProvider.getTilesForCategory(anyString())) .thenReturn(mDashboardCategory); mTestFragment.onAttach(ShadowApplication.getInstance().getApplicationContext()); } @Test Loading @@ -87,11 +96,14 @@ public class DashboardFragmentTest { @Test public void displayTilesAsPreference_shouldAddTilesWithIntent() { when(mFakeFeatureFactory.dashboardFeatureProvider.getTilesForCategory(anyString())) .thenReturn(mDashboardCategory); when(mFakeFeatureFactory.dashboardFeatureProvider.getDashboardKeyForTile(any(Tile.class))) .thenReturn("test_key"); mTestFragment.onCreatePreferences(new Bundle(), "rootKey"); verify(mTestFragment.mScreen).addPreference(any(DashboardTilePreference.class)); verify(mDisclosureMixin).addPreference(any(PreferenceScreen.class), any(DashboardTilePreference.class)); } @Test Loading @@ -109,6 +121,27 @@ public class DashboardFragmentTest { verify(mTestFragment.mScreen, never()).addPreference(any(DashboardTilePreference.class)); } @Test public void bindPreference_shouldBindAllData() { final Preference preference = new Preference( ShadowApplication.getInstance().getApplicationContext()); final Tile tile = new Tile(); tile.title = "title"; tile.summary = "summary"; tile.icon = Icon.createWithBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565)); tile.metaData = new Bundle(); tile.metaData.putString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS, "HI"); tile.priority = 10; mTestFragment.bindPreferenceToTile(mContext, preference, tile, "123"); assertThat(preference.getTitle()).isEqualTo(tile.title); assertThat(preference.getSummary()).isEqualTo(tile.summary); assertThat(preference.getIcon()).isNotNull(); assertThat(preference.getFragment()) .isEqualTo(tile.metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS)); assertThat(preference.getOrder()).isEqualTo(-tile.priority); } public static class TestPreferenceController extends PreferenceController { public TestPreferenceController(Context context) { Loading Loading @@ -139,7 +172,6 @@ public class DashboardFragmentTest { public static class TestFragment extends DashboardFragment { private final Context mContext; @Mock public PreferenceScreen mScreen; public TestFragment(Context context) { Loading