OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.widget.selection; | 5 package org.chromium.chrome.browser.widget.selection; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.content.res.Configuration; | 8 import android.content.res.Configuration; |
9 import android.content.res.Resources; | 9 import android.content.res.Resources; |
| 10 import android.graphics.Rect; |
10 import android.graphics.drawable.Drawable; | 11 import android.graphics.drawable.Drawable; |
| 12 import android.support.annotation.VisibleForTesting; |
11 import android.support.v4.widget.DrawerLayout; | 13 import android.support.v4.widget.DrawerLayout; |
12 import android.support.v7.widget.LinearLayoutManager; | 14 import android.support.v7.widget.LinearLayoutManager; |
13 import android.support.v7.widget.RecyclerView; | 15 import android.support.v7.widget.RecyclerView; |
14 import android.support.v7.widget.RecyclerView.Adapter; | 16 import android.support.v7.widget.RecyclerView.Adapter; |
15 import android.support.v7.widget.RecyclerView.AdapterDataObserver; | 17 import android.support.v7.widget.RecyclerView.AdapterDataObserver; |
| 18 import android.support.v7.widget.RecyclerView.ItemAnimator; |
| 19 import android.support.v7.widget.RecyclerView.OnScrollListener; |
16 import android.support.v7.widget.Toolbar.OnMenuItemClickListener; | 20 import android.support.v7.widget.Toolbar.OnMenuItemClickListener; |
17 import android.util.AttributeSet; | 21 import android.util.AttributeSet; |
18 import android.view.LayoutInflater; | 22 import android.view.LayoutInflater; |
19 import android.view.View; | 23 import android.view.View; |
20 import android.view.ViewStub; | 24 import android.view.ViewStub; |
21 import android.widget.RelativeLayout; | 25 import android.widget.RelativeLayout; |
22 import android.widget.TextView; | 26 import android.widget.TextView; |
23 | 27 |
24 import org.chromium.base.ApiCompatibilityUtils; | 28 import org.chromium.base.ApiCompatibilityUtils; |
25 import org.chromium.chrome.R; | 29 import org.chromium.chrome.R; |
26 import org.chromium.chrome.browser.widget.FadingShadow; | 30 import org.chromium.chrome.browser.widget.FadingShadow; |
27 import org.chromium.chrome.browser.widget.FadingShadowView; | 31 import org.chromium.chrome.browser.widget.FadingShadowView; |
28 import org.chromium.chrome.browser.widget.LoadingView; | 32 import org.chromium.chrome.browser.widget.LoadingView; |
29 import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserver; | 33 import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserver; |
30 import org.chromium.chrome.browser.widget.displaystyle.HorizontalDisplayStyle; | 34 import org.chromium.chrome.browser.widget.displaystyle.HorizontalDisplayStyle; |
31 import org.chromium.chrome.browser.widget.displaystyle.UiConfig; | 35 import org.chromium.chrome.browser.widget.displaystyle.UiConfig; |
32 import org.chromium.chrome.browser.widget.displaystyle.UiConfig.DisplayStyle; | 36 import org.chromium.chrome.browser.widget.displaystyle.UiConfig.DisplayStyle; |
| 37 import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionO
bserver; |
33 import org.chromium.ui.base.DeviceFormFactor; | 38 import org.chromium.ui.base.DeviceFormFactor; |
34 | 39 |
| 40 import java.util.List; |
| 41 |
35 import javax.annotation.Nullable; | 42 import javax.annotation.Nullable; |
36 | 43 |
37 /** | 44 /** |
38 * Contains UI elements common to selectable list views: a loading view, empty v
iew, selection | 45 * Contains UI elements common to selectable list views: a loading view, empty v
iew, selection |
39 * toolbar, shadow, and RecyclerView. | 46 * toolbar, shadow, and RecyclerView. |
40 * | 47 * |
41 * After the SelectableListLayout is inflated, it should be initialized through
calls to | 48 * After the SelectableListLayout is inflated, it should be initialized through
calls to |
42 * #initializeRecyclerView(), #initializeToolbar(), and #initializeEmptyView(). | 49 * #initializeRecyclerView(), #initializeToolbar(), and #initializeEmptyView(). |
43 * | 50 * |
44 * @param <E> The type of the selectable items this layout holds. | 51 * @param <E> The type of the selectable items this layout holds. |
45 */ | 52 */ |
46 public class SelectableListLayout<E> extends RelativeLayout implements DisplaySt
yleObserver { | 53 public class SelectableListLayout<E> |
| 54 extends RelativeLayout implements DisplayStyleObserver, SelectionObserve
r<E> { |
| 55 /** |
| 56 * @param res Resources used to retrieve drawables and dimensions. |
| 57 * @return The default list item lateral margin size in pixels. This value s
hould be used in |
| 58 * {@link HorizontalDisplayStyle#REGULAR} to hide the lateral shadow
and rounded edges |
| 59 * on items that use the list_item* 9-patches as a background. |
| 60 */ |
| 61 public static int getDefaultListItemLateralMarginPx(Resources res) { |
| 62 if (sDefaultListItemLateralMarginPx == -1) { |
| 63 Rect listItemShadow = new Rect(); |
| 64 ApiCompatibilityUtils.getDrawable(res, R.drawable.card_middle) |
| 65 .getPadding(listItemShadow); |
| 66 int cardCornerRadius = res.getDimensionPixelSize(R.dimen.list_item_c
orner_radius); |
| 67 |
| 68 assert listItemShadow.left == listItemShadow.right; |
| 69 |
| 70 // A negative margin is used in HorizontalDisplayStyle#REGULAR to hi
de the lateral |
| 71 // shadow. |
| 72 sDefaultListItemLateralMarginPx = -(listItemShadow.left + cardCorner
Radius); |
| 73 } |
| 74 |
| 75 return sDefaultListItemLateralMarginPx; |
| 76 } |
| 77 |
47 private static final int WIDE_DISPLAY_MIN_PADDING_DP = 16; | 78 private static final int WIDE_DISPLAY_MIN_PADDING_DP = 16; |
48 | 79 |
| 80 private static int sDefaultListItemLateralMarginPx = -1; |
| 81 |
49 private Adapter<RecyclerView.ViewHolder> mAdapter; | 82 private Adapter<RecyclerView.ViewHolder> mAdapter; |
50 private ViewStub mToolbarStub; | 83 private ViewStub mToolbarStub; |
51 private TextView mEmptyView; | 84 private TextView mEmptyView; |
52 private LoadingView mLoadingView; | 85 private LoadingView mLoadingView; |
53 private RecyclerView mRecyclerView; | 86 private RecyclerView mRecyclerView; |
| 87 private ItemAnimator mItemAnimator; |
54 SelectableListToolbar<E> mToolbar; | 88 SelectableListToolbar<E> mToolbar; |
| 89 private FadingShadowView mToolbarShadow; |
| 90 |
| 91 private boolean mToolbarPermanentlyHidden; |
| 92 private int mEmptyStringResId; |
| 93 private int mSearchEmptyStringResId; |
55 | 94 |
56 private UiConfig mUiConfig; | 95 private UiConfig mUiConfig; |
57 | 96 |
58 private final AdapterDataObserver mAdapterObserver = new AdapterDataObserver
() { | 97 private final AdapterDataObserver mAdapterObserver = new AdapterDataObserver
() { |
59 @Override | 98 @Override |
60 public void onChanged() { | 99 public void onChanged() { |
61 super.onChanged(); | 100 super.onChanged(); |
62 if (mAdapter.getItemCount() == 0) { | 101 if (mAdapter.getItemCount() == 0) { |
63 mEmptyView.setVisibility(View.VISIBLE); | 102 mEmptyView.setVisibility(View.VISIBLE); |
64 mRecyclerView.setVisibility(View.GONE); | 103 mRecyclerView.setVisibility(View.GONE); |
(...skipping 14 matching lines...) Expand all Loading... |
79 updateEmptyViewVisibility(); | 118 updateEmptyViewVisibility(); |
80 } | 119 } |
81 | 120 |
82 @Override | 121 @Override |
83 public void onItemRangeRemoved(int positionStart, int itemCount) { | 122 public void onItemRangeRemoved(int positionStart, int itemCount) { |
84 super.onItemRangeRemoved(positionStart, itemCount); | 123 super.onItemRangeRemoved(positionStart, itemCount); |
85 updateEmptyViewVisibility(); | 124 updateEmptyViewVisibility(); |
86 } | 125 } |
87 }; | 126 }; |
88 | 127 |
89 /** | |
90 * Unlike ListView or GridView, RecyclerView does not provide default empty | |
91 * view implementation. We need to check it ourselves. | |
92 */ | |
93 private void updateEmptyViewVisibility() { | |
94 mEmptyView.setVisibility(mAdapter.getItemCount() == 0 ? View.VISIBLE : V
iew.GONE); | |
95 } | |
96 | |
97 public SelectableListLayout(Context context, AttributeSet attrs) { | 128 public SelectableListLayout(Context context, AttributeSet attrs) { |
98 super(context, attrs); | 129 super(context, attrs); |
99 } | 130 } |
100 | 131 |
101 @Override | 132 @Override |
102 protected void onFinishInflate() { | 133 protected void onFinishInflate() { |
103 super.onFinishInflate(); | 134 super.onFinishInflate(); |
104 | 135 |
105 LayoutInflater.from(getContext()).inflate(R.layout.selectable_list_layou
t, this); | 136 LayoutInflater.from(getContext()).inflate(R.layout.selectable_list_layou
t, this); |
106 | 137 |
(...skipping 21 matching lines...) Expand all Loading... |
128 * that are displayed within the RecyclerView. | 159 * that are displayed within the RecyclerView. |
129 * @return The RecyclerView itself. | 160 * @return The RecyclerView itself. |
130 */ | 161 */ |
131 public RecyclerView initializeRecyclerView(Adapter<RecyclerView.ViewHolder>
adapter) { | 162 public RecyclerView initializeRecyclerView(Adapter<RecyclerView.ViewHolder>
adapter) { |
132 mAdapter = adapter; | 163 mAdapter = adapter; |
133 mAdapter.registerAdapterDataObserver(mAdapterObserver); | 164 mAdapter.registerAdapterDataObserver(mAdapterObserver); |
134 | 165 |
135 mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); | 166 mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); |
136 mRecyclerView.setAdapter(mAdapter); | 167 mRecyclerView.setAdapter(mAdapter); |
137 mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); | 168 mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); |
| 169 |
138 mRecyclerView.setHasFixedSize(true); | 170 mRecyclerView.setHasFixedSize(true); |
| 171 mRecyclerView.addOnScrollListener(new OnScrollListener() { |
| 172 @Override |
| 173 public void onScrolled(RecyclerView recyclerView, int dx, int dy) { |
| 174 setToolbarShadowVisibility(); |
| 175 } |
| 176 }); |
| 177 |
| 178 mItemAnimator = mRecyclerView.getItemAnimator(); |
139 | 179 |
140 return mRecyclerView; | 180 return mRecyclerView; |
141 } | 181 } |
142 | 182 |
143 /** | 183 /** |
144 * Initializes the SelectionToolbar. | 184 * Initializes the SelectionToolbar. |
145 * | 185 * |
146 * @param toolbarLayoutId The resource id of the toolbar layout. This will b
e inflated into | 186 * @param toolbarLayoutId The resource id of the toolbar layout. This will b
e inflated into |
147 * a ViewStub. | 187 * a ViewStub. |
148 * @param delegate The SelectionDelegate that will inform the toolbar of sel
ection changes. | 188 * @param delegate The SelectionDelegate that will inform the toolbar of sel
ection changes. |
149 * @param titleResId The resource id of the title string. May be 0 if this c
lass shouldn't set | 189 * @param titleResId The resource id of the title string. May be 0 if this c
lass shouldn't set |
150 * set a title when the selection is cleared. | 190 * set a title when the selection is cleared. |
151 * @param drawerLayout The DrawerLayout whose navigation icon is displayed i
n this toolbar. | 191 * @param drawerLayout The DrawerLayout whose navigation icon is displayed i
n this toolbar. |
152 * @param normalGroupResId The resource id of the menu group to show when a
selection isn't | 192 * @param normalGroupResId The resource id of the menu group to show when a
selection isn't |
153 * established. | 193 * established. |
154 * @param selectedGroupResId The resource id of the menu item to show when a
selection is | 194 * @param selectedGroupResId The resource id of the menu item to show when a
selection is |
155 * established. | 195 * established. |
156 * @param normalBackgroundColorResId The resource id of the color to use as
the background color | 196 * @param normalBackgroundColorResId The resource id of the color to use as
the background color |
157 * when selection is not enabled. If null
the default appbar | 197 * when selection is not enabled. If null
the default appbar |
158 * background color will be used. | 198 * background color will be used. |
159 * @param hideShadowOnLargeTablets Whether the toolbar shadow should be hidd
en on large tablets. | 199 * @param hideShadowOnLargeTablets Whether the toolbar shadow should be hidd
en on large tablets. |
160 * @param listener The OnMenuItemClickListener to set on the toolbar. | 200 * @param listener The OnMenuItemClickListener to set on the toolbar. |
161 * @return The initialized SelectionToolbar. | 201 * @return The initialized SelectionToolbar. |
162 */ | 202 */ |
163 public SelectableListToolbar<E> initializeToolbar(int toolbarLayoutId, | 203 public SelectableListToolbar<E> initializeToolbar(int toolbarLayoutId, |
164 SelectionDelegate<E> delegate, int titleResId, @Nullable DrawerLayou
t drawerLayout, | 204 SelectionDelegate<E> delegate, int titleResId, @Nullable DrawerLayou
t drawerLayout, |
165 int normalGroupResId, int selectedGroupResId, | 205 int normalGroupResId, int selectedGroupResId, |
166 @Nullable Integer normalBackgroundColorResId, boolean hideShadowOnLa
rgeTablets, | 206 @Nullable Integer normalBackgroundColorResId, boolean hideShadowOnLa
rgeTablets, |
167 @Nullable OnMenuItemClickListener listener) { | 207 @Nullable OnMenuItemClickListener listener) { |
168 FadingShadowView shadow = (FadingShadowView) findViewById(R.id.shadow); | |
169 if (hideShadowOnLargeTablets && DeviceFormFactor.isLargeTablet(getContex
t())) { | |
170 shadow.setVisibility(View.GONE); | |
171 } else { | |
172 shadow.init(ApiCompatibilityUtils.getColor(getResources(), | |
173 R.color.toolbar_shadow_color), FadingShadow.POSITION_TOP); | |
174 } | |
175 | |
176 mToolbarStub.setLayoutResource(toolbarLayoutId); | 208 mToolbarStub.setLayoutResource(toolbarLayoutId); |
177 @SuppressWarnings("unchecked") | 209 @SuppressWarnings("unchecked") |
178 SelectableListToolbar<E> toolbar = (SelectableListToolbar<E>) mToolbarSt
ub.inflate(); | 210 SelectableListToolbar<E> toolbar = (SelectableListToolbar<E>) mToolbarSt
ub.inflate(); |
179 mToolbar = toolbar; | 211 mToolbar = toolbar; |
180 mToolbar.initialize(delegate, titleResId, drawerLayout, normalGroupResId
, | 212 mToolbar.initialize(delegate, titleResId, drawerLayout, normalGroupResId
, |
181 selectedGroupResId, normalBackgroundColorResId); | 213 selectedGroupResId, normalBackgroundColorResId); |
182 | 214 |
183 if (listener != null) { | 215 if (listener != null) { |
184 mToolbar.setOnMenuItemClickListener(listener); | 216 mToolbar.setOnMenuItemClickListener(listener); |
185 } | 217 } |
186 | 218 |
| 219 mToolbarShadow = (FadingShadowView) findViewById(R.id.shadow); |
| 220 if (hideShadowOnLargeTablets && DeviceFormFactor.isLargeTablet(getContex
t())) { |
| 221 mToolbarPermanentlyHidden = true; |
| 222 mToolbarShadow.setVisibility(View.GONE); |
| 223 } else { |
| 224 mToolbarShadow.init( |
| 225 ApiCompatibilityUtils.getColor(getResources(), R.color.toolb
ar_shadow_color), |
| 226 FadingShadow.POSITION_TOP); |
| 227 delegate.addObserver(this); |
| 228 setToolbarShadowVisibility(); |
| 229 } |
| 230 |
187 return mToolbar; | 231 return mToolbar; |
188 } | 232 } |
189 | 233 |
190 /** | 234 /** |
191 * Initializes the view shown when the selectable list is empty. | 235 * Initializes the view shown when the selectable list is empty. |
192 * | 236 * |
193 * @param emptyDrawable The Drawable to show when the selectable list is emp
ty. | 237 * @param emptyDrawable The Drawable to show when the selectable list is emp
ty. |
194 * @param emptyStringResId The string to show when the selectable list is em
pty. | 238 * @param emptyStringResId The string to show when the selectable list is em
pty. |
| 239 * @param searchEmptyStringResId The string to show when the selectable list
is empty during |
| 240 * a search. |
195 * @return The {@link TextView} displayed when the list is empty. | 241 * @return The {@link TextView} displayed when the list is empty. |
196 */ | 242 */ |
197 public TextView initializeEmptyView(Drawable emptyDrawable, int emptyStringR
esId) { | 243 public TextView initializeEmptyView( |
| 244 Drawable emptyDrawable, int emptyStringResId, int searchEmptyStringR
esId) { |
| 245 mEmptyStringResId = emptyStringResId; |
| 246 mSearchEmptyStringResId = searchEmptyStringResId; |
| 247 |
198 mEmptyView.setCompoundDrawablesWithIntrinsicBounds(null, emptyDrawable,
null, null); | 248 mEmptyView.setCompoundDrawablesWithIntrinsicBounds(null, emptyDrawable,
null, null); |
199 mEmptyView.setText(emptyStringResId); | 249 mEmptyView.setText(mEmptyStringResId); |
200 return mEmptyView; | 250 return mEmptyView; |
201 } | 251 } |
202 | 252 |
203 /** | 253 /** |
204 * @param emptyStringResId The string to show when the selectable list is em
pty. | |
205 */ | |
206 public void setEmptyViewText(int emptyStringResId) { | |
207 mEmptyView.setText(emptyStringResId); | |
208 } | |
209 | |
210 /** | |
211 * Called when the view that owns the SelectableListLayout is destroyed. | 254 * Called when the view that owns the SelectableListLayout is destroyed. |
212 */ | 255 */ |
213 public void onDestroyed() { | 256 public void onDestroyed() { |
214 mAdapter.unregisterAdapterDataObserver(mAdapterObserver); | 257 mAdapter.unregisterAdapterDataObserver(mAdapterObserver); |
| 258 mToolbar.getSelectionDelegate().removeObserver(this); |
215 } | 259 } |
216 | 260 |
217 /** | 261 /** |
218 * When this layout has a wide display style, it will be width constrained t
o | 262 * When this layout has a wide display style, it will be width constrained t
o |
219 * {@link UiConfig#WIDE_DISPLAY_STYLE_MIN_WIDTH_DP}. If the current screen w
idth is greater than | 263 * {@link UiConfig#WIDE_DISPLAY_STYLE_MIN_WIDTH_DP}. If the current screen w
idth is greater than |
220 * UiConfig#WIDE_DISPLAY_STYLE_MIN_WIDTH_DP, the SelectableListLayout will b
e visually centered | 264 * UiConfig#WIDE_DISPLAY_STYLE_MIN_WIDTH_DP, the SelectableListLayout will b
e visually centered |
221 * by adding padding to both sides. | 265 * by adding padding to both sides. |
222 * | 266 * |
223 * This method should be called after the toolbar and RecyclerView are initi
alized. | 267 * This method should be called after the toolbar and RecyclerView are initi
alized. |
224 * | 268 * |
(...skipping 16 matching lines...) Expand all Loading... |
241 | 285 |
242 @Override | 286 @Override |
243 public void onDisplayStyleChanged(DisplayStyle newDisplayStyle) { | 287 public void onDisplayStyleChanged(DisplayStyle newDisplayStyle) { |
244 int padding = getPaddingForDisplayStyle(newDisplayStyle, getResources())
; | 288 int padding = getPaddingForDisplayStyle(newDisplayStyle, getResources())
; |
245 | 289 |
246 ApiCompatibilityUtils.setPaddingRelative(mRecyclerView, | 290 ApiCompatibilityUtils.setPaddingRelative(mRecyclerView, |
247 padding, mRecyclerView.getPaddingTop(), | 291 padding, mRecyclerView.getPaddingTop(), |
248 padding, mRecyclerView.getPaddingBottom()); | 292 padding, mRecyclerView.getPaddingBottom()); |
249 } | 293 } |
250 | 294 |
| 295 @Override |
| 296 public void onSelectionStateChange(List<E> selectedItems) { |
| 297 setToolbarShadowVisibility(); |
| 298 } |
| 299 |
| 300 /** |
| 301 * Called when a search is starting. |
| 302 */ |
| 303 public void onStartSearch() { |
| 304 mRecyclerView.setItemAnimator(null); |
| 305 mToolbarShadow.setVisibility(View.VISIBLE); |
| 306 mEmptyView.setText(mSearchEmptyStringResId); |
| 307 } |
| 308 |
| 309 /** |
| 310 * Called when a search has ended. |
| 311 */ |
| 312 public void onEndSearch() { |
| 313 mRecyclerView.setItemAnimator(mItemAnimator); |
| 314 setToolbarShadowVisibility(); |
| 315 mEmptyView.setText(mEmptyStringResId); |
| 316 } |
| 317 |
251 /** | 318 /** |
252 * @param displayStyle The current display style.. | 319 * @param displayStyle The current display style.. |
253 * @param resources The {@link Resources} used to retrieve configuration and
display metrics. | 320 * @param resources The {@link Resources} used to retrieve configuration and
display metrics. |
254 * @return The lateral padding to use for the current display style. | 321 * @return The lateral padding to use for the current display style. |
255 */ | 322 */ |
256 public static int getPaddingForDisplayStyle(DisplayStyle displayStyle, Resou
rces resources) { | 323 public static int getPaddingForDisplayStyle(DisplayStyle displayStyle, Resou
rces resources) { |
257 int padding = 0; | 324 int padding = 0; |
258 if (displayStyle.horizontal == HorizontalDisplayStyle.WIDE) { | 325 if (displayStyle.horizontal == HorizontalDisplayStyle.WIDE) { |
259 int screenWidthDp = resources.getConfiguration().screenWidthDp; | 326 int screenWidthDp = resources.getConfiguration().screenWidthDp; |
260 float dpToPx = resources.getDisplayMetrics().density; | 327 float dpToPx = resources.getDisplayMetrics().density; |
261 padding = (int) (((screenWidthDp - UiConfig.WIDE_DISPLAY_STYLE_MIN_W
IDTH_DP) / 2.f) | 328 padding = (int) (((screenWidthDp - UiConfig.WIDE_DISPLAY_STYLE_MIN_W
IDTH_DP) / 2.f) |
262 * dpToPx); | 329 * dpToPx); |
263 padding = (int) Math.max(WIDE_DISPLAY_MIN_PADDING_DP * dpToPx, paddi
ng); | 330 padding = (int) Math.max(WIDE_DISPLAY_MIN_PADDING_DP * dpToPx, paddi
ng); |
264 } | 331 } |
265 return padding; | 332 return padding; |
266 } | 333 } |
| 334 |
| 335 private void setToolbarShadowVisibility() { |
| 336 if (mToolbarPermanentlyHidden || mToolbar == null || mRecyclerView == nu
ll) return; |
| 337 |
| 338 boolean showShadow = mRecyclerView.computeVerticalScrollOffset() != 0 |
| 339 || mToolbar.isSearching() || mToolbar.getSelectionDelegate().isS
electionEnabled(); |
| 340 mToolbarShadow.setVisibility(showShadow ? View.VISIBLE : View.GONE); |
| 341 } |
| 342 |
| 343 /** |
| 344 * Unlike ListView or GridView, RecyclerView does not provide default empty |
| 345 * view implementation. We need to check it ourselves. |
| 346 */ |
| 347 private void updateEmptyViewVisibility() { |
| 348 mEmptyView.setVisibility(mAdapter.getItemCount() == 0 ? View.VISIBLE : V
iew.GONE); |
| 349 } |
| 350 |
| 351 @VisibleForTesting |
| 352 public View getToolbarShadowForTests() { |
| 353 return mToolbarShadow; |
| 354 } |
267 } | 355 } |
OLD | NEW |