Change to use new suggestion/condition UI.

Change to always use the new UI that combines the suggestion and conditions,
and remove all codes relating to the old UI.

Fix: 37645754
Fix: 62621808
Test: make RunSettingsRoboTests

Merged-In: I3421a9e5182f6606843392d6fae8b9f07c5f2e46
Change-Id: I5ef169a563166520dad0ac44f6780da814e2f1f7
This commit is contained in:
Doris Ling
2017-06-16 14:13:45 -07:00
parent a6b24388fc
commit b99af0e4a2
20 changed files with 278 additions and 1064 deletions

View File

@@ -1,128 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 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.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false">
<LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="?android:attr/colorAccent"
android:elevation="2dp"
android:clickable="true"
android:focusable="true">
<LinearLayout
android:id="@+id/collapsed_group"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:gravity="center">
<ImageView
android:id="@android:id/icon"
android:layout_width="24dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="32dp"
android:tint="?android:attr/textColorPrimaryInverse" />
<TextView
android:id="@android:id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimaryInverse" />
<ImageView
android:id="@+id/expand_indicator"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="16dp"
android:tint="?android:attr/textColorPrimaryInverse"/>
</LinearLayout>
<LinearLayout
android:id="@+id/detail_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="72dp"
android:visibility="gone"
android:orientation="vertical">
<!-- TODO: Don't set alpha here, and do proper themeing that
handles night mode -->
<TextView
android:id="@android:id/summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingBottom="16dp"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:alpha=".7"
android:textColor="?android:attr/textColorPrimaryInverse" />
<!-- TODO: Better background -->
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height=".25dp"
android:background="@android:color/white" />
<com.android.internal.widget.ButtonBarLayout
android:id="@+id/buttonBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
style="?android:attr/buttonBarStyle"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<Button
android:id="@+id/first_action"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingStart="0dp"
android:alpha=".8"
android:textAlignment="viewStart"
android:textColor="?android:attr/textColorPrimaryInverse"
style="?android:attr/buttonBarButtonStyle" />
<Button
android:id="@+id/second_action"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:alpha=".8"
android:textAlignment="viewStart"
android:textColor="?android:attr/textColorPrimaryInverse"
style="?android:attr/buttonBarButtonStyle" />
</com.android.internal.widget.ButtonBarLayout>
</LinearLayout>
</LinearLayout>
</FrameLayout>

View File

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/dashboard_category_height"
android:clickable="true"
android:focusable="true"
android:background="@drawable/selectable_card_grey"
android:gravity="center_vertical"
android:paddingTop="4dp">
<ImageView
android:id="@android:id/icon"
android:layout_width="@dimen/dashboard_tile_image_size"
android:layout_height="@dimen/dashboard_tile_image_size"
android:layout_marginStart="@dimen/dashboard_tile_image_margin"
android:layout_marginEnd="@dimen/dashboard_tile_image_margin"
android:src="@drawable/ic_expand_more"/>
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.SuggestionTitle"
android:textColor="?android:attr/colorAccent"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
<TextView
android:id="@android:id/summary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:paddingEnd="18dp"
android:textAppearance="@style/TextAppearance.SuggestionTitle"
android:textColor="?android:attr/colorAccent"/>
</LinearLayout>

View File

@@ -1,58 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selectable_card_grey"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:minHeight="@dimen/dashboard_tile_minimum_height">
<ImageView
android:id="@android:id/icon"
android:layout_width="@dimen/dashboard_tile_image_size"
android:layout_height="@dimen/dashboard_tile_image_size"
android:layout_marginStart="@dimen/dashboard_tile_image_margin"
android:layout_marginEnd="@dimen/dashboard_tile_image_margin"
android:scaleType="centerInside"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.TileTitle"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
<TextView android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:textAppearance="@style/TextAppearance.Small"
android:textColor="?android:attr/textColorSecondary"/>
</RelativeLayout>
</LinearLayout>

View File

@@ -18,9 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="@drawable/selectable_card"
android:background="@android:color/white"
android:clickable="true"
android:elevation="2dp"
android:focusable="true"
android:minHeight="@dimen/dashboard_tile_minimum_height" />

View File

