Update new UI of conditional cards

- Add half-width and full-width layouts for conditional cards
- Keep origin strings of conditional cards, that could make conditional
cards truncate its title and summary in half-width card.
- Add default value of isHalfWidth to each condition controller.

Bug: 113451905
Test: robotests, visual
Change-Id: Ib0055f32c4ab9e73c0e0a57c6b0ef586d52942e0
This commit is contained in:
Mill Chen
2018-11-05 17:20:22 +08:00
parent d20641059f
commit 0ca7130403
19 changed files with 237 additions and 111 deletions

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 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.
-->
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/ContextualCardStyle">
<LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="@dimen/homepage_condition_full_card_height"
android:paddingStart="@dimen/homepage_card_padding_start"
android:paddingEnd="@dimen/homepage_card_padding_end"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:id="@android:id/icon"
android:layout_width="@dimen/suggestion_card_icon_size"
android:layout_height="@dimen/suggestion_card_icon_size"
android:tint="?android:attr/colorAccent"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingStart="@dimen/homepage_condition_full_card_padding_start"
android:paddingEnd="@dimen/homepage_condition_full_card_padding_end"
android:orientation="vertical">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
style="@style/TextAppearance.ConditionCardTitle"/>
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/TextAppearance.ConditionCardSummary"/>
</LinearLayout>
<View
android:id="@+id/divider"
android:layout_width="@dimen/homepage_condition_full_card_divider_width"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/homepage_condition_full_card_divider_padding_top"
android:layout_marginBottom="@dimen/homepage_condition_full_card_divider_padding_bottom"
android:background="?android:attr/dividerVertical" />
<Button
android:id="@+id/first_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/ConditionFullCardBorderlessButton"/>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 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.
-->
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/homepage_condition_half_card_height"
style="@style/ContextualCardStyle">
<LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/homepage_card_padding_start"
android:paddingEnd="@dimen/homepage_card_padding_end"
android:paddingTop="@dimen/homepage_condition_half_card_padding_top"
android:orientation="vertical">
<ImageView
android:id="@android:id/icon"
android:layout_width="@dimen/suggestion_card_icon_size"
android:layout_height="@dimen/suggestion_card_icon_size"
android:tint="?android:attr/colorAccent"/>
<TextView
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/homepage_condition_half_card_title_margin_top"
android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
style="@style/TextAppearance.ConditionCardTitle"/>
<TextView
android:id="@android:id/summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextAppearance.ConditionCardSummary"/>
<include layout="@layout/horizontal_divider"/>
<Button
android:id="@+id/first_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/ConditionHalfCardBorderlessButton"/>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -1,97 +0,0 @@
<!--
Copyright (C) 2018 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.
-->
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/ContextualCardStyle">
<LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/condition_header_height"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal">
<ImageView
android:id="@android:id/icon"
android:layout_width="@dimen/suggestion_card_icon_size"
android:layout_height="@dimen/suggestion_card_icon_size"
android:layout_marginTop="12dp"
android:layout_marginStart="14dp"
android:layout_marginEnd="24dp"
android:tint="?android:attr/colorAccent"/>
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="14dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary"/>
</LinearLayout>
<TextView
android:id="@android:id/summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="62dp"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingBottom="8dp"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:alpha=".7"
android:textColor="?android:attr/textColorPrimary"/>
<androidx.appcompat.widget.ButtonBarLayout
android:id="@+id/buttonBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="62dp"
android:paddingBottom="1dp"
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/textColorPrimary"
style="?android:attr/buttonBarButtonStyle"/>
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</androidx.appcompat.widget.ButtonBarLayout>
<include layout="@layout/horizontal_divider"/>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -346,6 +346,16 @@
<!-- Signal icon in NetworkSelectSetting -->
<dimen name="signal_strength_icon_size">24dp</dimen>
<!-- Condition cards size and padding -->
<dimen name="homepage_condition_card_title_margin_bottom">2dp</dimen>
<dimen name="homepage_condition_half_card_height">150dp</dimen>
<dimen name="homepage_condition_half_card_padding_top">12dp</dimen>
<dimen name="homepage_condition_half_card_title_margin_top">12dp</dimen>
<dimen name="homepage_condition_full_card_height">72dp</dimen>
<dimen name="homepage_condition_full_card_padding_start">24dp</dimen>
<dimen name="homepage_condition_full_card_padding_end">24dp</dimen>
<dimen name="homepage_condition_full_card_divider_width">.75dp</dimen>
<dimen name="homepage_condition_full_card_divider_padding_top">12dp</dimen>
<dimen name="homepage_condition_full_card_divider_padding_bottom">12dp</dimen>
</resources>

