blob: 714bc895c53b9642b3ce1352249cd13579df9f0d [file] [log] [blame]
Chuck Liao1e0501f2020-02-17 18:20:54 +08001/*
2 * Copyright (C) 2020 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 */
16package com.android.wallpaper.picker;
17
18import android.app.Activity;
Chuck Liaof646e052020-09-24 12:24:59 +080019import android.app.AlertDialog;
Chuck Liao1e0501f2020-02-17 18:20:54 +080020import android.content.Intent;
21import android.graphics.Point;
22import android.graphics.PorterDuff;
23import android.graphics.Rect;
24import android.net.Uri;
25import android.os.Bundle;
26import android.provider.Settings;
27import android.util.DisplayMetrics;
28import android.util.Log;
29import android.view.LayoutInflater;
30import android.view.View;
31import android.view.ViewGroup;
32import android.widget.ImageView;
33import android.widget.ProgressBar;
34import android.widget.TextView;
35
36import androidx.annotation.NonNull;
37import androidx.annotation.Nullable;
Chuck Liao1e0501f2020-02-17 18:20:54 +080038import androidx.cardview.widget.CardView;
39import androidx.fragment.app.Fragment;
40import androidx.recyclerview.widget.GridLayoutManager;
41import androidx.recyclerview.widget.RecyclerView;
42
43import com.android.wallpaper.R;
44import com.android.wallpaper.asset.Asset;
45import com.android.wallpaper.model.Category;
Chuck Liaoddf2b522021-04-15 00:36:25 +080046import com.android.wallpaper.model.CategoryProvider;
Chuck Liao1e0501f2020-02-17 18:20:54 +080047import com.android.wallpaper.module.InjectorProvider;
48import com.android.wallpaper.module.UserEventLogger;
Chuck Liaof6b4b192020-08-07 02:31:32 +080049import com.android.wallpaper.util.DeepLinkUtils;
Chuck Liao1e0501f2020-02-17 18:20:54 +080050import com.android.wallpaper.util.DisplayMetricsRetriever;
Santiago Etchebehere53c63432020-05-07 18:55:35 -070051import com.android.wallpaper.util.SizeCalculator;
Wesley.CW Wangdc68fde2020-06-15 19:12:33 +080052import com.android.wallpaper.widget.WallpaperPickerRecyclerViewAccessibilityDelegate;
53import com.android.wallpaper.widget.WallpaperPickerRecyclerViewAccessibilityDelegate.BottomSheetHost;
Chuck Liao1e0501f2020-02-17 18:20:54 +080054
55import com.bumptech.glide.Glide;
56
57import java.util.ArrayList;
58import java.util.List;
59
60/**
61 * Displays the UI which contains the categories of the wallpaper.
62 */
Chuck Liao58aca1c2021-03-17 01:20:55 +080063public class CategorySelectorFragment extends AppbarFragment {
Chuck Liao1e0501f2020-02-17 18:20:54 +080064
65 // The number of ViewHolders that don't pertain to category tiles.
66 // Currently 2: one for the metadata section and one for the "Select wallpaper" header.
67 private static final int NUM_NON_CATEGORY_VIEW_HOLDERS = 0;
68 private static final int SETTINGS_APP_INFO_REQUEST_CODE = 1;
69 private static final String TAG = "CategorySelectorFragment";
70
71 /**
72 * Interface to be implemented by an Fragment hosting a {@link CategorySelectorFragment}
73 */
74 public interface CategorySelectorFragmentHost {
75
76 /**
77 * Requests to show the Android custom photo picker for the sake of picking a photo
78 * to set as the device's wallpaper.
79 */
80 void requestCustomPhotoPicker(MyPhotosStarter.PermissionChangedListener listener);
81
82 /**
83 * Shows the wallpaper page of the specific category.
84 *
Chuck Liaoa63f1bf2020-06-11 01:35:42 +080085 * @param category the wallpaper's {@link Category}
Chuck Liao1e0501f2020-02-17 18:20:54 +080086 */
Chuck Liaoa63f1bf2020-06-11 01:35:42 +080087 void show(Category category);
Chuck Liao0088bca2020-05-28 16:03:23 +080088
Chuck Liao58aca1c2021-03-17 01:20:55 +080089
Chuck Liao0088bca2020-05-28 16:03:23 +080090 /**
Chuck Liao58aca1c2021-03-17 01:20:55 +080091 * Indicates if the host has toolbar to show the title. If it does, we should set the title
92 * there.
93 */
94 boolean isHostToolbarShown();
95
96 /**
97 * Sets the title in the host's toolbar.
Chuck Liao0088bca2020-05-28 16:03:23 +080098 */
99 void setToolbarTitle(CharSequence title);
Chuck Liaof6b4b192020-08-07 02:31:32 +0800100
101 /**
102 * Fetches the wallpaper categories.
103 */
104 void fetchCategories();
Chuck Liao81145b22020-09-03 09:52:25 +0800105
106 /**
Chuck Liao3abf15b2020-12-17 22:33:02 +0800107 * Cleans up the listeners which will be notified when there's a package event.
108 */
109 void cleanUp();
Chuck Liao1e0501f2020-02-17 18:20:54 +0800110 }
111
Chuck Liaoddf2b522021-04-15 00:36:25 +0800112 private final CategoryProvider mCategoryProvider;
113
Chuck Liao1e0501f2020-02-17 18:20:54 +0800114 private RecyclerView mImageGrid;
115 private CategoryAdapter mAdapter;
116 private ArrayList<Category> mCategories = new ArrayList<>();
117 private Point mTileSizePx;
118 private boolean mAwaitingCategories;
119
120 public CategorySelectorFragment() {
121 mAdapter = new CategoryAdapter(mCategories);
Chuck Liaoddf2b522021-04-15 00:36:25 +0800122 mCategoryProvider = InjectorProvider.getInjector().getCategoryProvider(getContext());
Chuck Liao1e0501f2020-02-17 18:20:54 +0800123 }
124
125 @Nullable
126 @Override
127 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
128 @Nullable Bundle savedInstanceState) {
129 View view = inflater.inflate(R.layout.fragment_category_selector, container,
130 /* attachToRoot= */ false);
Chuck Liao1e0501f2020-02-17 18:20:54 +0800131 mImageGrid = view.findViewById(R.id.category_grid);
132 mImageGrid.addItemDecoration(new GridPaddingDecoration(
133 getResources().getDimensionPixelSize(R.dimen.grid_padding)));
134
Santiago Etchebehere53c63432020-05-07 18:55:35 -0700135 mTileSizePx = SizeCalculator.getCategoryTileSize(getActivity());
Chuck Liao1e0501f2020-02-17 18:20:54 +0800136
137 mImageGrid.setAdapter(mAdapter);
138
Chuck Liaoddf2b522021-04-15 00:36:25 +0800139 GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(),
140 getNumColumns() * CategorySpanSizeLookup.DEFAULT_CATEGORY_SPAN_SIZE);
141 gridLayoutManager.setSpanSizeLookup(new CategorySpanSizeLookup(mAdapter));
Chuck Liao1e0501f2020-02-17 18:20:54 +0800142 mImageGrid.setLayoutManager(gridLayoutManager);
Wesley.CW Wang27ff4262020-06-12 19:19:57 +0800143 mImageGrid.setAccessibilityDelegateCompat(
Wesley.CW Wangdc68fde2020-06-15 19:12:33 +0800144 new WallpaperPickerRecyclerViewAccessibilityDelegate(
145 mImageGrid, (BottomSheetHost) getParentFragment(), getNumColumns()));
Chuck Liao58aca1c2021-03-17 01:20:55 +0800146
147 if (getCategorySelectorFragmentHost().isHostToolbarShown()) {
148 view.findViewById(R.id.header_bar).setVisibility(View.GONE);
149 getCategorySelectorFragmentHost().setToolbarTitle(getText(R.string.wallpaper_title));
150 } else {
151 setUpToolbar(view);
152 setTitle(getText(R.string.wallpaper_title));
153 }
Chuck Liao1e0501f2020-02-17 18:20:54 +0800154
Chuck Liaof6b4b192020-08-07 02:31:32 +0800155 if (!DeepLinkUtils.isDeepLink(getActivity().getIntent())) {
156 getCategorySelectorFragmentHost().fetchCategories();
157 }
158
Chihhang Chuange6c73222021-04-14 22:36:41 +0800159 // For nav bar edge-to-edge effect.
160 view.findViewById(R.id.category_grid).setOnApplyWindowInsetsListener((v, windowInsets) -> {
161 v.setPadding(
162 v.getPaddingLeft(),
163 v.getPaddingTop(),
164 v.getPaddingRight(),
165 windowInsets.getSystemWindowInsetBottom());
166 return windowInsets.consumeSystemWindowInsets();
167 });
Chuck Liao1e0501f2020-02-17 18:20:54 +0800168 return view;
169 }
170
Chuck Liao3abf15b2020-12-17 22:33:02 +0800171 @Override
172 public void onDestroyView() {
173 getCategorySelectorFragmentHost().cleanUp();
174 super.onDestroyView();
175 }
176
Chuck Liao1e0501f2020-02-17 18:20:54 +0800177 /**
178 * Inserts the given category into the categories list in priority order.
179 */
180 void addCategory(Category category, boolean loading) {
181 // If not previously waiting for categories, enter the waiting state by showing the loading
182 // indicator.
183 if (loading && !mAwaitingCategories) {
184 mAdapter.notifyItemChanged(getNumColumns());
185 mAdapter.notifyItemInserted(getNumColumns());
186 mAwaitingCategories = true;
187 }
188 // Not add existing category to category list
189 if (mCategories.indexOf(category) >= 0) {
190 updateCategory(category);
191 return;
192 }
193
194 int priority = category.getPriority();
195
196 int index = 0;
197 while (index < mCategories.size() && priority >= mCategories.get(index).getPriority()) {
198 index++;
199 }
200
201 mCategories.add(index, category);
202 if (mAdapter != null) {
203 // Offset the index because of the static metadata element at beginning of RecyclerView.
204 mAdapter.notifyItemInserted(index + NUM_NON_CATEGORY_VIEW_HOLDERS);
205 }
206 }
207
208 void removeCategory(Category category) {
209 int index = mCategories.indexOf(category);
210 if (index >= 0) {
211 mCategories.remove(index);
212 mAdapter.notifyItemRemoved(index + NUM_NON_CATEGORY_VIEW_HOLDERS);
213 }
214 }
215
216 void updateCategory(Category category) {
217 int index = mCategories.indexOf(category);
218 if (index >= 0) {
219 mCategories.remove(index);
220 mCategories.add(index, category);
221 mAdapter.notifyItemChanged(index + NUM_NON_CATEGORY_VIEW_HOLDERS);
222 }
223 }
224
225 void clearCategories() {
226 mCategories.clear();
227 mAdapter.notifyDataSetChanged();
228 }
229
230 /**
231 * Notifies the CategoryFragment that no further categories are expected so it may hide
232 * the loading indicator.
233 */
234 void doneFetchingCategories() {
235 if (mAwaitingCategories) {
236 mAdapter.notifyItemRemoved(mAdapter.getItemCount() - 1);
237 mAwaitingCategories = false;
238 }
239 }
240
241 void notifyDataSetChanged() {
242 mAdapter.notifyDataSetChanged();
243 }
244
245 private int getNumColumns() {
246 Activity activity = getActivity();
Chuck Liaoe2fe0302020-06-29 21:15:35 +0800247 return activity == null ? 1 : SizeCalculator.getNumCategoryColumns(activity);
Chuck Liao1e0501f2020-02-17 18:20:54 +0800248 }
249
250
251 private CategorySelectorFragmentHost getCategorySelectorFragmentHost() {
Chuck Liao8cbe49f2021-03-15 20:28:04 +0800252 Fragment parentFragment = getParentFragment();
253 if (parentFragment != null) {
254 return (CategorySelectorFragmentHost) parentFragment;
255 } else {
256 return (CategorySelectorFragmentHost) getActivity();
257 }
Chuck Liao1e0501f2020-02-17 18:20:54 +0800258 }
259
260 /**
261 * ViewHolder subclass for a category tile in the RecyclerView.
262 */
263 private class CategoryHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
264 private Category mCategory;
265 private ImageView mImageView;
266 private ImageView mOverlayIconView;
267 private TextView mTitleView;
268
269 CategoryHolder(View itemView) {
270 super(itemView);
271 itemView.setOnClickListener(this);
272
273 mImageView = itemView.findViewById(R.id.image);
274 mOverlayIconView = itemView.findViewById(R.id.overlay_icon);
275 mTitleView = itemView.findViewById(R.id.category_title);
276
277 CardView categoryView = itemView.findViewById(R.id.category);
278 categoryView.getLayoutParams().height = mTileSizePx.y;
279 }
280
281 @Override
282 public void onClick(View view) {
283 final UserEventLogger eventLogger =
284 InjectorProvider.getInjector().getUserEventLogger(getActivity());
285 eventLogger.logCategorySelected(mCategory.getCollectionId());
286
287 if (mCategory.supportsCustomPhotos()) {
288 getCategorySelectorFragmentHost().requestCustomPhotoPicker(
289 new MyPhotosStarter.PermissionChangedListener() {
290 @Override
291 public void onPermissionsGranted() {
292 drawThumbnailAndOverlayIcon();
293 }
294
295 @Override
296 public void onPermissionsDenied(boolean dontAskAgain) {
297 // No-op
298 }
299 });
300 return;
301 }
302
Chuck Liaoa63f1bf2020-06-11 01:35:42 +0800303 getCategorySelectorFragmentHost().show(mCategory);
Chuck Liao1e0501f2020-02-17 18:20:54 +0800304 }
305
306 /**
307 * Binds the given category to this CategoryHolder.
308 */
309 private void bindCategory(Category category) {
310 mCategory = category;
311 mTitleView.setText(category.getTitle());
312 drawThumbnailAndOverlayIcon();
313 }
314
315 /**
316 * Draws the CategoryHolder's thumbnail and overlay icon.
317 */
318 private void drawThumbnailAndOverlayIcon() {
319 mOverlayIconView.setImageDrawable(mCategory.getOverlayIcon(
320 getActivity().getApplicationContext()));
321
322 // Size the overlay icon according to the category.
323 int overlayIconDimenDp = mCategory.getOverlayIconSizeDp();
324 DisplayMetrics metrics = DisplayMetricsRetriever.getInstance().getDisplayMetrics(
325 getResources(), getActivity().getWindowManager().getDefaultDisplay());
326 int overlayIconDimenPx = (int) (overlayIconDimenDp * metrics.density);
327 mOverlayIconView.getLayoutParams().width = overlayIconDimenPx;
328 mOverlayIconView.getLayoutParams().height = overlayIconDimenPx;
329
330 Asset thumbnail = mCategory.getThumbnail(getActivity().getApplicationContext());
331 if (thumbnail != null) {
332 thumbnail.loadDrawable(getActivity(), mImageView,
333 getResources().getColor(R.color.secondary_color));
334 } else {
335 // TODO(orenb): Replace this workaround for b/62584914 with a proper way of
336 // unloading the ImageView such that no incorrect image is improperly loaded upon
337 // rapid scroll.
338 Object nullObj = null;
339 Glide.with(getActivity())
340 .asDrawable()
341 .load(nullObj)
342 .into(mImageView);
343
344 }
345 }
346 }
347
Chuck Liaoddf2b522021-04-15 00:36:25 +0800348 private class FeaturedCategoryHolder extends CategoryHolder {
349
350 FeaturedCategoryHolder(View itemView) {
351 super(itemView);
352 CardView categoryView = itemView.findViewById(R.id.category);
353 categoryView.getLayoutParams().height =
354 SizeCalculator.getFeaturedCategoryTileSize(getActivity()).y;
355 }
356 }
357
358 private class MyPhotosCategoryHolder extends CategoryHolder {
359
360 MyPhotosCategoryHolder(View itemView) {
361 super(itemView);
362 // Reuse the height of featured category since My Photos category & featured category
363 // have the same height in current UI design.
364 CardView categoryView = itemView.findViewById(R.id.category);
Tianguang Zhangbae57642021-04-19 19:46:33 +0200365 int height = SizeCalculator.getFeaturedCategoryTileSize(getActivity()).y;
366 categoryView.getLayoutParams().height = height;
367 // Use the height as the card corner radius for the "My photos" category
368 // for a stadium border.
369 categoryView.setRadius(height);
Chuck Liaoddf2b522021-04-15 00:36:25 +0800370 }
371 }
372
Chuck Liao1e0501f2020-02-17 18:20:54 +0800373 /**
374 * ViewHolder subclass for the loading indicator ("spinner") shown when categories are being
375 * fetched.
376 */
377 private class LoadingIndicatorHolder extends RecyclerView.ViewHolder {
378 private LoadingIndicatorHolder(View view) {
379 super(view);
380 ProgressBar progressBar = view.findViewById(R.id.loading_indicator);
381 progressBar.getIndeterminateDrawable().setColorFilter(
382 getResources().getColor(R.color.accent_color), PorterDuff.Mode.SRC_IN);
383 }
384 }
385
386 /**
387 * RecyclerView Adapter subclass for the category tiles in the RecyclerView.
388 */
389 private class CategoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
390 implements MyPhotosStarter.PermissionChangedListener {
Chuck Liaoddf2b522021-04-15 00:36:25 +0800391 private static final int ITEM_VIEW_TYPE_MY_PHOTOS = 1;
392 private static final int ITEM_VIEW_TYPE_FEATURED_CATEGORY = 2;
Chuck Liao1e0501f2020-02-17 18:20:54 +0800393 private static final int ITEM_VIEW_TYPE_CATEGORY = 3;
394 private static final int ITEM_VIEW_TYPE_LOADING_INDICATOR = 4;
395 private List<Category> mCategories;
396
397 private CategoryAdapter(List<Category> categories) {
398 mCategories = categories;
399 }
400
401 @Override
402 public int getItemViewType(int position) {
403 if (mAwaitingCategories && position == getItemCount() - 1) {
404 return ITEM_VIEW_TYPE_LOADING_INDICATOR;
405 }
406
Chuck Liaoddf2b522021-04-15 00:36:25 +0800407 if (position == 0) {
408 return ITEM_VIEW_TYPE_MY_PHOTOS;
409 }
410
411 if (mCategoryProvider.isFeaturedCategory(mCategories.get(position))) {
412 return ITEM_VIEW_TYPE_FEATURED_CATEGORY;
413 }
414
Chuck Liao1e0501f2020-02-17 18:20:54 +0800415 return ITEM_VIEW_TYPE_CATEGORY;
416 }
417
418 @Override
419 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
420 LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
421 View view;
422
423 switch (viewType) {
424 case ITEM_VIEW_TYPE_LOADING_INDICATOR:
425 view = layoutInflater.inflate(R.layout.grid_item_loading_indicator,
426 parent, /* attachToRoot= */ false);
427 return new LoadingIndicatorHolder(view);
Chuck Liaoddf2b522021-04-15 00:36:25 +0800428 case ITEM_VIEW_TYPE_MY_PHOTOS:
429 view = layoutInflater.inflate(R.layout.grid_item_category,
430 parent, /* attachToRoot= */ false);
431 return new MyPhotosCategoryHolder(view);
432 case ITEM_VIEW_TYPE_FEATURED_CATEGORY:
433 view = layoutInflater.inflate(R.layout.grid_item_category,
434 parent, /* attachToRoot= */ false);
435 return new FeaturedCategoryHolder(view);
Chuck Liao1e0501f2020-02-17 18:20:54 +0800436 case ITEM_VIEW_TYPE_CATEGORY:
437 view = layoutInflater.inflate(R.layout.grid_item_category,
438 parent, /* attachToRoot= */ false);
439 return new CategoryHolder(view);
440 default:
441 Log.e(TAG, "Unsupported viewType " + viewType + " in CategoryAdapter");
442 return null;
443 }
444 }
445
446 @Override
447 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
448 int viewType = getItemViewType(position);
449
450 switch (viewType) {
Chuck Liaoddf2b522021-04-15 00:36:25 +0800451 case ITEM_VIEW_TYPE_MY_PHOTOS:
452 case ITEM_VIEW_TYPE_FEATURED_CATEGORY:
Chuck Liao1e0501f2020-02-17 18:20:54 +0800453 case ITEM_VIEW_TYPE_CATEGORY:
454 // Offset position to get category index to account for the non-category view
455 // holders.
456 Category category = mCategories.get(position - NUM_NON_CATEGORY_VIEW_HOLDERS);
457 ((CategoryHolder) holder).bindCategory(category);
458 break;
459 case ITEM_VIEW_TYPE_LOADING_INDICATOR:
460 // No op.
461 break;
462 default:
463 Log.e(TAG, "Unsupported viewType " + viewType + " in CategoryAdapter");
464 }
465 }
466
467 @Override
468 public int getItemCount() {
469 // Add to size of categories to account for the metadata related views.
470 // Add 1 more for the loading indicator if not yet done loading.
471 int size = mCategories.size() + NUM_NON_CATEGORY_VIEW_HOLDERS;
472 if (mAwaitingCategories) {
473 size += 1;
474 }
475
476 return size;
477 }
478
479 @Override
480 public void onPermissionsGranted() {
481 notifyDataSetChanged();
482 }
483
484 @Override
485 public void onPermissionsDenied(boolean dontAskAgain) {
486 if (!dontAskAgain) {
487 return;
488 }
489
490 String permissionNeededMessage =
491 getString(R.string.permission_needed_explanation_go_to_settings);
492 AlertDialog dialog = new AlertDialog.Builder(getActivity(), R.style.LightDialogTheme)
493 .setMessage(permissionNeededMessage)
494 .setPositiveButton(android.R.string.ok, null /* onClickListener */)
495 .setNegativeButton(
496 R.string.settings_button_label,
497 (dialogInterface, i) -> {
498 Intent appInfoIntent =
499 new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
500 Uri uri = Uri.fromParts("package",
501 getActivity().getPackageName(), /* fragment= */ null);
502 appInfoIntent.setData(uri);
503 startActivityForResult(
504 appInfoIntent, SETTINGS_APP_INFO_REQUEST_CODE);
505 })
506 .create();
507 dialog.show();
508 }
509 }
510
511 private class GridPaddingDecoration extends RecyclerView.ItemDecoration {
512
513 private int mPadding;
514
515 GridPaddingDecoration(int padding) {
516 mPadding = padding;
517 }
518
519 @Override
520 public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
521 RecyclerView.State state) {
522 int position = parent.getChildAdapterPosition(view) - NUM_NON_CATEGORY_VIEW_HOLDERS;
523 if (position >= 0) {
524 outRect.left = mPadding;
525 outRect.right = mPadding;
526 }
527 }
528 }
529
530 /**
531 * SpanSizeLookup subclass which provides that the item in the first position spans the number
532 * of columns in the RecyclerView and all other items only take up a single span.
533 */
534 private class CategorySpanSizeLookup extends GridLayoutManager.SpanSizeLookup {
Chuck Liaoddf2b522021-04-15 00:36:25 +0800535 private static final int DEFAULT_CATEGORY_SPAN_SIZE = 2;
536
Chuck Liao1e0501f2020-02-17 18:20:54 +0800537 CategoryAdapter mAdapter;
538
539 private CategorySpanSizeLookup(CategoryAdapter adapter) {
540 mAdapter = adapter;
541 }
542
543 @Override
544 public int getSpanSize(int position) {
Chuck Liaoddf2b522021-04-15 00:36:25 +0800545 if (position < NUM_NON_CATEGORY_VIEW_HOLDERS || mAdapter.getItemViewType(position)
546 == CategoryAdapter.ITEM_VIEW_TYPE_LOADING_INDICATOR || mAdapter.getItemViewType(
547 position) == CategoryAdapter.ITEM_VIEW_TYPE_MY_PHOTOS) {
548 return getNumColumns() * DEFAULT_CATEGORY_SPAN_SIZE;
Chuck Liao1e0501f2020-02-17 18:20:54 +0800549 }
550
Chuck Liaoddf2b522021-04-15 00:36:25 +0800551 if (mAdapter.getItemViewType(position)
552 == CategoryAdapter.ITEM_VIEW_TYPE_FEATURED_CATEGORY) {
553 return getNumColumns() * DEFAULT_CATEGORY_SPAN_SIZE / 2;
554 }
555
556 return DEFAULT_CATEGORY_SPAN_SIZE;
Chuck Liao1e0501f2020-02-17 18:20:54 +0800557 }
558 }
Chuck Liao1e0501f2020-02-17 18:20:54 +0800559}