• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.launcher3.widget;
17 
18 import android.annotation.TargetApi;
19 import android.content.Context;
20 import android.content.pm.ResolveInfo;
21 import android.content.res.Resources;
22 import android.os.Build;
23 import android.support.v7.widget.RecyclerView;
24 import android.support.v7.widget.RecyclerView.Adapter;
25 import android.util.Log;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.view.ViewGroup.LayoutParams;
30 import android.widget.LinearLayout;
31 
32 import com.android.launcher3.BubbleTextView;
33 import com.android.launcher3.DeviceProfile;
34 import com.android.launcher3.Launcher;
35 import com.android.launcher3.LauncherAppState;
36 import com.android.launcher3.LauncherAppWidgetProviderInfo;
37 import com.android.launcher3.R;
38 import com.android.launcher3.Utilities;
39 import com.android.launcher3.WidgetPreviewLoader;
40 import com.android.launcher3.model.PackageItemInfo;
41 import com.android.launcher3.model.WidgetsModel;
42 
43 import java.util.List;
44 
45 /**
46  * List view adapter for the widget tray.
47  *
48  * <p>Memory vs. Performance:
49  * The less number of types of views are inserted into a {@link RecyclerView}, the more recycling
50  * happens and less memory is consumed. {@link #getItemViewType} was not overridden as there is
51  * only a single type of view.
52  */
53 public class WidgetsListAdapter extends Adapter<WidgetsRowViewHolder> {
54 
55     private static final String TAG = "WidgetsListAdapter";
56     private static final boolean DEBUG = false;
57 
58     private Launcher mLauncher;
59     private LayoutInflater mLayoutInflater;
60 
61     private WidgetsModel mWidgetsModel;
62     private WidgetPreviewLoader mWidgetPreviewLoader;
63 
64     private View.OnClickListener mIconClickListener;
65     private View.OnLongClickListener mIconLongClickListener;
66 
67     private static final int PRESET_INDENT_SIZE_TABLET = 56;
68     private int mIndent = 0;
69 
WidgetsListAdapter(Context context, View.OnClickListener iconClickListener, View.OnLongClickListener iconLongClickListener, Launcher launcher)70     public WidgetsListAdapter(Context context,
71             View.OnClickListener iconClickListener,
72             View.OnLongClickListener iconLongClickListener,
73             Launcher launcher) {
74         mLayoutInflater = LayoutInflater.from(context);
75 
76         mIconClickListener = iconClickListener;
77         mIconLongClickListener = iconLongClickListener;
78         mLauncher = launcher;
79 
80         setContainerHeight();
81     }
82 
setWidgetsModel(WidgetsModel w)83     public void setWidgetsModel(WidgetsModel w) {
84         mWidgetsModel = w;
85     }
86 
87     @Override
getItemCount()88     public int getItemCount() {
89         if (mWidgetsModel == null) {
90             return 0;
91         }
92         return mWidgetsModel.getPackageSize();
93     }
94 
95     @Override
onBindViewHolder(WidgetsRowViewHolder holder, int pos)96     public void onBindViewHolder(WidgetsRowViewHolder holder, int pos) {
97         List<Object> infoList = mWidgetsModel.getSortedWidgets(pos);
98 
99         ViewGroup row = ((ViewGroup) holder.getContent().findViewById(R.id.widgets_cell_list));
100         if (DEBUG) {
101             Log.d(TAG, String.format(
102                     "onBindViewHolder [pos=%d, widget#=%d, row.getChildCount=%d]",
103                     pos, infoList.size(), row.getChildCount()));
104         }
105 
106         // Add more views.
107         // if there are too many, hide them.
108         int diff = infoList.size() - row.getChildCount();
109 
110         if (diff > 0) {
111             for (int i = 0; i < diff; i++) {
112                 WidgetCell widget = (WidgetCell) mLayoutInflater.inflate(
113                         R.layout.widget_cell, row, false);
114 
115                 // set up touch.
116                 widget.setOnClickListener(mIconClickListener);
117                 widget.setOnLongClickListener(mIconLongClickListener);
118                 LayoutParams lp = widget.getLayoutParams();
119                 lp.height = widget.cellSize;
120                 lp.width = widget.cellSize;
121                 widget.setLayoutParams(lp);
122 
123                 row.addView(widget);
124             }
125         } else if (diff < 0) {
126             for (int i=infoList.size() ; i < row.getChildCount(); i++) {
127                 row.getChildAt(i).setVisibility(View.GONE);
128             }
129         }
130 
131         // Bind the views in the application info section.
132         PackageItemInfo infoOut = mWidgetsModel.getPackageItemInfo(pos);
133         BubbleTextView tv = ((BubbleTextView) holder.getContent().findViewById(R.id.section));
134         tv.applyFromPackageItemInfo(infoOut);
135 
136         // Bind the view in the widget horizontal tray region.
137         if (getWidgetPreviewLoader() == null) {
138             return;
139         }
140         for (int i=0; i < infoList.size(); i++) {
141             WidgetCell widget = (WidgetCell) row.getChildAt(i);
142             if (infoList.get(i) instanceof LauncherAppWidgetProviderInfo) {
143                 LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo) infoList.get(i);
144                 PendingAddWidgetInfo pawi = new PendingAddWidgetInfo(mLauncher, info, null);
145                 widget.setTag(pawi);
146                 widget.applyFromAppWidgetProviderInfo(info, mWidgetPreviewLoader);
147             } else if (infoList.get(i) instanceof ResolveInfo) {
148                 ResolveInfo info = (ResolveInfo) infoList.get(i);
149                 PendingAddShortcutInfo pasi = new PendingAddShortcutInfo(info.activityInfo);
150                 widget.setTag(pasi);
151                 widget.applyFromResolveInfo(mLauncher.getPackageManager(), info, mWidgetPreviewLoader);
152             }
153             widget.ensurePreview();
154             widget.setVisibility(View.VISIBLE);
155         }
156     }
157 
158     @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
159     @Override
onCreateViewHolder(ViewGroup parent, int viewType)160     public WidgetsRowViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
161         if (DEBUG) {
162             Log.v(TAG, "\nonCreateViewHolder");
163         }
164 
165         ViewGroup container = (ViewGroup) mLayoutInflater.inflate(
166                 R.layout.widgets_list_row_view, parent, false);
167         LinearLayout cellList = (LinearLayout) container.findViewById(R.id.widgets_cell_list);
168 
169         // if the end padding is 0, then container view (horizontal scroll view) doesn't respect
170         // the end of the linear layout width + the start padding and doesn't allow scrolling.
171         if (Utilities.ATLEAST_JB_MR1) {
172             cellList.setPaddingRelative(mIndent, 0, 1, 0);
173         } else {
174             cellList.setPadding(mIndent, 0, 1, 0);
175         }
176 
177         return new WidgetsRowViewHolder(container);
178     }
179 
180     @Override
onViewRecycled(WidgetsRowViewHolder holder)181     public void onViewRecycled(WidgetsRowViewHolder holder) {
182         ViewGroup row = ((ViewGroup) holder.getContent().findViewById(R.id.widgets_cell_list));
183 
184         for (int i = 0; i < row.getChildCount(); i++) {
185             WidgetCell widget = (WidgetCell) row.getChildAt(i);
186             widget.clear();
187         }
188     }
189 
onFailedToRecycleView(WidgetsRowViewHolder holder)190     public boolean onFailedToRecycleView(WidgetsRowViewHolder holder) {
191         // If child views are animating, then the RecyclerView may choose not to recycle the view,
192         // causing extraneous onCreateViewHolder() calls.  It is safe in this case to continue
193         // recycling this view, and take care in onViewRecycled() to cancel any existing
194         // animations.
195         return true;
196     }
197 
198     @Override
getItemId(int pos)199     public long getItemId(int pos) {
200         return pos;
201     }
202 
getWidgetPreviewLoader()203     private WidgetPreviewLoader getWidgetPreviewLoader() {
204         if (mWidgetPreviewLoader == null) {
205             mWidgetPreviewLoader = LauncherAppState.getInstance().getWidgetCache();
206         }
207         return mWidgetPreviewLoader;
208     }
209 
setContainerHeight()210     private void setContainerHeight() {
211         Resources r = mLauncher.getResources();
212         DeviceProfile profile = mLauncher.getDeviceProfile();
213         if (profile.isLargeTablet || profile.isTablet) {
214             mIndent = Utilities.pxFromDp(PRESET_INDENT_SIZE_TABLET, r.getDisplayMetrics());
215         }
216     }
217 }
218