@@ -15,7 +15,6 @@
*/
package com.android.settings.dashboard;
import android.annotation.ColorInt;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
@@ -40,12 +39,10 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.R.id;
import com.android.settings.SettingsActivity;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.dashboard.DashboardData.SuggestionConditionHeaderData;
import com.android.settings.dashboard.conditional.Condition;
import com.android.settings.dashboard.conditional.ConditionAdapter;
import com.android.settings.dashboard.conditional.ConditionAdapterUtils;
import com.android.settings.dashboard.suggestions.SuggestionAdapter;
import com.android.settings.dashboard.suggestions.SuggestionDismissController;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
@@ -63,7 +60,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
public static final String TAG = "DashboardAdapter";
private static final String STATE_SUGGESTION_LIST = "suggestion_list";
private static final String STATE_CATEGORY_LIST = "category_list";
private static final String STATE_SUGGESTION_MODE = "suggestion_mode";
private static final String STATE_SUGGESTIONS_SHOWN_LOGGED = "suggestions_shown_logged";
private static final String STATE_SUGGESTION_CONDITION_MODE = "suggestion_condition_mode";
@@ -77,7 +73,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
private final SuggestionFeatureProvider mSuggestionFeatureProvider;
private final ArrayList<String> mSuggestionsShownLogged;
private boolean mFirstFrameDrawn;
private boolean mCombineSuggestionAndCondition;
private RecyclerView mRecyclerView;
private SuggestionParser mSuggestionParser;
private SuggestionAdapter mSuggestionAdapter;
@@ -99,46 +94,20 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
@Override
public void onClick(View v) {
if (mCombineSuggestionAndCondition) {
Condition condition = (Condition) v.getTag();
//TODO: get rid of setTag/getTag
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_SETTINGS_CONDITION_CLICK,
condition.getMetricsConstant());
condition.onPrimaryClick();
} else {
Condition expandedCondition = mDashboardData.getExpandedCondition();
//TODO: get rid of setTag/getTag
if (v.getTag() == expandedCondition) {
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_SETTINGS_CONDITION_CLICK,
expandedCondition.getMetricsConstant());
expandedCondition.onPrimaryClick();
} else {
expandedCondition = (Condition) v.getTag();
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND,
expandedCondition.getMetricsConstant());
updateExpandedCondition(expandedCondition);
}
}
}
};
@Deprecated
public DashboardAdapter(Context context, Bundle savedInstanceState,
List<Condition> conditions) {
this(context, savedInstanceState, conditions, null, null);
}
public DashboardAdapter(Context context, Bundle savedInstanceState,
List<Condition> conditions, SuggestionParser suggestionParser,
SuggestionDismissController.Callback callback) {
List<Tile> suggestions = null;
List<DashboardCategory> categories = null;
int suggestionMode = DashboardData.SUGGESTION_MODE_DEFAULT;
int suggestionConditionMode = DashboardData.HEADER_MODE_DEFAULT;
mContext = context;
@@ -146,7 +115,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
mMetricsFeatureProvider = factory.getMetricsFeatureProvider();
mDashboardFeatureProvider = factory.getDashboardFeatureProvider(context);
mSuggestionFeatureProvider = factory.getSuggestionFeatureProvider(context);
mCombineSuggestionAndCondition = mDashboardFeatureProvider.combineSuggestionAndCondition();
mCache = new IconCache(context);
mSuggestionParser = suggestionParser;
mCallback = callback;
@@ -158,8 +126,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
categories = savedInstanceState.getParcelableArrayList(STATE_CATEGORY_LIST);
suggestionConditionMode = savedInstanceState.getInt(
STATE_SUGGESTION_CONDITION_MODE, suggestionConditionMode);
suggestionMode = savedInstanceState.getInt(
STATE_SUGGESTION_MODE, DashboardData.SUGGESTION_MODE_DEFAULT);
mSuggestionsShownLogged = savedInstanceState.getStringArrayList(
STATE_SUGGESTIONS_SHOWN_LOGGED);
} else {
@@ -170,8 +136,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
.setConditions(conditions)
.setSuggestions(suggestions)
.setCategories(categories)
.setSuggestionMode(suggestionMode)
.setCombineSuggestionAndCondition(mCombineSuggestionAndCondition)
.setSuggestionConditionMode(suggestionConditionMode)
.build();
}
@@ -213,7 +177,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
.build();
notifyDashboardDataChanged(prevData);
List<Tile> shownSuggestions = null;
if (mCombineSuggestionAndCondition) {
final int mode = mDashboardData.getSuggestionConditionMode();
if (mode == DashboardData.HEADER_MODE_DEFAULT) {
shownSuggestions = suggestions.subList(0,
@@ -221,17 +184,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
} else if (mode != DashboardData.HEADER_MODE_COLLAPSED) {
shownSuggestions = suggestions;
}
} else {
switch (mDashboardData.getSuggestionMode()) {
case DashboardData.SUGGESTION_MODE_DEFAULT:
shownSuggestions = suggestions.subList(0,
Math.min(suggestions.size(), DashboardData.DEFAULT_SUGGESTION_COUNT));
break;
case DashboardData.SUGGESTION_MODE_EXPANDED:
shownSuggestions = suggestions;
break;
}
}
if (shownSuggestions != null) {
for (Tile suggestion : shownSuggestions) {
final String identifier = mSuggestionFeatureProvider.getSuggestionIdentifier(
@@ -255,16 +207,9 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
public void setConditions(List<Condition> conditions) {
final DashboardData prevData = mDashboardData;
Log.d(TAG, "adapter setConditions called");
if (mCombineSuggestionAndCondition) {
mDashboardData = new DashboardData.Builder(prevData)
.setConditions(conditions)
.build();
} else {
mDashboardData = new DashboardData.Builder(prevData)
.setConditions(conditions)
.setExpandedCondition(null)
.build();
}
notifyDashboardDataChanged(prevData);
}
@@ -317,44 +262,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
holder.itemView.setTag(tile);
holder.itemView.setOnClickListener(mTileClickListener);
break;
case R.layout.suggestion_header:
onBindSuggestionHeader(holder, (DashboardData.SuggestionHeaderData)
mDashboardData.getItemEntityByPosition(position));
break;
case R.layout.suggestion_tile:
case R.layout.suggestion_tile_card:
final Tile suggestion = (Tile) mDashboardData.getItemEntityByPosition(position);
final String suggestionId = mSuggestionFeatureProvider.getSuggestionIdentifier(
mContext, suggestion);
// This is for cases when a suggestion is dismissed and the next one comes to view
if (!mSuggestionsShownLogged.contains(suggestionId)) {
mMetricsFeatureProvider.action(
mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, suggestionId);
mSuggestionsShownLogged.add(suggestionId);
}
onBindTile(holder, suggestion);
View clickHandler = holder.itemView;
// If a view with @android:id/primary is defined, use that as the click handler
// instead.
final View primaryAction = holder.itemView.findViewById(android.R.id.primary);
if (primaryAction != null) {
clickHandler = primaryAction;
// set the item view to disabled to remove any touch effects
holder.itemView.setEnabled(false);
}
clickHandler.setOnClickListener(v -> {
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_SETTINGS_SUGGESTION, suggestionId);
((SettingsActivity) mContext).startSuggestion(suggestion.intent);
});
break;
case R.layout.condition_card:
final boolean isExpanded = mDashboardData.getItemEntityByPosition(position)
== mDashboardData.getExpandedCondition();
ConditionAdapterUtils.bindViews(
(Condition) mDashboardData.getItemEntityByPosition(position),
holder, isExpanded, mConditionClickListener, v -> onExpandClick(v));
break;
case R.layout.suggestion_condition_container:
onBindConditionAndSuggestion(
(SuggestionAndConditionContainerHolder) holder, position);
@@ -434,35 +341,13 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
mSuggestionsShownLogged.clear();
}
// condition card is always expanded in new suggestion/condition UI.
// TODO: Remove when completely move to new suggestion/condition UI
@Deprecated
public void onExpandClick(View v) {
Condition expandedCondition = mDashboardData.getExpandedCondition();
if (v.getTag() == expandedCondition) {
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_SETTINGS_CONDITION_COLLAPSE,
expandedCondition.getMetricsConstant());
expandedCondition = null;
} else {
expandedCondition = (Condition) v.getTag();
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND,
expandedCondition.getMetricsConstant());
}
updateExpandedCondition(expandedCondition);
}
public Object getItem(long itemId) {
return mDashboardData.getItemEntityById(itemId);
}
public Tile getSuggestion(int position) {
if (mCombineSuggestionAndCondition) {
return mSuggestionAdapter.getSuggestion(position);
}
return (Tile) getItem(getItemId(position));
}
@VisibleForTesting
void notifyDashboardDataChanged(DashboardData prevData) {
@@ -476,56 +361,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
}
}
private void updateExpandedCondition(Condition condition) {
final DashboardData prevData = mDashboardData;
mDashboardData = new DashboardData.Builder(prevData)
.setExpandedCondition(condition)
.build();
notifyDashboardDataChanged(prevData);
}
@VisibleForTesting
void onBindSuggestionHeader(final DashboardItemHolder holder, DashboardData
.SuggestionHeaderData data) {
final boolean moreSuggestions = data.hasMoreSuggestions;
final int undisplayedSuggestionCount = data.undisplayedSuggestionCount;
holder.icon.setImageResource(moreSuggestions ? R.drawable.ic_expand_more
: R.drawable.ic_expand_less);
holder.title.setText(mContext.getString(R.string.suggestions_title, data.suggestionSize));
String summaryContentDescription;
if (moreSuggestions) {
summaryContentDescription = mContext.getResources().getQuantityString(
R.plurals.settings_suggestion_header_summary_hidden_items,
undisplayedSuggestionCount, undisplayedSuggestionCount);
} else {
summaryContentDescription = mContext.getString(R.string.condition_expand_hide);
}
holder.summary.setContentDescription(summaryContentDescription);
if (undisplayedSuggestionCount == 0) {
holder.summary.setText(null);
} else {
holder.summary.setText(
mContext.getString(R.string.suggestions_summary, undisplayedSuggestionCount));
}
holder.itemView.setOnClickListener(v -> {
final int suggestionMode;
if (moreSuggestions) {
suggestionMode = DashboardData.SUGGESTION_MODE_EXPANDED;
logSuggestions();
} else {
suggestionMode = DashboardData.SUGGESTION_MODE_COLLAPSED;
}
DashboardData prevData = mDashboardData;
mDashboardData = new DashboardData.Builder(prevData)
.setSuggestionMode(suggestionMode)
.build();
notifyDashboardDataChanged(prevData);
});
}
private void logSuggestions() {
for (Tile suggestion : mDashboardData.getSuggestions()) {
final String suggestionId = mSuggestionFeatureProvider.getSuggestionIdentifier(
@@ -550,7 +385,8 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
holder.itemView.setOnClickListener(null);
}
private void onBindSuggestionConditionHeader(final SuggestionAndConditionHeaderHolder holder,
@VisibleForTesting
void onBindSuggestionConditionHeader(final SuggestionAndConditionHeaderHolder holder,
SuggestionConditionHeaderData data) {
final int curMode = mDashboardData.getSuggestionConditionMode();
final int nextMode = data.hiddenSuggestionCount > 0 && data.conditionCount > 0
@@ -632,24 +468,23 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
@VisibleForTesting
void onBindConditionAndSuggestion(final SuggestionAndConditionContainerHolder holder,
int position) {
RecyclerView.Adapter<DashboardItemHolder> adapter;
// If there is suggestions to show, it will be at position 1
// position 0 is suggestion header.
if (position == (SUGGESTION_CONDITION_HEADER_POSITION + 1)
&& mDashboardData.getSuggestions() != null) {
mSuggestionAdapter = new SuggestionAdapter(mContext, (List<Tile>)
mDashboardData.getItemEntityByPosition(position), mSuggestionsShownLogged);
adapter = mSuggestionAdapter;
mSuggestionDismissHandler = new SuggestionDismissController(mContext,
holder.data, mSuggestionParser, mCallback);
holder.data.setAdapter(mSuggestionAdapter);
} else {
ConditionAdapterUtils.addDismiss(holder.data);
adapter = new ConditionAdapter(mContext,
ConditionAdapter adapter = new ConditionAdapter(mContext,
(List<Condition>) mDashboardData.getItemEntityByPosition(position),
mDashboardData.getSuggestionConditionMode());
adapter.addDismissHandling(holder.data);
holder.data.setAdapter(adapter);
}
holder.data.setLayoutManager(new LinearLayoutManager(mContext));
holder.data.setAdapter(adapter);
}
private void onBindTile(DashboardItemHolder holder, Tile tile) {
@@ -682,7 +517,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
if (categories != null) {
outState.putParcelableArrayList(STATE_CATEGORY_LIST, new ArrayList<>(categories));
}
outState.putInt(STATE_SUGGESTION_MODE, mDashboardData.getSuggestionMode());
outState.putStringArrayList(STATE_SUGGESTIONS_SHOWN_LOGGED, mSuggestionsShownLogged);
outState.putInt(STATE_SUGGESTION_CONDITION_MODE,
mDashboardData.getSuggestionConditionMode());

View File

@@ -17,8 +17,6 @@ package com.android.settings.dashboard;
import android.annotation.IntDef;
import android.graphics.drawable.Icon;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.v7.util.DiffUtil;
import android.text.TextUtils;
@@ -31,7 +29,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Description about data list used in the DashboardAdapter. In the data list each item can be
@@ -40,13 +37,6 @@ import java.util.Objects;
* ItemsData has inner class Item, which represents the Item in data list.
*/
public class DashboardData {
@Deprecated
public static final int SUGGESTION_MODE_DEFAULT = 0;
@Deprecated
public static final int SUGGESTION_MODE_COLLAPSED = 1;
@Deprecated
public static final int SUGGESTION_MODE_EXPANDED = 2;
public static final int HEADER_MODE_DEFAULT = 0;
public static final int HEADER_MODE_SUGGESTION_EXPANDED = 1;
public static final int HEADER_MODE_FULLY_EXPANDED = 2;
@@ -62,29 +52,20 @@ public class DashboardData {
// id namespace for different type of items.
private static final int NS_SPACER = 0;
private static final int NS_ITEMS = 2000;
private static final int NS_CONDITION = 3000;
private static final int NS_SUGGESTION_CONDITION = 4000;
private static final int NS_SUGGESTION_CONDITION = 3000;
private final List<Item> mItems;
private final List<DashboardCategory> mCategories;
private final List<Condition> mConditions;
private final List<Tile> mSuggestions;
@Deprecated
private final int mSuggestionMode;
@Deprecated
private final Condition mExpandedCondition;
private final @HeaderMode int mSuggestionConditionMode;
private int mId;
private boolean mCombineSuggestionAndCondition;
private DashboardData(Builder builder) {
mCategories = builder.mCategories;
mConditions = builder.mConditions;
mSuggestions = builder.mSuggestions;
mSuggestionMode = builder.mSuggestionMode;
mExpandedCondition = builder.mExpandedCondition;
mSuggestionConditionMode = builder.mSuggestionConditionMode;
mCombineSuggestionAndCondition = builder.mCombineSuggestionAndCondition;
mItems = new ArrayList<>();
mId = 0;
@@ -133,19 +114,10 @@ public class DashboardData {
return mSuggestions;
}
public int getSuggestionMode() {
return mSuggestionMode;
}
public int getSuggestionConditionMode() {
return mSuggestionConditionMode;
}
@Deprecated
public Condition getExpandedCondition() {
return mExpandedCondition;
}
/**
* Find the position of the object in mItems list, using the equals method to compare
*
@@ -192,10 +164,10 @@ public class DashboardData {
/**
* Get the count of suggestions to display
*
* The displayable count mainly depends on the {@link #mSuggestionMode}
* The displayable count mainly depends on the {@link #mSuggestionConditionMode}
* and the size of suggestions list.
*
* When in default mode, displayable count couldn't larger than
* When in default mode, displayable count couldn't be larger than
* {@link #DEFAULT_SUGGESTION_COUNT}.
*
* When in expanded mode, display all the suggestions.
@@ -204,7 +176,6 @@ public class DashboardData {
*/
public int getDisplayableSuggestionCount() {
final int suggestionSize = sizeOf(mSuggestions);
if (mCombineSuggestionAndCondition) {
if (mSuggestionConditionMode == HEADER_MODE_COLLAPSED) {
return 0;
}
@@ -213,25 +184,12 @@ public class DashboardData {
}
return suggestionSize;
}
if (mSuggestionMode == SUGGESTION_MODE_DEFAULT) {
return Math.min(DEFAULT_SUGGESTION_COUNT, suggestionSize);
}
if (mSuggestionMode == SUGGESTION_MODE_EXPANDED) {
return suggestionSize;
}
return 0;
}
public boolean hasMoreSuggestions() {
if (mCombineSuggestionAndCondition) {
return mSuggestionConditionMode == HEADER_MODE_COLLAPSED && mSuggestions.size() > 0
|| mSuggestionConditionMode == HEADER_MODE_DEFAULT
&& mSuggestions.size() > DEFAULT_SUGGESTION_COUNT;
}
return mSuggestionMode == SUGGESTION_MODE_COLLAPSED
|| (mSuggestionMode == SUGGESTION_MODE_DEFAULT
&& mSuggestions.size() > DEFAULT_SUGGESTION_COUNT);
}
private void resetCount() {
mId = 0;
@@ -251,59 +209,17 @@ public class DashboardData {
*/
private void countItem(Object object, int type, boolean add, int nameSpace) {
if (add) {
if (mCombineSuggestionAndCondition) {
mItems.add(new Item(object, type, mId + nameSpace));
} else {
mItems.add(new Item(object, type, mId + nameSpace, object == mExpandedCondition));
}
}
mId++;
}
/**
* A special count item method for just suggestions. Id is calculated using suggestion hash
* instead of the position of suggestion in list. This is a more stable id than countItem.
*/
private void countSuggestion(Tile tile, boolean add) {
if (add) {
mItems.add(new Item(
tile,
tile.remoteViews != null
? R.layout.suggestion_tile_card
: R.layout.suggestion_tile,
Objects.hash(tile.title),
false));
}
mId++;
}
/**
* Build the mItems list using mConditions, mSuggestions, mCategories data
* and mIsShowingAll, mSuggestionMode flag.
* and mIsShowingAll, mSuggestionConditionMode flag.
*/
private void buildItemsData() {
final boolean hasSuggestions = sizeOf(mSuggestions) > 0;
if (!mCombineSuggestionAndCondition) {
boolean hasConditions = false;
for (int i = 0; mConditions != null && i < mConditions.size(); i++) {
boolean shouldShow = mConditions.get(i).shouldShow();
hasConditions |= shouldShow;
countItem(mConditions.get(i), R.layout.condition_card, shouldShow, NS_CONDITION);
}
resetCount();
countItem(null, R.layout.dashboard_spacer, hasConditions && hasSuggestions, NS_SPACER);
countItem(buildSuggestionHeaderData(), R.layout.suggestion_header, hasSuggestions,
NS_SPACER);
resetCount();
if (mSuggestions != null) {
int maxSuggestions = getDisplayableSuggestionCount();
for (int i = 0; i < mSuggestions.size(); i++) {
countSuggestion(mSuggestions.get(i), i < maxSuggestions);
}
}
} else {
final List<Condition> conditions = getConditionsToShow(mConditions);
final boolean hasConditions = sizeOf(conditions) > 0;
@@ -349,7 +265,6 @@ public class DashboardData {
mSuggestionConditionMode == HEADER_MODE_FULLY_EXPANDED
|| hasSuggestions && !hasConditions && hiddenSuggestion == 0,
NS_SUGGESTION_CONDITION);
}
resetCount();
for (int i = 0; mCategories != null && i < mCategories.size(); i++) {
@@ -367,21 +282,6 @@ public class DashboardData {
return list == null ? 0 : list.size();
}
private SuggestionHeaderData buildSuggestionHeaderData() {
SuggestionHeaderData data;
if (mSuggestions == null) {
data = new SuggestionHeaderData();
} else {
final boolean hasMoreSuggestions = hasMoreSuggestions();
final int suggestionSize = mSuggestions.size();
final int undisplayedSuggestionCount = suggestionSize - getDisplayableSuggestionCount();
data = new SuggestionHeaderData(hasMoreSuggestions, suggestionSize,
undisplayedSuggestionCount);
}
return data;
}
private List<Condition> getConditionsToShow(List<Condition> conditions) {
if (conditions == null) {
return null;
@@ -411,20 +311,14 @@ public class DashboardData {
/**
* Builder used to build the ItemsData
* <p>
* {@link #mExpandedCondition}, {@link #mSuggestionConditionMode} and {@link #mSuggestionMode}
* have default value while others are not.
* {@link #mSuggestionConditionMode} have default value while others are not.
*/
public static class Builder {
@Deprecated
private int mSuggestionMode = SUGGESTION_MODE_DEFAULT;
@Deprecated
private Condition mExpandedCondition = null;
private @HeaderMode int mSuggestionConditionMode = HEADER_MODE_DEFAULT;
private List<DashboardCategory> mCategories;
private List<Condition> mConditions;
private List<Tile> mSuggestions;
private boolean mCombineSuggestionAndCondition;
public Builder() {
}
@@ -433,10 +327,7 @@ public class DashboardData {
mCategories = dashboardData.mCategories;
mConditions = dashboardData.mConditions;
mSuggestions = dashboardData.mSuggestions;
mSuggestionMode = dashboardData.mSuggestionMode;
mExpandedCondition = dashboardData.mExpandedCondition;
mSuggestionConditionMode = dashboardData.mSuggestionConditionMode;
mCombineSuggestionAndCondition = dashboardData.mCombineSuggestionAndCondition;
}
public Builder setCategories(List<DashboardCategory> categories) {
@@ -454,27 +345,11 @@ public class DashboardData {
return this;
}
public Builder setSuggestionMode(int suggestionMode) {
this.mSuggestionMode = suggestionMode;
return this;
}
@Deprecated
public Builder setExpandedCondition(Condition expandedCondition) {
this.mExpandedCondition = expandedCondition;
return this;
}
public Builder setSuggestionConditionMode(@HeaderMode int mode) {
this.mSuggestionConditionMode = mode;
return this;
}
public Builder setCombineSuggestionAndCondition(boolean combine) {
this.mCombineSuggestionAndCondition = combine;
return this;
}
public DashboardData build() {
return new DashboardData(this);
}
@@ -513,16 +388,6 @@ public class DashboardData {
return mOldItems.get(oldItemPosition).equals(mNewItems.get(newItemPosition));
}
// not needed in combined UI
@Deprecated
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
if (mOldItems.get(oldItemPosition).type == Item.TYPE_CONDITION_CARD) {
return "condition"; // return anything but null to mark the payload
}
return null;
}
}
/**
@@ -532,24 +397,17 @@ public class DashboardData {
// valid types in field type
private static final int TYPE_DASHBOARD_CATEGORY = R.layout.dashboard_category;
private static final int TYPE_DASHBOARD_TILE = R.layout.dashboard_tile;
@Deprecated
private static final int TYPE_SUGGESTION_HEADER = R.layout.suggestion_header;
@Deprecated
private static final int TYPE_SUGGESTION_TILE = R.layout.suggestion_tile;
private static final int TYPE_SUGGESTION_CONDITION_CONTAINER =
R.layout.suggestion_condition_container;
private static final int TYPE_SUGGESTION_CONDITION_HEADER =
R.layout.suggestion_condition_header;
@Deprecated
private static final int TYPE_CONDITION_CARD = R.layout.condition_card;
private static final int TYPE_SUGGESTION_CONDITION_FOOTER =
R.layout.suggestion_condition_footer;
private static final int TYPE_DASHBOARD_SPACER = R.layout.dashboard_spacer;
@IntDef({TYPE_DASHBOARD_CATEGORY, TYPE_DASHBOARD_TILE, TYPE_SUGGESTION_HEADER,
TYPE_SUGGESTION_TILE, TYPE_SUGGESTION_CONDITION_CONTAINER,
TYPE_SUGGESTION_CONDITION_HEADER, TYPE_CONDITION_CARD,
TYPE_SUGGESTION_CONDITION_FOOTER, TYPE_DASHBOARD_SPACER})
@IntDef({TYPE_DASHBOARD_CATEGORY, TYPE_DASHBOARD_TILE, TYPE_SUGGESTION_CONDITION_CONTAINER,
TYPE_SUGGESTION_CONDITION_HEADER, TYPE_SUGGESTION_CONDITION_FOOTER,
TYPE_DASHBOARD_SPACER})
@Retention(RetentionPolicy.SOURCE)
public @interface ItemTypes{}
@@ -571,23 +429,10 @@ public class DashboardData {
*/
public final int id;
/**
* To store whether the condition is expanded, useless when {@link #type} is not
* {@link #TYPE_CONDITION_CARD}
*/
@Deprecated
public final boolean conditionExpanded;
@Deprecated
public Item(Object entity, @ItemTypes int type, int id, boolean conditionExpanded) {
public Item(Object entity, @ItemTypes int type, int id) {
this.entity = entity;
this.type = type;
this.id = id;
this.conditionExpanded = conditionExpanded;
}
public Item(Object entity, @ItemTypes int type, int id) {
this(entity, type, id, false);
}
/**
@@ -622,12 +467,6 @@ public class DashboardData {
// Only check title and summary for dashboard tile
return TextUtils.equals(localTile.title, targetTile.title)
&& TextUtils.equals(localTile.summary, targetTile.summary);
case TYPE_CONDITION_CARD:
// First check conditionExpanded for quick return
if (conditionExpanded != targetItem.conditionExpanded) {
return false;
}
// After that, go to default to do final check
default:
return entity == null ? targetItem.entity == null
: entity.equals(targetItem.entity);
@@ -635,46 +474,6 @@ public class DashboardData {
}
}
/**
* This class contains the data needed to build the header. The data can also be
* used to check the diff in DiffUtil.Callback
*/
public static class SuggestionHeaderData {
public final boolean hasMoreSuggestions;
public final int suggestionSize;
public final int undisplayedSuggestionCount;
public SuggestionHeaderData(boolean moreSuggestions, int suggestionSize, int
undisplayedSuggestionCount) {
this.hasMoreSuggestions = moreSuggestions;
this.suggestionSize = suggestionSize;
this.undisplayedSuggestionCount = undisplayedSuggestionCount;
}
public SuggestionHeaderData() {
hasMoreSuggestions = false;
suggestionSize = 0;
undisplayedSuggestionCount = 0;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof SuggestionHeaderData)) {
return false;
}
SuggestionHeaderData targetData = (SuggestionHeaderData) obj;
return hasMoreSuggestions == targetData.hasMoreSuggestions
&& suggestionSize == targetData.suggestionSize
&& undisplayedSuggestionCount == targetData.undisplayedSuggestionCount;
}
}
/**
* This class contains the data needed to build the suggestion/condition header. The data can
* also be used to check the diff in DiffUtil.Callback

View File

@@ -43,21 +43,16 @@ public class DashboardDecorator extends RecyclerView.ItemDecoration {
for (int i = 1; i < childCount; i++) {
final View child = parent.getChildAt(i);
final ViewHolder holder = parent.getChildViewHolder(child);
if (holder.getItemViewType() == R.layout.dashboard_category) {
if (parent.getChildViewHolder(parent.getChildAt(i - 1)).getItemViewType()
!= R.layout.dashboard_tile) {
continue;
}
} else if (holder.getItemViewType() != R.layout.condition_card) {
continue;
}
if (holder.getItemViewType() == R.layout.dashboard_category
&& parent.getChildViewHolder(parent.getChildAt(i - 1)).getItemViewType()
== R.layout.dashboard_tile) {
int top = getChildTop(child);
mDivider.setBounds(child.getLeft(), top, child.getRight(),
top + mDivider.getIntrinsicHeight());
mDivider.draw(c);
}
}
}
private int getChildTop(View child) {
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child

View File

@@ -95,9 +95,4 @@ public interface DashboardFeatureProvider {
*/
void openTileIntent(Activity activity, Tile tile);
/**
* Whether or not we should use new UI that combines the settings suggestions and conditions.
*/
boolean combineSuggestionAndCondition();
}

View File

@@ -206,11 +206,6 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
launchIntentOrSelectProfile(activity, tile, intent, MetricsEvent.DASHBOARD_SUMMARY);
}
@Override
public boolean combineSuggestionAndCondition() {
return false;
}
private void launchIntentOrSelectProfile(Activity activity, Tile tile, Intent intent,
int sourceMetricCategory) {
if (!isIntentResolvable(intent)) {

View File

@@ -32,7 +32,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.core.InstrumentedFragment;
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.ConditionManager.ConditionListener;
import com.android.settings.dashboard.conditional.FocusRecyclerView;
@@ -75,7 +74,6 @@ public class DashboardSummary extends InstrumentedFragment
private DashboardFeatureProvider mDashboardFeatureProvider;
private SuggestionFeatureProvider mSuggestionFeatureProvider;
private boolean isOnCategoriesChangedCalled;
private SuggestionDismissController mSuggestionDismissHandler;
@Override
public int getMetricsCategory() {
@@ -198,11 +196,6 @@ public class DashboardSummary extends InstrumentedFragment
mAdapter = new DashboardAdapter(getContext(), bundle, mConditionManager.getConditions(),
mSuggestionParser, this /* SuggestionDismissController.Callback */);
mDashboard.setAdapter(mAdapter);
if (!mDashboardFeatureProvider.combineSuggestionAndCondition()) {
mSuggestionDismissHandler = new SuggestionDismissController(
getContext(), mDashboard, mSuggestionParser, this);
ConditionAdapterUtils.addDismiss(mDashboard);
}
mDashboard.setItemAnimator(new DashboardItemAnimator());
mSummaryLoader.setSummaryConsumer(mAdapter);
if (DEBUG_TIMING) {

View File

@@ -17,16 +17,23 @@ package com.android.settings.dashboard.conditional;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.dashboard.DashboardAdapter;
import com.android.settings.dashboard.DashboardAdapter.DashboardItemHolder;
import com.android.settings.dashboard.DashboardData;
import com.android.settings.dashboard.DashboardData.HeaderMode;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.WirelessUtils;
import java.util.List;
import java.util.Objects;
@@ -77,8 +84,7 @@ public class ConditionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
@Override
public void onBindViewHolder(DashboardItemHolder holder, int position) {
// TODO: merge methods from ConditionAdapterUtils into this class
ConditionAdapterUtils.bindViews(mConditions.get(position), holder,
bindViews(mConditions.get(position), holder,
position == mConditions.size() - 1, mConditionClickListener);
}
@@ -100,4 +106,78 @@ public class ConditionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
return 0;
}
public void addDismissHandling(final RecyclerView recyclerView) {
ItemTouchHelper.SimpleCallback callback = new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.START | ItemTouchHelper.END) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
return true;
}
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
return viewHolder.getItemViewType() == R.layout.condition_tile_new_ui
? super.getSwipeDirs(recyclerView, viewHolder) : 0;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
Object item = getItem(viewHolder.getItemId());
((Condition) item).silence();
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(recyclerView);
}
private void bindViews(final Condition condition,
DashboardAdapter.DashboardItemHolder view, boolean isLastItem,
View.OnClickListener onClickListener) {
if (condition instanceof AirplaneModeCondition) {
Log.d(TAG, "Airplane mode condition has been bound with "
+ "isActive=" + condition.isActive() + ". Airplane mode is currently " +
WirelessUtils.isAirplaneModeOn(condition.mManager.getContext()));
}
View card = view.itemView.findViewById(R.id.content);
card.setTag(condition);
card.setOnClickListener(onClickListener);
view.icon.setImageIcon(condition.getIcon());
view.title.setText(condition.getTitle());
CharSequence[] actions = condition.getActions();
final boolean hasButtons = actions.length > 0;
setViewVisibility(view.itemView, R.id.buttonBar, hasButtons);
view.summary.setText(condition.getSummary());
for (int i = 0; i < 2; i++) {
Button button = (Button) view.itemView.findViewById(i == 0
? R.id.first_action : R.id.second_action);
if (actions.length > i) {
button.setVisibility(View.VISIBLE);
button.setText(actions[i]);
final int index = i;
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
FeatureFactory.getFactory(context).getMetricsFeatureProvider()
.action(context, MetricsEvent.ACTION_SETTINGS_CONDITION_BUTTON,
condition.getMetricsConstant());
condition.onActionClick(index);
}
});
} else {
button.setVisibility(View.GONE);
}
}
setViewVisibility(view.itemView, R.id.divider, !isLastItem);
}
private void setViewVisibility(View containerView, int viewId, boolean visible) {
View view = containerView.findViewById(viewId);
if (view != null) {
view.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
}

View File

@@ -1,179 +0,0 @@
/*
* Copyright (C) 2015 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.conditional;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardAdapter;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.WirelessUtils;
public class ConditionAdapterUtils {
private static final String TAG = "ConditionAdapterUtils";
public static void addDismiss(final RecyclerView recyclerView) {
ItemTouchHelper.SimpleCallback callback = new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.START | ItemTouchHelper.END) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
return true;
}
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
return viewHolder.getItemViewType() == R.layout.condition_card
|| viewHolder.getItemViewType() == R.layout.condition_tile_new_ui
? super.getSwipeDirs(recyclerView, viewHolder) : 0;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
Object item;
if (viewHolder.getItemViewType() == R.layout.condition_card) {
DashboardAdapter adapter = (DashboardAdapter) recyclerView.getAdapter();
item = adapter.getItem(viewHolder.getItemId());
} else {
ConditionAdapter adapter = (ConditionAdapter) recyclerView.getAdapter();
item = adapter.getItem(viewHolder.getItemId());
}
((Condition) item).silence();
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(recyclerView);
}
@Deprecated
public static void bindViews(final Condition condition,
DashboardAdapter.DashboardItemHolder view, boolean isExpanded,
View.OnClickListener onClickListener, View.OnClickListener onExpandListener) {
if (condition instanceof AirplaneModeCondition) {
Log.d(TAG, "Airplane mode condition has been bound with "
+ "isActive=" + condition.isActive() + ". Airplane mode is currently " +
WirelessUtils.isAirplaneModeOn(condition.mManager.getContext()));
}
View card = view.itemView.findViewById(R.id.content);
card.setTag(condition);
card.setOnClickListener(onClickListener);
view.icon.setImageIcon(condition.getIcon());
view.title.setText(condition.getTitle());
final View collapsedGroup = view.itemView.findViewById(R.id.collapsed_group);
collapsedGroup.setTag(condition);
final ImageView expand = (ImageView) view.itemView.findViewById(R.id.expand_indicator);
expand.setImageResource(isExpanded ? R.drawable.ic_expand_less : R.drawable.ic_expand_more);
expand.setContentDescription(expand.getContext().getString(isExpanded
? R.string.condition_expand_hide : R.string.condition_expand_show));
collapsedGroup.setOnClickListener(onExpandListener);
View detailGroup = view.itemView.findViewById(R.id.detail_group);
CharSequence[] actions = condition.getActions();
if (isExpanded != (detailGroup.getVisibility() == View.VISIBLE)) {
if (isExpanded) {
final boolean hasButtons = actions.length > 0;
setViewVisibility(detailGroup, R.id.divider, hasButtons);
setViewVisibility(detailGroup, R.id.buttonBar, hasButtons);
detailGroup.setVisibility(View.VISIBLE);
} else {
detailGroup.setVisibility(View.GONE);
}
}
if (isExpanded) {
view.summary.setText(condition.getSummary());
for (int i = 0; i < 2; i++) {
Button button = (Button) detailGroup.findViewById(i == 0
? R.id.first_action : R.id.second_action);
if (actions.length > i) {
button.setVisibility(View.VISIBLE);
button.setText(actions[i]);
final int index = i;
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
FeatureFactory.getFactory(context).getMetricsFeatureProvider()
.action(context, MetricsEvent.ACTION_SETTINGS_CONDITION_BUTTON,
condition.getMetricsConstant());
condition.onActionClick(index);
}
});
} else {
button.setVisibility(View.GONE);
}
}
}
}
public static void bindViews(final Condition condition,
DashboardAdapter.DashboardItemHolder view, boolean isLastItem,
View.OnClickListener onClickListener) {
if (condition instanceof AirplaneModeCondition) {
Log.d(TAG, "Airplane mode condition has been bound with "
+ "isActive=" + condition.isActive() + ". Airplane mode is currently " +
WirelessUtils.isAirplaneModeOn(condition.mManager.getContext()));
}
View card = view.itemView.findViewById(R.id.content);
card.setTag(condition);
card.setOnClickListener(onClickListener);
view.icon.setImageIcon(condition.getIcon());
view.title.setText(condition.getTitle());
CharSequence[] actions = condition.getActions();
final boolean hasButtons = actions.length > 0;
setViewVisibility(view.itemView, R.id.buttonBar, hasButtons);
view.summary.setText(condition.getSummary());
for (int i = 0; i < 2; i++) {
Button button = (Button) view.itemView.findViewById(i == 0
? R.id.first_action : R.id.second_action);
if (actions.length > i) {
button.setVisibility(View.VISIBLE);
button.setText(actions[i]);
final int index = i;
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
FeatureFactory.getFactory(context).getMetricsFeatureProvider()
.action(context, MetricsEvent.ACTION_SETTINGS_CONDITION_BUTTON,
condition.getMetricsConstant());
condition.onActionClick(index);
}
});
} else {
button.setVisibility(View.GONE);
}
}
setViewVisibility(view.itemView, R.id.divider, !isLastItem);
}
private static void setViewVisibility(View containerView, int viewId, boolean visible) {
View view = containerView.findViewById(viewId);
if (view != null) {
view.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
}

View File

@@ -23,7 +23,6 @@ import android.view.View;
import android.view.ViewGroup;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.R.layout;
import com.android.settings.SettingsActivity;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.dashboard.DashboardAdapter.DashboardItemHolder;
@@ -114,7 +113,10 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
@Override
public int getItemViewType(int position) {
return layout.suggestion_tile_new_ui;
Tile suggestion = getSuggestion(position);
return suggestion.remoteViews != null
? R.layout.suggestion_tile_card
: R.layout.suggestion_tile_new_ui;
}
@Override

View File

@@ -66,8 +66,7 @@ public class SuggestionDismissController extends ItemTouchHelper.SimpleCallback
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
final int layoutId = viewHolder.getItemViewType();
if (layoutId == R.layout.suggestion_tile
|| layoutId == R.layout.suggestion_tile_new_ui
if (layoutId == R.layout.suggestion_tile_new_ui
|| layoutId == R.layout.suggestion_tile_card) {
// Only return swipe direction for suggestion tiles. All other types are not swipeable.
return super.getSwipeDirs(recyclerView, viewHolder);

View File

@@ -1,74 +0,0 @@
/*
* Copyright (C) 2016 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.conditional;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.dashboard.DashboardAdapter;
import com.android.settings.dashboard.conditional.Condition;
import com.android.settings.dashboard.conditional.ConditionAdapterUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import com.android.settings.R;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
// Not needed in new UI as the view is always expanded
@Deprecated
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ConditionAdapterUtilsTest{
@Mock
private Condition mCondition;
private DashboardAdapter.DashboardItemHolder mViewHolder;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
final CharSequence[] actions = new CharSequence[2];
when(mCondition.getActions()).thenReturn(actions);
final View view = LayoutInflater.from(mContext).inflate(R.layout.condition_card, new
LinearLayout(mContext), true);
mViewHolder = new DashboardAdapter.DashboardItemHolder(view);
}
@Test
public void testBindView_isExpanded_returnVisible() {
ConditionAdapterUtils.bindViews(mCondition, mViewHolder, true, null, null);
assertThat(mViewHolder.itemView.findViewById(R.id.detail_group).getVisibility())
.isEqualTo(View.VISIBLE);
}
@Test
public void testBindView_isNotExpanded_returnGone() {
ConditionAdapterUtils.bindViews(mCondition, mViewHolder, false, null, null);
assertThat(mViewHolder.itemView.findViewById(R.id.detail_group).getVisibility())
.isEqualTo(View.GONE);
}
}

View File

@@ -38,15 +38,10 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Icon;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.RelativeLayout;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -71,7 +66,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import java.util.ArrayList;
import java.util.Collections;
@@ -101,8 +95,8 @@ public class DashboardAdapterTest {
private ArgumentCaptor<String> mActionPackageCaptor = ArgumentCaptor.forClass(String.class);
private FakeFeatureFactory mFactory;
private DashboardAdapter mDashboardAdapter;
private DashboardAdapter.DashboardItemHolder mSuggestionHolder;
private DashboardData.SuggestionHeaderData mSuggestionHeaderData;
private DashboardAdapter.SuggestionAndConditionHeaderHolder mSuggestionHolder;
private DashboardData.SuggestionConditionHeaderData mSuggestionHeaderData;
@Before
public void setUp() {
@@ -121,8 +115,10 @@ public class DashboardAdapterTest {
when(mResources.getQuantityString(any(int.class), any(int.class), any()))
.thenReturn("");
mDashboardAdapter = new DashboardAdapter(mContext, null, null);
mSuggestionHeaderData = new DashboardData.SuggestionHeaderData(true, 1, 0);
List<Condition> conditions = new ArrayList<>();
conditions.add(mCondition);
mDashboardAdapter = new DashboardAdapter(mContext, null, conditions, null, null);
mSuggestionHeaderData = new DashboardData.SuggestionConditionHeaderData(conditions, 1);
when(mView.getTag()).thenReturn(mCondition);
}
@@ -161,8 +157,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_Expanded() {
setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3"));
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
verify(mFactory.metricsFeatureProvider, times(3)).action(
any(Context.class), mActionCategoryCaptor.capture(),
@@ -180,8 +175,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_ExpandedAndPaused() {
setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3"));
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
mDashboardAdapter.onPause();
verify(mFactory.metricsFeatureProvider, times(6)).action(
@@ -204,8 +198,7 @@ public class DashboardAdapterTest {
public void testSuggestionsLogs_ExpandedAfterPause() {
setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3"));
mDashboardAdapter.onPause();
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
verify(mFactory.metricsFeatureProvider, times(7)).action(
any(Context.class), mActionCategoryCaptor.capture(),
@@ -229,8 +222,7 @@ public class DashboardAdapterTest {
public void testSuggestionsLogs_ExpandedAfterPauseAndPausedAgain() {
setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3"));
mDashboardAdapter.onPause();
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
mDashboardAdapter.onPause();
verify(mFactory.metricsFeatureProvider, times(10)).action(
@@ -257,8 +249,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_ExpandedWithLessThanDefaultShown() {
setupSuggestions(makeSuggestions("pkg1"));
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
verify(mFactory.metricsFeatureProvider, times(1)).action(
any(Context.class), mActionCategoryCaptor.capture(),
@@ -274,8 +265,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_ExpandedWithLessThanDefaultShownAndPaused() {
setupSuggestions(makeSuggestions("pkg1"));
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
mDashboardAdapter.onPause();
verify(mFactory.metricsFeatureProvider, times(2)).action(
@@ -294,8 +284,7 @@ public class DashboardAdapterTest {
public void testSuggestionsLogs_ExpandedWithLessThanDefaultShownAfterPause() {
setupSuggestions(makeSuggestions("pkg1"));
mDashboardAdapter.onPause();
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
verify(mFactory.metricsFeatureProvider, times(3)).action(
any(Context.class), mActionCategoryCaptor.capture(),
@@ -314,8 +303,7 @@ public class DashboardAdapterTest {
public void testSuggestionsLogs_ExpandedWithLessThanDefaultShownAfterPauseAndPausedAgain() {
setupSuggestions(makeSuggestions("pkg1"));
mDashboardAdapter.onPause();
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
mDashboardAdapter.onPause();
verify(mFactory.metricsFeatureProvider, times(4)).action(
@@ -333,81 +321,9 @@ public class DashboardAdapterTest {
}
@Test
public void testBindViewHolder_inflateRemoteView() {
List<Tile> packages = makeSuggestions("pkg1");
RemoteViews remoteViews = mock(RemoteViews.class);
TextView textView = new TextView(RuntimeEnvironment.application);
doReturn(textView).when(remoteViews).apply(any(Context.class), any(ViewGroup.class));
packages.get(0).remoteViews = remoteViews;
mDashboardAdapter.setCategoriesAndSuggestions(Collections.emptyList(), packages);
mSuggestionHolder = mDashboardAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
R.layout.suggestion_tile_card);
mDashboardAdapter.onBindViewHolder(mSuggestionHolder, 1);
assertThat(textView.getParent()).isSameAs(mSuggestionHolder.itemView);
mSuggestionHolder.itemView.performClick();
verify(mContext).startSuggestion(any(Intent.class));
}
@Test
public void testBindViewHolder_primaryViewHandlesClick() {
Context context =
new ContextThemeWrapper(RuntimeEnvironment.application, R.style.Theme_Settings);
List<Tile> packages = makeSuggestions("pkg1");
RemoteViews remoteViews = mock(RemoteViews.class);
FrameLayout layout = new FrameLayout(context);
Button primary = new Button(context);
primary.setId(android.R.id.primary);
layout.addView(primary);
doReturn(layout).when(remoteViews).apply(any(Context.class), any(ViewGroup.class));
packages.get(0).remoteViews = remoteViews;
mDashboardAdapter.setCategoriesAndSuggestions(Collections.emptyList(), packages);
mSuggestionHolder = mDashboardAdapter.onCreateViewHolder(
new FrameLayout(context),
R.layout.suggestion_tile_card);
mDashboardAdapter.onBindViewHolder(mSuggestionHolder, 1);
mSuggestionHolder.itemView.performClick();
assertThat(ShadowApplication.getInstance().getNextStartedActivity()).isNull();
verify(mContext, never()).startSuggestion(any(Intent.class));
primary.performClick();
verify(mContext).startSuggestion(any(Intent.class));
}
@Test
public void testBindViewHolder_viewsClearedOnRebind() {
Context context =
new ContextThemeWrapper(RuntimeEnvironment.application, R.style.Theme_Settings);
List<Tile> packages = makeSuggestions("pkg1");
RemoteViews remoteViews = mock(RemoteViews.class);
FrameLayout layout = new FrameLayout(context);
Button primary = new Button(context);
primary.setId(android.R.id.primary);
layout.addView(primary);
doReturn(layout).when(remoteViews).apply(any(Context.class), any(ViewGroup.class));
packages.get(0).remoteViews = remoteViews;
mDashboardAdapter.setCategoriesAndSuggestions(Collections.emptyList(), packages);
mSuggestionHolder = mDashboardAdapter.onCreateViewHolder(
new FrameLayout(context),
R.layout.suggestion_tile_card);
mDashboardAdapter.onBindViewHolder(mSuggestionHolder, 1);
mDashboardAdapter.onBindViewHolder(mSuggestionHolder, 1);
ViewGroup itemView = (ViewGroup) mSuggestionHolder.itemView;
assertThat(itemView.getChildCount()).isEqualTo(1);
}
@Test
public void testSuggestionDismissed_notOnlySuggestion_doNothing() {
final DashboardAdapter adapter = spy(new DashboardAdapter(mContext, null, null));
public void testSuggestioDismissed_notOnlySuggestion_doNothing() {
final DashboardAdapter adapter =
spy(new DashboardAdapter(mContext, null, null, null, null));
adapter.setCategoriesAndSuggestions(
new ArrayList<>(), makeSuggestions("pkg1", "pkg2", "pkg3"));
final DashboardData dashboardData = adapter.mDashboardData;
@@ -420,8 +336,9 @@ public class DashboardAdapterTest {
}
@Test
public void testSuggestionDismissed_onlySuggestion_updateDashboardData() {
DashboardAdapter adapter = spy(new DashboardAdapter(mContext, null, null));
public void testSuggestioDismissed_onlySuggestion_updateDashboardData() {
DashboardAdapter adapter =
spy(new DashboardAdapter(mContext, null, null, null, null));
adapter.setCategoriesAndSuggestions(new ArrayList<>(), makeSuggestions("pkg1"));
final DashboardData dashboardData = adapter.mDashboardData;
reset(adapter); // clear interactions tracking
@@ -450,8 +367,7 @@ public class DashboardAdapterTest {
@Test
public void testBindConditionAndSuggestion_shouldSetSuggestionAdapterAndNoCrash() {
when(mFactory.dashboardFeatureProvider.combineSuggestionAndCondition()).thenReturn(true);
mDashboardAdapter = new DashboardAdapter(mContext, null, null);
mDashboardAdapter = new DashboardAdapter(mContext, null, null, null, null);
final List<Tile> suggestions = makeSuggestions("pkg1");
final List<DashboardCategory> categories = new ArrayList<>();
final DashboardCategory category = mock(DashboardCategory.class);
@@ -489,8 +405,9 @@ public class DashboardAdapterTest {
private void setupSuggestions(List<Tile> suggestions) {
mDashboardAdapter.setCategoriesAndSuggestions(new ArrayList<>(), suggestions);
mSuggestionHolder = mDashboardAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mDashboardAdapter.getItemViewType(1));
final Context context = RuntimeEnvironment.application;
mSuggestionHolder = new DashboardAdapter.SuggestionAndConditionHeaderHolder(
LayoutInflater.from(context).inflate(
R.layout.suggestion_condition_header, new RelativeLayout(context), true));
}
}

View File

@@ -94,7 +94,6 @@ public class DashboardDataTest {
.setCategories(categories)
.setSuggestions(suggestions)
.setSuggestionConditionMode(DashboardData.HEADER_MODE_FULLY_EXPANDED)
.setCombineSuggestionAndCondition(true)
.build();
mDashboardDataWithTwoConditions = new DashboardData.Builder()
@@ -102,7 +101,6 @@ public class DashboardDataTest {
.setCategories(categories)
.setSuggestions(suggestions)
.setSuggestionConditionMode(DashboardData.HEADER_MODE_FULLY_EXPANDED)
.setCombineSuggestionAndCondition(true)
.build();
mDashboardDataWithNoItems = new DashboardData.Builder()
@@ -127,9 +125,7 @@ public class DashboardDataTest {
.isEqualTo(expectedSize);
for (int i = 0; i < expectedSize; i++) {
final Object item = mDashboardDataWithOneConditions.getItemEntityByPosition(i);
if (item instanceof DashboardData.SuggestionHeaderData
|| item instanceof List) {
// SuggestionHeaderData is created inside when build, we can only use isEqualTo
if (item instanceof List) {
assertThat(item).isEqualTo(expectedObjects[i]);
} else if (item instanceof DashboardData.SuggestionConditionHeaderData) {
DashboardData.SuggestionConditionHeaderData i1 =

View File

@@ -38,7 +38,6 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

View File

@@ -15,16 +15,26 @@
*/
package com.android.settings.dashboard.suggestions;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ContextThemeWrapper;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.dashboard.DashboardAdapter;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.drawer.Tile;
import java.util.ArrayList;
@@ -33,15 +43,20 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
@RunWith(SettingsRobolectricTestRunner.class)
@@ -51,9 +66,12 @@ public class SuggestionAdapterTest {
private Tile mSuggestion1;
@Mock
private Tile mSuggestion2;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private SettingsActivity mActivity;
private Context mContext;
private SuggestionAdapter mSuggestionAdapter;
private DashboardAdapter.DashboardItemHolder mSuggestionHolder;
private List<Tile> mOneSuggestion;
private List<Tile> mTwoSuggestions;
@@ -61,6 +79,8 @@ public class SuggestionAdapterTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
FakeFeatureFactory.setupForTest(mActivity);
mSuggestion1.title = "Test Suggestion 1";
mSuggestion1.icon = mock(Icon.class);
mSuggestion2.title = "Test Suggestion 2";
@@ -92,13 +112,96 @@ public class SuggestionAdapterTest {
public void onBindViewHolder_shouldSetListener() {
final View view = spy(LayoutInflater.from(mContext).inflate(
R.layout.suggestion_tile_new_ui, new LinearLayout(mContext), true));
final DashboardAdapter.DashboardItemHolder viewHolder =
new DashboardAdapter.DashboardItemHolder(view);
mSuggestionHolder = new DashboardAdapter.DashboardItemHolder(view);
mSuggestionAdapter = new SuggestionAdapter(mContext, mOneSuggestion, new ArrayList<>());
mSuggestionAdapter.onBindViewHolder(viewHolder, 0);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
verify(view).setOnClickListener(any(View.OnClickListener.class));
}
@Test
public void onBindViewHolder_shouldInflateRemoteView() {
List<Tile> packages = makeSuggestions("pkg1");
RemoteViews remoteViews = mock(RemoteViews.class);
TextView textView = new TextView(RuntimeEnvironment.application);
doReturn(textView).when(remoteViews).apply(any(Context.class), any(ViewGroup.class));
packages.get(0).remoteViews = remoteViews;
setupSuggestions(mActivity, packages);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
assertThat(textView.getParent()).isSameAs(mSuggestionHolder.itemView);
mSuggestionHolder.itemView.performClick();
verify(mActivity).startSuggestion(any(Intent.class));
}
@Test
public void onBindViewHolder_primaryViewShouldHandleClick() {
Context context =
new ContextThemeWrapper(RuntimeEnvironment.application, R.style.Theme_Settings);
List<Tile> packages = makeSuggestions("pkg1");
RemoteViews remoteViews = mock(RemoteViews.class);
FrameLayout layout = new FrameLayout(context);
Button primary = new Button(context);
primary.setId(android.R.id.primary);
layout.addView(primary);
doReturn(layout).when(remoteViews).apply(any(Context.class), any(ViewGroup.class));
packages.get(0).remoteViews = remoteViews;
setupSuggestions(mActivity, packages);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
mSuggestionHolder.itemView.performClick();
assertThat(ShadowApplication.getInstance().getNextStartedActivity()).isNull();
verify(mActivity, never()).startSuggestion(any(Intent.class));
primary.performClick();
verify(mActivity).startSuggestion(any(Intent.class));
}
@Test
public void onBindViewHolder_viewsShouldClearOnRebind() {
Context context =
new ContextThemeWrapper(RuntimeEnvironment.application, R.style.Theme_Settings);
List<Tile> packages = makeSuggestions("pkg1");
RemoteViews remoteViews = mock(RemoteViews.class);
FrameLayout layout = new FrameLayout(context);
Button primary = new Button(context);
primary.setId(android.R.id.primary);
layout.addView(primary);
doReturn(layout).when(remoteViews).apply(any(Context.class), any(ViewGroup.class));
packages.get(0).remoteViews = remoteViews;
setupSuggestions(mActivity, packages);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
ViewGroup itemView = (ViewGroup) mSuggestionHolder.itemView;
assertThat(itemView.getChildCount()).isEqualTo(1);
}
private void setupSuggestions(Context context, List<Tile> suggestions) {
mSuggestionAdapter = new SuggestionAdapter(context, suggestions, new ArrayList<>());
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
}
private List<Tile> makeSuggestions(String... pkgNames) {
final List<Tile> suggestions = new ArrayList<>();
for (String pkgName : pkgNames) {
Tile suggestion = new Tile();
suggestion.intent = new Intent("action");
suggestion.intent.setComponent(new ComponentName(pkgName, "cls"));
suggestions.add(suggestion);
suggestion.icon = mock(Icon.class);
}
return suggestions;
}
}

View File

@@ -80,7 +80,7 @@ public class SuggestionDismissControllerTest {
@Test
public void getSwipeDirs_isSuggestionTile_shouldReturnDirection() {
final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
when(vh.getItemViewType()).thenReturn(R.layout.suggestion_tile);
when(vh.getItemViewType()).thenReturn(R.layout.suggestion_tile_new_ui);
assertThat(mController.getSwipeDirs(mRecyclerView, vh))
.isEqualTo(ItemTouchHelper.START | ItemTouchHelper.END);
@@ -98,7 +98,7 @@ public class SuggestionDismissControllerTest {
@Test
public void getSwipeDirs_isNotSuggestionTile_shouldReturn0() {
final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
when(vh.getItemViewType()).thenReturn(R.layout.condition_card);
when(vh.getItemViewType()).thenReturn(R.layout.condition_tile_new_ui);
assertThat(mController.getSwipeDirs(mRecyclerView, vh))
.isEqualTo(0);