OSDN Git Service

89c731f6aa4ecaa4856172a97a6137a495965706
[android-x86/packages-apps-Settings.git] / src / com / android / settings / dashboard / suggestions / SuggestionAdapterV2.java
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.settings.dashboard.suggestions;
17
18 import android.app.PendingIntent;
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.os.Bundle;
22 import android.service.settings.suggestions.Suggestion;
23 import android.support.v7.widget.RecyclerView;
24 import android.text.TextUtils;
25 import android.util.Log;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.widget.ImageView;
30 import android.widget.LinearLayout;
31
32 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
33 import com.android.settings.R;
34 import com.android.settings.core.instrumentation.MetricsFeatureProvider;
35 import com.android.settings.dashboard.DashboardAdapterV2.DashboardItemHolder;
36 import com.android.settings.dashboard.DashboardAdapterV2.IconCache;
37 import com.android.settings.overlay.FeatureFactory;
38 import com.android.settingslib.core.lifecycle.Lifecycle;
39 import com.android.settingslib.core.lifecycle.LifecycleObserver;
40 import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
41
42 import java.util.ArrayList;
43 import java.util.List;
44 import java.util.Objects;
45
46 public class SuggestionAdapterV2 extends RecyclerView.Adapter<DashboardItemHolder> implements
47         LifecycleObserver, OnSaveInstanceState {
48     public static final String TAG = "SuggestionAdapterV2";
49
50     private static final String STATE_SUGGESTIONS_SHOWN_LOGGED = "suggestions_shown_logged";
51     private static final String STATE_SUGGESTION_LIST = "suggestion_list";
52
53     private final Context mContext;
54     private final MetricsFeatureProvider mMetricsFeatureProvider;
55     private final IconCache mCache;
56     private final ArrayList<String> mSuggestionsShownLogged;
57     private final SuggestionControllerMixin mSuggestionControllerMixin;
58     private final Callback mCallback;
59     private final int mMultipleCardsMarginEnd;
60     private final int mWidthSingleCard;
61     private final int mWidthTwoCards;
62     private final int mWidthMultipleCards;
63
64     private List<Suggestion> mSuggestions;
65
66     public interface Callback {
67         /**
68          * Called when the close button of the suggestion card is clicked.
69          */
70         void onSuggestionClosed(Suggestion suggestion);
71     }
72
73     public SuggestionAdapterV2(Context context, SuggestionControllerMixin suggestionControllerMixin,
74             Bundle savedInstanceState, Callback callback, Lifecycle lifecycle) {
75         mContext = context;
76         mSuggestionControllerMixin = suggestionControllerMixin;
77         mCache = new IconCache(context);
78         final FeatureFactory factory = FeatureFactory.getFactory(context);
79         mMetricsFeatureProvider = factory.getMetricsFeatureProvider();
80         mCallback = callback;
81         if (savedInstanceState != null) {
82             mSuggestions = savedInstanceState.getParcelableArrayList(STATE_SUGGESTION_LIST);
83             mSuggestionsShownLogged = savedInstanceState.getStringArrayList(
84                 STATE_SUGGESTIONS_SHOWN_LOGGED);
85         } else {
86             mSuggestionsShownLogged = new ArrayList<>();
87         }
88
89         if (lifecycle != null) {
90             lifecycle.addObserver(this);
91         }
92
93         final Resources res = mContext.getResources();
94         mMultipleCardsMarginEnd = res.getDimensionPixelOffset(R.dimen.suggestion_card_margin_end);
95         mWidthSingleCard = res.getDimensionPixelOffset(R.dimen.suggestion_card_width_one_card);
96         mWidthTwoCards = res.getDimensionPixelOffset(R.dimen.suggestion_card_width_two_cards);
97         mWidthMultipleCards =
98             res.getDimensionPixelOffset(R.dimen.suggestion_card_width_multiple_cards);
99
100         setHasStableIds(true);
101     }
102
103     @Override
104     public DashboardItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
105         return new DashboardItemHolder(LayoutInflater.from(parent.getContext()).inflate(
106                 viewType, parent, false));
107     }
108
109     @Override
110     public void onBindViewHolder(DashboardItemHolder holder, int position) {
111         final Suggestion suggestion = mSuggestions.get(position);
112         final String id = suggestion.getId();
113         final int suggestionCount = mSuggestions.size();
114         if (!mSuggestionsShownLogged.contains(id)) {
115             mMetricsFeatureProvider.action(
116                     mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, id);
117             mSuggestionsShownLogged.add(id);
118         }
119         setCardWidthAndMargin(holder, suggestionCount);
120         holder.icon.setImageDrawable(mCache.getIcon(suggestion.getIcon()));
121         holder.title.setText(suggestion.getTitle());
122         holder.title.setSingleLine(suggestionCount == 1);
123
124         if (suggestionCount == 1) {
125             final CharSequence summary = suggestion.getSummary();
126             if (!TextUtils.isEmpty(summary)) {
127                 holder.summary.setText(summary);
128                 holder.summary.setVisibility(View.VISIBLE);
129             } else {
130                 holder.summary.setVisibility(View.GONE);
131             }
132         } else {
133             // Do not show summary if there are more than 1 suggestions
134             holder.summary.setVisibility(View.GONE);
135             holder.title.setMaxLines(3);
136         }
137
138         final ImageView closeButton = holder.itemView.findViewById(R.id.close_button);
139         if (closeButton != null) {
140             if (mCallback != null) {
141                 closeButton.setOnClickListener(v -> {
142                     mCallback.onSuggestionClosed(suggestion);
143                 });
144             } else {
145                 closeButton.setOnClickListener(null);
146             }
147         }
148
149         View clickHandler = holder.itemView;
150         // If a view with @android:id/primary is defined, use that as the click handler
151         // instead.
152         final View primaryAction = holder.itemView.findViewById(android.R.id.primary);
153         if (primaryAction != null) {
154             clickHandler = primaryAction;
155         }
156         clickHandler.setOnClickListener(v -> {
157             mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_SETTINGS_SUGGESTION, id);
158             try {
159                 suggestion.getPendingIntent().send();
160                 mSuggestionControllerMixin.launchSuggestion(suggestion);
161             } catch (PendingIntent.CanceledException e) {
162                 Log.w(TAG, "Failed to start suggestion " + suggestion.getTitle());
163             }
164         });
165     }
166
167     @Override
168     public long getItemId(int position) {
169         return Objects.hash(mSuggestions.get(position).getId());
170     }
171
172     @Override
173     public int getItemViewType(int position) {
174         final Suggestion suggestion = getSuggestion(position);
175         if ((suggestion.getFlags() & Suggestion.FLAG_HAS_BUTTON) != 0) {
176             return R.layout.suggestion_tile_with_button_v2;
177         } else {
178             return R.layout.suggestion_tile_v2;
179         }
180     }
181
182     @Override
183     public int getItemCount() {
184         return mSuggestions.size();
185     }
186
187     public Suggestion getSuggestion(int position) {
188         final long itemId = getItemId(position);
189         if (mSuggestions == null) {
190             return null;
191         }
192         for (Suggestion suggestion : mSuggestions) {
193             if (Objects.hash(suggestion.getId()) == itemId) {
194                 return suggestion;
195             }
196         }
197         return null;
198     }
199
200     public void removeSuggestion(Suggestion suggestion) {
201         final int position = mSuggestions.indexOf(suggestion);
202         mSuggestions.remove(suggestion);
203         notifyItemRemoved(position);
204     }
205
206     @Override
207     public void onSaveInstanceState(Bundle outState) {
208         if (mSuggestions != null) {
209             outState.putParcelableArrayList(STATE_SUGGESTION_LIST,
210                 new ArrayList<>(mSuggestions));
211         }
212         outState.putStringArrayList(STATE_SUGGESTIONS_SHOWN_LOGGED, mSuggestionsShownLogged);
213     }
214
215     public void setSuggestions(List<Suggestion> suggestions) {
216         mSuggestions = suggestions;
217     }
218
219     public List<Suggestion> getSuggestions() {
220         return mSuggestions;
221     }
222
223     private void setCardWidthAndMargin(DashboardItemHolder holder, int suggestionCount) {
224         final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
225             suggestionCount == 1
226                 ? mWidthSingleCard : suggestionCount == 2 ? mWidthTwoCards : mWidthMultipleCards,
227             LinearLayout.LayoutParams.WRAP_CONTENT);
228         params.setMarginEnd(suggestionCount == 1 ? 0 : mMultipleCardsMarginEnd);
229         holder.itemView.setLayoutParams(params);
230     }
231 }