diff --git a/res/layout/dashboard.xml b/res/layout/dashboard.xml index ebf5204e636..6b3d827079b 100644 --- a/res/layout/dashboard.xml +++ b/res/layout/dashboard.xml @@ -14,7 +14,7 @@ limitations under the License. --> - + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="match_parent"/> diff --git a/res/layout/dashboard_status.xml b/res/layout/dashboard_status.xml index d9b28630153..8eee08f372d 100644 --- a/res/layout/dashboard_status.xml +++ b/res/layout/dashboard_status.xml @@ -14,8 +14,14 @@ limitations under the License. --> - \ No newline at end of file + android:layout_height="match_parent" + android:paddingStart="@dimen/dashboard_padding_start" + android:paddingEnd="@dimen/dashboard_padding_end" + android:paddingTop="@dimen/dashboard_padding_top" + android:paddingBottom="@dimen/dashboard_padding_bottom" + android:clipChildren="false" + android:clipToPadding="false" /> diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java index 292244c492d..dad18f287b4 100644 --- a/src/com/android/settings/dashboard/DashboardAdapter.java +++ b/src/com/android/settings/dashboard/DashboardAdapter.java @@ -29,13 +29,12 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; + import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.internal.util.ArrayUtils; import com.android.settings.R; import com.android.settings.SettingsActivity; -import com.android.settings.dashboard.conditional.Condition; -import com.android.settings.dashboard.conditional.ConditionAdapterUtils; import com.android.settingslib.SuggestionParser; import com.android.settingslib.drawer.DashboardCategory; import com.android.settingslib.drawer.Tile; @@ -43,13 +42,11 @@ import com.android.settingslib.drawer.Tile; import java.util.ArrayList; import java.util.List; -public class DashboardAdapter extends RecyclerView.Adapter - implements View.OnClickListener { +public class DashboardAdapter extends RecyclerView.Adapter { public static final String TAG = "DashboardAdapter"; private static final int NS_SPACER = 0; private static final int NS_SUGGESTION = 1000; private static final int NS_ITEMS = 2000; - private static final int NS_CONDITION = 3000; private static int SUGGESTION_MODE_DEFAULT = 0; private static int SUGGESTION_MODE_COLLAPSED = 1; @@ -65,7 +62,6 @@ public class DashboardAdapter extends RecyclerView.Adapter mCategories; - private List mConditions; private List mSuggestions; private boolean mIsShowingAll; @@ -74,7 +70,6 @@ public class DashboardAdapter extends RecyclerView.Adapter conditions) { - mConditions = conditions; - recountItems(); - } - public boolean isShowingAll() { return mIsShowingAll; } @@ -151,14 +141,7 @@ public class DashboardAdapter extends RecyclerView.Adapter + implements View.OnClickListener { + + public static final int GRID_COLUMN_COUNT = 2; + + // Namespaces + private static final int NS_CONDITION = 0; + + // Item types + private static final int TYPE_CONDITION = R.layout.condition_card; + + // Multi namespace support. + private final Context mContext; + private final List mItems = new ArrayList<>(); + private final List mTypes = new ArrayList<>(); + private final List mIds = new ArrayList<>(); + private int mId; + + // Layout control + private final SpanSizeLookup mSpanSizeLookup; + + private List mConditions; + private Condition mExpandedCondition = null; + + public DashboardStatusAdapter(Context context) { + mContext = context; + mSpanSizeLookup = new SpanSizeLookup(); + setHasStableIds(true); + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new ViewHolder( + LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false)); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + switch (holder.getItemViewType()) { + case TYPE_CONDITION: + ConditionAdapterUtils.bindViews((Condition) mItems.get(position), holder, + mItems.get(position) == mExpandedCondition, this, + new View.OnClickListener() { + @Override + public void onClick(View v) { + onExpandClick(v); + } + }); + } + } + + @Override + public long getItemId(int position) { + return mIds.get(position); + } + + @Override + public int getItemViewType(int position) { + return mTypes.get(position); + } + + @Override + public int getItemCount() { + return mIds.size(); + } + + @Override + public void onClick(View v) { + if (v.getTag() == mExpandedCondition) { + mExpandedCondition.onPrimaryClick(); + } else { + mExpandedCondition = (Condition) v.getTag(); + notifyDataSetChanged(); + } + } + + public SpanSizeLookup getSpanSizeLookup() { + return mSpanSizeLookup; + } + + public void setConditions(List conditions) { + mConditions = conditions; + recountItems(); + } + + public Object getItem(long itemId) { + for (int i = 0; i < mIds.size(); i++) { + if (mIds.get(i) == itemId) { + return mItems.get(i); + } + } + return null; + } + + private void countItem(Object object, int type, boolean add, int nameSpace) { + if (add) { + mItems.add(object); + mTypes.add(type); + // TODO: Counting namespaces for handling of suggestions/conds appearing/disappearing. + mIds.add(mId + nameSpace); + } + mId++; + } + + private void reset() { + mItems.clear(); + mTypes.clear(); + mIds.clear(); + resetCount(); + } + + private void resetCount() { + mId = 0; + } + + private void recountItems() { + reset(); + for (int i = 0; mConditions != null && i < mConditions.size(); i++) { + boolean shouldShow = mConditions.get(i).shouldShow(); + countItem(mConditions.get(i), TYPE_CONDITION, shouldShow, NS_CONDITION); + } + notifyDataSetChanged(); + } + + private void onExpandClick(View v) { + if (v.getTag() == mExpandedCondition) { + mExpandedCondition = null; + } else { + mExpandedCondition = (Condition) v.getTag(); + } + notifyDataSetChanged(); + } + + private final class SpanSizeLookup extends GridLayoutManager.SpanSizeLookup { + @Override + public int getSpanSize(int position) { + final int viewType = getItemViewType(position); + switch (viewType) { + case TYPE_CONDITION: + return 2; + default: + return 1; + } + } + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + public final ImageView icon; + public final TextView title; + public final TextView summary; + + public ViewHolder(View itemView) { + super(itemView); + icon = (ImageView) itemView.findViewById(android.R.id.icon); + title = (TextView) itemView.findViewById(android.R.id.title); + summary = (TextView) itemView.findViewById(android.R.id.summary); + } + } +} \ No newline at end of file diff --git a/src/com/android/settings/dashboard/DashboardStatusFragment.java b/src/com/android/settings/dashboard/DashboardStatusFragment.java index 66106be8f9e..38f06293166 100644 --- a/src/com/android/settings/dashboard/DashboardStatusFragment.java +++ b/src/com/android/settings/dashboard/DashboardStatusFragment.java @@ -17,25 +17,93 @@ package com.android.settings.dashboard; import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.android.internal.logging.MetricsLogger; import com.android.settings.InstrumentedFragment; import com.android.settings.R; +import com.android.settings.dashboard.conditional.Condition; +import com.android.settings.dashboard.conditional.ConditionAdapterUtils; +import com.android.settings.dashboard.conditional.ConditionManager; +import com.android.settings.dashboard.conditional.FocusRecyclerView; /** * Dashboard fragment for showing status and suggestions. */ -public final class DashboardStatusFragment extends InstrumentedFragment { +public final class DashboardStatusFragment extends InstrumentedFragment + implements ConditionManager.ConditionListener, FocusRecyclerView.FocusListener { + + private static final String TAG = "DashboardStatus"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private ConditionManager mConditionManager; + private DashboardStatusAdapter mAdapter; + private FocusRecyclerView mRecyclerView; + private GridLayoutManager mLayoutManager; @Override protected int getMetricsCategory() { return DASHBOARD_STATUS; } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mConditionManager = ConditionManager.get(getContext()); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { - return inflater.inflate(R.layout.dashboard_status, parent, false); + final View content = inflater.inflate(R.layout.dashboard_status, parent, false); + mRecyclerView = + (FocusRecyclerView) content.findViewById(R.id.dashboard_status_recycler_view); + mAdapter = new DashboardStatusAdapter(getContext()); + mAdapter.setConditions(mConditionManager.getConditions()); + mLayoutManager = new GridLayoutManager( + getContext(), DashboardStatusAdapter.GRID_COLUMN_COUNT); + mLayoutManager.setOrientation(GridLayoutManager.VERTICAL); + mLayoutManager.setSpanSizeLookup(mAdapter.getSpanSizeLookup()); + mRecyclerView.setLayoutManager(mLayoutManager); + mRecyclerView.setHasFixedSize(true); + mRecyclerView.setListener(this); + mRecyclerView.setAdapter(mAdapter); + ConditionAdapterUtils.addDismiss(mRecyclerView); + return content; + } + + @Override + public void onResume() { + super.onResume(); + for (Condition c : mConditionManager.getVisibleConditions()) { + MetricsLogger.visible(getContext(), c.getMetricsConstant()); + } + } + + @Override + public void onPause() { + super.onPause(); + for (Condition c : mConditionManager.getVisibleConditions()) { + MetricsLogger.hidden(getContext(), c.getMetricsConstant()); + } + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + if (hasWindowFocus) { + mConditionManager.addListener(this); + mConditionManager.refreshAll(); + } else { + mConditionManager.remListener(this); + } + } + + @Override + public void onConditionsChanged() { + if (DEBUG) Log.d(TAG, "onConditionsChanged"); + mAdapter.setConditions(mConditionManager.getConditions()); } } diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java index 1a27e605528..7e623fdcf87 100644 --- a/src/com/android/settings/dashboard/DashboardSummary.java +++ b/src/com/android/settings/dashboard/DashboardSummary.java @@ -19,6 +19,7 @@ package com.android.settings.dashboard; import android.content.Context; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -30,10 +31,7 @@ import com.android.settings.InstrumentedFragment; import com.android.settings.R; import com.android.settings.Settings; import com.android.settings.SettingsActivity; -import com.android.settings.dashboard.conditional.Condition; -import com.android.settings.dashboard.conditional.ConditionAdapterUtils; -import com.android.settings.dashboard.conditional.ConditionManager; -import com.android.settings.dashboard.conditional.FocusRecyclerView; + import com.android.settingslib.SuggestionParser; import com.android.settingslib.drawer.DashboardCategory; import com.android.settingslib.drawer.SettingsDrawerActivity; @@ -42,8 +40,7 @@ import com.android.settingslib.drawer.Tile; import java.util.List; public class DashboardSummary extends InstrumentedFragment - implements SettingsDrawerActivity.CategoryListener, ConditionManager.ConditionListener, - FocusRecyclerView.FocusListener { + implements SettingsDrawerActivity.CategoryListener { public static final boolean DEBUG = false; private static final boolean DEBUG_TIMING = false; private static final String TAG = "DashboardSummary"; @@ -61,10 +58,9 @@ public class DashboardSummary extends InstrumentedFragment private static final String EXTRA_SCROLL_POSITION = "scroll_position"; - private FocusRecyclerView mDashboard; + private RecyclerView mDashboard; private DashboardAdapter mAdapter; private SummaryLoader mSummaryLoader; - private ConditionManager mConditionManager; private SuggestionParser mSuggestionParser; private LinearLayoutManager mLayoutManager; @@ -84,7 +80,7 @@ public class DashboardSummary extends InstrumentedFragment if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) + " ms"); Context context = getContext(); - mConditionManager = ConditionManager.get(context); + mSuggestionParser = new SuggestionParser(context, context.getSharedPreferences(SUGGESTIONS, 0), R.xml.suggestion_ordering); } @@ -101,9 +97,6 @@ public class DashboardSummary extends InstrumentedFragment ((SettingsDrawerActivity) getActivity()).addCategoryListener(this); mSummaryLoader.setListening(true); - for (Condition c : mConditionManager.getVisibleConditions()) { - MetricsLogger.visible(getContext(), c.getMetricsConstant()); - } for (Tile suggestion : mSuggestionParser.getSuggestions()) { MetricsLogger.action(getContext(), MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, DashboardAdapter.getSuggestionIdentifier(getContext(), suggestion)); @@ -116,25 +109,12 @@ public class DashboardSummary extends InstrumentedFragment ((SettingsDrawerActivity) getActivity()).remCategoryListener(this); mSummaryLoader.setListening(false); - for (Condition c : mConditionManager.getVisibleConditions()) { - MetricsLogger.hidden(getContext(), c.getMetricsConstant()); - } for (Tile suggestion : mSuggestionParser.getSuggestions()) { MetricsLogger.action(getContext(), MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, DashboardAdapter.getSuggestionIdentifier(getContext(), suggestion)); } } - @Override - public void onWindowFocusChanged(boolean hasWindowFocus) { - if (hasWindowFocus) { - mConditionManager.addListener(this); - mConditionManager.refreshAll(); - } else { - mConditionManager.remListener(this); - } - } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -150,7 +130,7 @@ public class DashboardSummary extends InstrumentedFragment @Override public void onViewCreated(View view, Bundle bundle) { - mDashboard = (FocusRecyclerView) view.findViewById(R.id.dashboard_container); + mDashboard = (RecyclerView) view.findViewById(R.id.dashboard_container); mLayoutManager = new LinearLayoutManager(getContext()); mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); if (bundle != null) { @@ -159,13 +139,11 @@ public class DashboardSummary extends InstrumentedFragment } mDashboard.setLayoutManager(mLayoutManager); mDashboard.setHasFixedSize(true); - mDashboard.setListener(this); + mAdapter = new DashboardAdapter(getContext()); - mAdapter.setConditions(mConditionManager.getConditions()); mAdapter.setSuggestions(mSuggestionParser); mDashboard.setAdapter(mAdapter); mSummaryLoader.setAdapter(mAdapter); - ConditionAdapterUtils.addDismiss(mDashboard); rebuildUI(); } @@ -193,10 +171,4 @@ public class DashboardSummary extends InstrumentedFragment public void onCategoriesChanged() { rebuildUI(); } - - @Override - public void onConditionsChanged() { - Log.d(TAG, "onConditionsChanged"); - mAdapter.setConditions(mConditionManager.getConditions()); - } } diff --git a/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java b/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java index a87b0d028f8..973373ee791 100644 --- a/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java +++ b/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java @@ -25,10 +25,11 @@ import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup.LayoutParams; import android.widget.Button; import android.widget.ImageView; + import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.settings.R; -import com.android.settings.dashboard.DashboardAdapter; +import com.android.settings.dashboard.DashboardStatusAdapter; public class ConditionAdapterUtils { @@ -49,7 +50,7 @@ public class ConditionAdapterUtils { @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { - DashboardAdapter adapter = (DashboardAdapter) recyclerView.getAdapter(); + DashboardStatusAdapter adapter = (DashboardStatusAdapter) recyclerView.getAdapter(); Object item = adapter.getItem(viewHolder.getItemId()); if (item instanceof Condition) { ((Condition) item).silence(); @@ -61,7 +62,7 @@ public class ConditionAdapterUtils { } public static void bindViews(final Condition condition, - DashboardAdapter.DashboardItemHolder view, boolean isExpanded, + DashboardStatusAdapter.ViewHolder view, boolean isExpanded, View.OnClickListener onClickListener, View.OnClickListener onExpandListener) { View card = view.itemView.findViewById(R.id.content); card.setTag(condition);