Add conditional cards to the new homepage.

Make existing Settings Conditions show up in the new homepage as custom
view.

Bug: 113451905
Test: robotests
Change-Id: Ic49089f95ff04442a887cda97481e945136f7209
This commit is contained in:
Emily Chuang
2018-08-29 19:47:00 +08:00
parent c21f4a512a
commit 307d209322
12 changed files with 641 additions and 33 deletions

View File

@@ -21,6 +21,9 @@ import android.util.Log;
import androidx.collection.ArraySet;
import com.android.settings.homepage.conditional.ConditionHomepageCardController;
import com.android.settings.homepage.conditional.ConditionHomepageCardRenderer;
import java.util.Set;
/**
@@ -80,19 +83,16 @@ public class ControllerRendererPool {
private HomepageCardController createCardController(Context context,
Class<? extends HomepageCardController> clz) {
/*
if (ConditionHomepageCardController.class == clz) {
return new ConditionHomepageCardController(context);
}
*/
return null;
}
private HomepageCardRenderer createCardRenderer(Context context, Class<?> clz) {
//if (ConditionHomepageCardRenderer.class == clz) {
// return new ConditionHomepageCardRenderer(context, this /*controllerRendererPool*/);
//}
if (ConditionHomepageCardRenderer.class == clz) {
return new ConditionHomepageCardRenderer(context, this /*controllerRendererPool*/);
}
return null;
}

View File