View File

@@ -308,6 +308,16 @@
<item name="android:textColor">?android:attr/colorAccent</item>
</style>
<style name="TextAppearance.ConditionCardTitle"
parent="@android:style/TextAppearance.Material.Body2">
<item name="android:textSize">16sp</item>
</style>
<style name="TextAppearance.ConditionCardSummary"
parent="@android:style/TextAppearance.Material.Body1">
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
<style name="TextAppearance.EntityHeaderTitle"
parent="@android:style/TextAppearance.Material.Subhead">
<item name="android:textColor">?android:attr/textColorPrimary</item>
@@ -463,4 +473,24 @@
<item name="cardElevation">@dimen/homepage_card_elevation</item>
</style>
<style name="ConditionCardBorderlessButton"
parent="android:Widget.DeviceDefault.Button.Borderless">
<item name="android:textColor">?android:attr/colorAccent</item>
<item name="android:textSize">14sp</item>
<item name="android:textAllCaps">false</item>
<item name="android:fontFamily">sans-serif-medium</item>
</style>
<style name="ConditionHalfCardBorderlessButton"
parent="@style/ConditionCardBorderlessButton">
<item name="android:textAlignment">viewStart</item>
<item name="android:paddingStart">0dp</item>
</style>
<style name="ConditionFullCardBorderlessButton"
parent="@style/ConditionCardBorderlessButton">
<item name="android:textAlignment">viewEnd</item>
<item name="android:paddingEnd">0dp</item>
</style>
</resources>

View File

@@ -42,6 +42,7 @@ public class ContextualCard {
int CONDITIONAL = 3;
}
private final Builder mBuilder;
private final String mName;
@CardType
private final int mCardType;
@@ -142,7 +143,12 @@ public class ContextualCard {
return TextUtils.isEmpty(mSliceUri);
}
public Builder mutate() {
return mBuilder;
}
public ContextualCard(Builder builder) {
mBuilder = builder;
mName = builder.mName;
mCardType = builder.mCardType;
mRankingScore = builder.mRankingScore;
@@ -164,28 +170,47 @@ public class ContextualCard {
}
ContextualCard(Cursor c) {
mBuilder = new Builder();
mName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.NAME));
mBuilder.setName(mName);
mCardType = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.TYPE));
mBuilder.setCardType(mCardType);
mRankingScore = c.getDouble(c.getColumnIndex(CardDatabaseHelper.CardColumns.SCORE));
mBuilder.setRankingScore(mRankingScore);
mSliceUri = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.SLICE_URI));
mBuilder.setSliceUri(Uri.parse(mSliceUri));
mCategory = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.CATEGORY));
mBuilder.setCategory(mCategory);
mLocalizedToLocale = c.getString(
c.getColumnIndex(CardDatabaseHelper.CardColumns.LOCALIZED_TO_LOCALE));
mBuilder.setLocalizedToLocale(mLocalizedToLocale);
mPackageName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.PACKAGE_NAME));
mBuilder.setPackageName(mPackageName);
mAppVersion = c.getLong(c.getColumnIndex(CardDatabaseHelper.CardColumns.APP_VERSION));
mBuilder.setAppVersion(mAppVersion);
mTitleResName = c.getString(
c.getColumnIndex(CardDatabaseHelper.CardColumns.TITLE_RES_NAME));
mBuilder.setTitleResName(mTitleResName);
mTitleText = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.TITLE_TEXT));
mBuilder.setTitleText(mTitleText);
mSummaryResName = c.getString(
c.getColumnIndex(CardDatabaseHelper.CardColumns.SUMMARY_RES_NAME));
mBuilder.setSummaryResName(mSummaryResName);
mSummaryText = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.SUMMARY_TEXT));
mBuilder.setSummaryText(mSummaryText);
mIconResName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.ICON_RES_NAME));
mBuilder.setIconResName(mIconResName);
mIconResId = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.ICON_RES_ID));
mBuilder.setIconResId(mIconResId);
mCardAction = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.CARD_ACTION));
mBuilder.setCardAction(mCardAction);
mExpireTimeMS = c.getLong(c.getColumnIndex(CardDatabaseHelper.CardColumns.EXPIRE_TIME_MS));
mBuilder.setExpireTimeMS(mExpireTimeMS);
mIsHalfWidth = (c.getInt(
c.getColumnIndex(CardDatabaseHelper.CardColumns.SUPPORT_HALF_WIDTH)) == 1);
mBuilder.setIsHalfWidth(mIsHalfWidth);
mIconDrawable = null;
mBuilder.setIconDrawable(mIconDrawable);
}
@Override

View File

@@ -62,7 +62,11 @@ public class ContextualCardLookupTable {
static final Set<ControllerRendererMapping> LOOKUP_TABLE =
new TreeSet<ControllerRendererMapping>() {{
add(new ControllerRendererMapping(CardType.CONDITIONAL,
ConditionContextualCardRenderer.VIEW_TYPE,
ConditionContextualCardRenderer.HALF_WIDTH_VIEW_TYPE,
ConditionContextualCardController.class,
ConditionContextualCardRenderer.class));
add(new ControllerRendererMapping(CardType.CONDITIONAL,
ConditionContextualCardRenderer.FULL_WIDTH_VIEW_TYPE,
ConditionContextualCardController.class,
ConditionContextualCardRenderer.class));
add(new ControllerRendererMapping(CardType.SLICE,

View File

@@ -79,6 +79,7 @@ public class AirplaneModeConditionController implements ConditionalCardControlle
.setTitleText(mAppContext.getText(R.string.condition_airplane_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_airplane_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_airplanemode_active))
.setIsHalfWidth(true)
.build();
}

View File

@@ -73,6 +73,7 @@ public class BackgroundDataConditionController implements ConditionalCardControl
.setTitleText(mAppContext.getText(R.string.condition_bg_data_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_bg_data_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_data_saver))
.setIsHalfWidth(true)
.build();
}

View File

@@ -82,6 +82,7 @@ public class BatterySaverConditionController implements ConditionalCardControlle
.setTitleText(mAppContext.getText(R.string.condition_battery_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_battery_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_battery_saver_accent_24dp))
.setIsHalfWidth(true)
.build();
}

View File

@@ -89,6 +89,7 @@ public class CellularDataConditionController implements ConditionalCardControlle
.setTitleText(mAppContext.getText(R.string.condition_cellular_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_cellular_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_cellular_off))
.setIsHalfWidth(true)
.build();
}

View File

@@ -85,6 +85,14 @@ public class ConditionContextualCardController implements ContextualCardControll
public void onConditionsChanged() {
final List<ContextualCard> conditionCards = mConditionManager.getDisplayableCards();
final boolean isOddNumber = conditionCards.size() % 2 == 1;
if (isOddNumber) {
final int lastIndex = conditionCards.size() - 1;
final ConditionalContextualCard card = (ConditionalContextualCard) conditionCards.get(
lastIndex);
conditionCards.set(lastIndex, card.mutate().setIsHalfWidth(false).build());
}
if (mListener != null) {
final Map<Integer, List<ContextualCard>> conditionalCards = new ArrayMap<>();
conditionalCards.put(ContextualCard.CardType.CONDITIONAL, conditionCards);

View File

@@ -37,7 +37,8 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
* Card renderer for {@link ConditionalContextualCard}.
*/
public class ConditionContextualCardRenderer implements ContextualCardRenderer {
public static final int VIEW_TYPE = R.layout.homepage_condition_tile;
public static final int HALF_WIDTH_VIEW_TYPE = R.layout.homepage_condition_half_tile;
public static final int FULL_WIDTH_VIEW_TYPE = R.layout.homepage_condition_full_tile;
private final Context mContext;
private final ControllerRendererPool mControllerRendererPool;
@@ -50,7 +51,11 @@ public class ConditionContextualCardRenderer implements ContextualCardRenderer {
@Override
public int getViewType(boolean isHalfWidth) {
return VIEW_TYPE;
if (isHalfWidth) {
return HALF_WIDTH_VIEW_TYPE;
} else {
return FULL_WIDTH_VIEW_TYPE;
}
}
@Override
@@ -88,15 +93,12 @@ public class ConditionContextualCardRenderer implements ContextualCardRenderer {
view.icon.setImageDrawable(card.getIconDrawable());
view.title.setText(card.getTitleText());
view.summary.setText(card.getSummaryText());
setViewVisibility(view.itemView, R.id.divider, false);
}
private void initializeActionButton(ConditionalCardHolder view, ConditionalContextualCard card,
MetricsFeatureProvider metricsFeatureProvider) {
final CharSequence action = card.getActionText();
final boolean hasButtons = !TextUtils.isEmpty(action);
setViewVisibility(view.itemView, R.id.buttonBar, hasButtons);
final Button button = view.itemView.findViewById(R.id.first_action);
if (hasButtons) {
@@ -115,13 +117,6 @@ public class ConditionContextualCardRenderer implements ContextualCardRenderer {
}
}
private void setViewVisibility(View containerView, int viewId, boolean visible) {
View view = containerView.findViewById(viewId);
if (view != null) {
view.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
public static class ConditionalCardHolder extends RecyclerView.ViewHolder {
public final ImageView icon;

View File

@@ -100,6 +100,7 @@ public class DndConditionCardController implements ConditionalCardController {
.setTitleText(mAppContext.getText(R.string.condition_zen_title).toString())
.setSummaryText(getSummary().toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp))
.setIsHalfWidth(true)
.build();
}

View File

@@ -99,6 +99,7 @@ public class HotspotConditionController implements ConditionalCardController {
.setTitleText(mAppContext.getText(R.string.condition_hotspot_title).toString())
.setSummaryText(getSummary().toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_hotspot))
.setIsHalfWidth(true)
.build();
}

View File

@@ -78,6 +78,7 @@ public class NightDisplayConditionController implements ConditionalCardControlle
.setSummaryText(
mAppContext.getText(R.string.condition_night_display_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_settings_night_display))
.setIsHalfWidth(true)
.build();
}

View File

@@ -72,6 +72,7 @@ public class RingerMutedConditionController extends AbnormalRingerConditionContr
.setSummaryText(
mAppContext.getText(R.string.condition_device_muted_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_notifications_off_24dp))
.setIsHalfWidth(true)
.build();
}
}

View File

@@ -60,6 +60,7 @@ public class RingerVibrateConditionController extends AbnormalRingerConditionCon
.setSummaryText(
mAppContext.getText(R.string.condition_device_vibrate_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_volume_ringer_vibrate))
.setIsHalfWidth(true)
.build();
}
}

View File

@@ -93,6 +93,7 @@ public class WorkModeConditionController implements ConditionalCardController {
.setTitleText(mAppContext.getText(R.string.condition_work_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_work_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_signal_workmode_enable))
.setIsHalfWidth(true)
.build();
}