@@ -65,79 +65,79 @@ public class HomepageCard {
return mName;
}
int getCardType() {
public int getCardType() {
return mCardType;
}
double getRankingScore() {
public double getRankingScore() {
return mRankingScore;
}
String getTextSliceUri() {
public String getTextSliceUri() {
return mSliceUri;
}
Uri getSliceUri() {
public Uri getSliceUri() {
return Uri.parse(mSliceUri);
}
int getCategory() {
public int getCategory() {
return mCategory;
}
String getLocalizedToLocale() {
public String getLocalizedToLocale() {
return mLocalizedToLocale;
}
String getPackageName() {
public String getPackageName() {
return mPackageName;
}
String getAppVersion() {
public String getAppVersion() {
return mAppVersion;
}
String getTitleResName() {
public String getTitleResName() {
return mTitleResName;
}
String getTitleText() {
public String getTitleText() {
return mTitleText;
}
String getSummaryResName() {
public String getSummaryResName() {
return mSummaryResName;
}
String getSummaryText() {
public String getSummaryText() {
return mSummaryText;
}
String getIconResName() {
public String getIconResName() {
return mIconResName;
}
int getIconResId() {
public int getIconResId() {
return mIconResId;
}
int getCardAction() {
public int getCardAction() {
return mCardAction;
}
long getExpireTimeMS() {
public long getExpireTimeMS() {
return mExpireTimeMS;
}
Drawable getIconDrawable() {
public Drawable getIconDrawable() {
return mIconDrawable;
}
boolean isHalfWidth() {
public boolean isHalfWidth() {
return mIsHalfWidth;
}
HomepageCard(Builder builder) {
public HomepageCard(Builder builder) {
mName = builder.mName;
mCardType = builder.mCardType;
mRankingScore = builder.mRankingScore;
@@ -179,7 +179,7 @@ public class HomepageCard {
return TextUtils.equals(mName, that.mName);
}
static class Builder {
public static class Builder {
private String mName;
private int mCardType;
private double mRankingScore;

View File

@@ -18,8 +18,6 @@ package com.android.settings.homepage;
import java.util.List;
//TODO(b/111821137): add test cases
/**
* Data controller for {@link HomepageCard}.
*/

View File

@@ -17,6 +17,8 @@
package com.android.settings.homepage;
import com.android.settings.homepage.HomepageCard.CardType;
import com.android.settings.homepage.conditional.ConditionHomepageCardController;
import com.android.settings.homepage.conditional.ConditionHomepageCardRenderer;
import java.util.Set;
import java.util.TreeSet;
@@ -43,10 +45,10 @@ public class HomepageCardLookupTable {
}
}
private static final Set<HomepageMapping> LOOKUP_TABLE = new TreeSet<HomepageMapping>() {
//add(new HomepageMapping(CardType.CONDITIONAL, ConditionHomepageCardController.class,
// ConditionHomepageCardRenderer.class));
};
private static final Set<HomepageMapping> LOOKUP_TABLE = new TreeSet<HomepageMapping>() {{
add(new HomepageMapping(CardType.CONDITIONAL, ConditionHomepageCardController.class,
ConditionHomepageCardRenderer.class));
}};
public static Class<? extends HomepageCardController> getCardControllerClass(
@CardType int cardType) {

View File

@@ -26,6 +26,6 @@ import java.util.List;
* {@link HomepageManager} will notify the listeners registered, {@link HomepageAdapter} in this
* case.
*/
interface HomepageCardUpdateListener {
public interface HomepageCardUpdateListener {
void onHomepageCardUpdated(int cardType, List<HomepageCard> updateList);
}

View File

@@ -0,0 +1,78 @@
/*
* 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.
*/
package com.android.settings.homepage.conditional;
import com.android.settings.homepage.HomepageCard;
/**
* Data class representing a {@link ConditionCard}.
*
* Use this class to store additional attributes on top of {@link HomepageCard} for
* {@link ConditionalCard}.
*/
public class ConditionCard extends HomepageCard {
private final long mConditionId;
private final int mMetricsConstant;
private final CharSequence mActionText;
private ConditionCard(Builder builder) {
super(builder);
mConditionId = builder.mConditionId;
mMetricsConstant = builder.mMetricsConstant;
mActionText = builder.mActionText;
}
public long getConditionId() {
return mConditionId;
}
public int getMetricsConstant() {
return mMetricsConstant;
}
public CharSequence getActionText() {
return mActionText;
}
static class Builder extends HomepageCard.Builder {
private long mConditionId;
private int mMetricsConstant;
private CharSequence mActionText;
public Builder setConditionId(long id) {
mConditionId = id;
return this;
}
public Builder setMetricsConstant(int metricsConstant) {
mMetricsConstant = metricsConstant;
return this;
}
public Builder setActionText(CharSequence actionText) {
mActionText = actionText;
return this;
}
public ConditionCard build() {
return new ConditionCard(this);
}
}
}

View File

@@ -0,0 +1,111 @@
/*
* 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.
*/
package com.android.settings.homepage.conditional;
import android.content.Context;
import com.android.settings.homepage.HomepageCard;
import com.android.settings.homepage.HomepageCardController;
import com.android.settings.homepage.HomepageCardUpdateListener;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.ArrayList;
import java.util.List;
/**
* This controller triggers the loading of conditional cards and monitors state changes to
* update the homepage.
*/
public class ConditionHomepageCardController implements HomepageCardController, ConditionListener,
LifecycleObserver, OnStart, OnStop {
private final Context mContext;
private final ConditionManager mConditionManager;
private HomepageCardUpdateListener mListener;
public ConditionHomepageCardController(Context context) {
mContext = context;
mConditionManager = new ConditionManager(context.getApplicationContext(), this);
mConditionManager.startMonitoringStateChange();
}
@Override
public void setHomepageCardUpdateListener(HomepageCardUpdateListener listener) {
mListener = listener;
}
@Override
public int getCardType() {
return HomepageCard.CardType.CONDITIONAL;
}
@Override
public void onDataUpdated(List<HomepageCard> cardList) {
mListener.onHomepageCardUpdated(getCardType(), cardList);
}
@Override
public void onStart() {
mConditionManager.startMonitoringStateChange();
}
@Override
public void onStop() {
mConditionManager.stopMonitoringStateChange();
}
@Override
public void onPrimaryClick(HomepageCard homepageCard) {
final ConditionCard card = (ConditionCard) homepageCard;
mConditionManager.onPrimaryClick(mContext, card.getConditionId());
}
@Override
public void onActionClick(HomepageCard homepageCard) {
final ConditionCard card = (ConditionCard) homepageCard;
mConditionManager.onActionClick(card.getConditionId());
}
@Override
public void onConditionsChanged() {
final List<HomepageCard> conditionCards = new ArrayList<>();
final List<ConditionalCard> conditionList = mConditionManager.getDisplayableCards();
for (ConditionalCard condition : conditionList) {
final ConditionCard conditionCard = ((ConditionCard.Builder) new ConditionCard.Builder()
.setConditionId(condition.getId())
.setMetricsConstant(condition.getMetricsConstant())
.setActionText(condition.getActionText())
.setName(mContext.getPackageName() + "/" + condition.getTitle().toString())
.setCardType(HomepageCard.CardType.CONDITIONAL)
.setTitleText(condition.getTitle().toString())
.setSummaryText(condition.getSummary().toString())
.setIconDrawable(condition.getIcon()))
.build();
conditionCards.add(conditionCard);
}
if (mListener != null) {
onDataUpdated(conditionCards);
}
}
}

View File

@@ -0,0 +1,137 @@
/*
* 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.
*/
package com.android.settings.homepage.conditional;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.homepage.ControllerRendererPool;
import com.android.settings.homepage.HomepageCard;
import com.android.settings.homepage.HomepageCardRenderer;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Card renderer for {@link ConditionCard}.
*/
public class ConditionHomepageCardRenderer implements HomepageCardRenderer {
private final Context mContext;
private final ControllerRendererPool mControllerRendererPool;
public ConditionHomepageCardRenderer(Context context,
ControllerRendererPool controllerRendererPool) {
mContext = context;
mControllerRendererPool = controllerRendererPool;
}
@Override
public int getViewType() {
return R.layout.homepage_condition_tile;
}
@Override
public RecyclerView.ViewHolder createViewHolder(View view) {
return new ConditionalCardHolder(view);
}
@Override
public void bindView(RecyclerView.ViewHolder holder, HomepageCard homepageCard) {
final ConditionalCardHolder view = (ConditionalCardHolder) holder;
final ConditionCard card = (ConditionCard) homepageCard;
final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory.getFactory(
mContext).getMetricsFeatureProvider();
metricsFeatureProvider.visible(mContext, MetricsProto.MetricsEvent.SETTINGS_HOMEPAGE,
card.getMetricsConstant());
initializePrimaryClick(view, card, metricsFeatureProvider);
initializeView(view, card);
initializeActionButton(view, card, metricsFeatureProvider);
}
private void initializePrimaryClick(ConditionalCardHolder view, ConditionCard card,
MetricsFeatureProvider metricsFeatureProvider) {
view.itemView.findViewById(R.id.content).setOnClickListener(
v -> {
metricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_CLICK,
card.getMetricsConstant());
mControllerRendererPool.getController(mContext,
card.getCardType()).onPrimaryClick(card);
});
}
private void initializeView(ConditionalCardHolder view, ConditionCard card) {
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, ConditionCard 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) {
button.setVisibility(View.VISIBLE);
button.setText(action);
button.setOnClickListener(v -> {
final Context viewContext = v.getContext();
metricsFeatureProvider.action(
viewContext, MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_BUTTON,
card.getMetricsConstant());
mControllerRendererPool.getController(mContext, card.getCardType()).onActionClick(
card);
});
} else {
button.setVisibility(View.GONE);
}
}
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;
public final TextView title;
public final TextView summary;
public ConditionalCardHolder(View itemView) {
super(itemView);
icon = itemView.findViewById(android.R.id.icon);
title = itemView.findViewById(android.R.id.title);
summary = itemView.findViewById(android.R.id.summary);
}
}
}