1 /*
2  * Copyright (C) 2024 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 
17 package com.android.settings.notification.modes;
18 
19 import android.content.Context;
20 import android.view.LayoutInflater;
21 import android.view.View;
22 import android.view.ViewGroup;
23 import android.widget.ImageView;
24 
25 import androidx.annotation.DrawableRes;
26 import androidx.annotation.NonNull;
27 import androidx.annotation.Nullable;
28 import androidx.annotation.VisibleForTesting;
29 import androidx.preference.Preference;
30 import androidx.preference.PreferenceScreen;
31 import androidx.recyclerview.widget.GridLayoutManager;
32 import androidx.recyclerview.widget.RecyclerView;
33 
34 import com.android.settings.R;
35 import com.android.settings.dashboard.DashboardFragment;
36 import com.android.settingslib.widget.LayoutPreference;
37 
38 import com.google.common.collect.ImmutableList;
39 
40 class ZenModeIconPickerListPreferenceController extends AbstractZenModePreferenceController {
41 
42     private final DashboardFragment mFragment;
43     private final IconOptionsProvider mIconOptionsProvider;
44     @Nullable private IconAdapter mAdapter;
45 
ZenModeIconPickerListPreferenceController(@onNull Context context, @NonNull String key, @NonNull DashboardFragment fragment, @NonNull IconOptionsProvider iconOptionsProvider, @Nullable ZenModesBackend backend)46     ZenModeIconPickerListPreferenceController(@NonNull Context context, @NonNull String key,
47             @NonNull DashboardFragment fragment, @NonNull IconOptionsProvider iconOptionsProvider,
48             @Nullable ZenModesBackend backend) {
49         super(context, key, backend);
50         mFragment = fragment;
51         mIconOptionsProvider = iconOptionsProvider;
52     }
53 
54     @Override
displayPreference(PreferenceScreen screen)55     public void displayPreference(PreferenceScreen screen) {
56         super.displayPreference(screen);
57         LayoutPreference pref = screen.findPreference(getPreferenceKey());
58         if (pref == null) {
59             return;
60         }
61 
62         if (mAdapter == null) {
63             mAdapter = new IconAdapter(mIconOptionsProvider);
64         }
65         RecyclerView recyclerView = pref.findViewById(R.id.icon_list);
66         recyclerView.setLayoutManager(new AutoFitGridLayoutManager(mContext));
67         recyclerView.setAdapter(mAdapter);
68         recyclerView.setHasFixedSize(true);
69     }
70 
71     @VisibleForTesting
onIconSelected(@rawableRes int resId)72     void onIconSelected(@DrawableRes int resId) {
73         saveMode(mode -> {
74             mode.getRule().setIconResId(resId);
75             return mode;
76         });
77         mFragment.finish();
78     }
79 
80     @Override
updateState(Preference preference, @NonNull ZenMode zenMode)81     void updateState(Preference preference, @NonNull ZenMode zenMode) {
82         // Nothing to do, the current icon is shown in a different preference.
83     }
84 
85     private class IconHolder extends RecyclerView.ViewHolder {
86 
87         private final ImageView mImageView;
88 
IconHolder(@onNull View itemView)89         IconHolder(@NonNull View itemView) {
90             super(itemView);
91             mImageView = itemView.findViewById(R.id.icon_image_view);
92         }
93 
bindIcon(IconOptionsProvider.IconInfo icon)94         void bindIcon(IconOptionsProvider.IconInfo icon) {
95             mImageView.setImageDrawable(
96                     IconUtil.makeIconCircle(itemView.getContext(), icon.resId()));
97             itemView.setContentDescription(icon.description());
98             itemView.setOnClickListener(v -> onIconSelected(icon.resId()));
99         }
100     }
101 
102     private class IconAdapter extends RecyclerView.Adapter<IconHolder> {
103 
104         private final ImmutableList<IconOptionsProvider.IconInfo> mIconResources;
105 
IconAdapter(IconOptionsProvider iconOptionsProvider)106         private IconAdapter(IconOptionsProvider iconOptionsProvider) {
107             mIconResources = iconOptionsProvider.getIcons();
108         }
109 
110         @NonNull
111         @Override
onCreateViewHolder(@onNull ViewGroup parent, int viewType)112         public IconHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
113             View itemView = LayoutInflater.from(parent.getContext()).inflate(
114                     R.layout.modes_icon_list_item, parent, false);
115             return new IconHolder(itemView);
116         }
117 
118         @Override
onBindViewHolder(@onNull IconHolder holder, int position)119         public void onBindViewHolder(@NonNull IconHolder holder, int position) {
120             holder.bindIcon(mIconResources.get(position));
121         }
122 
123         @Override
getItemCount()124         public int getItemCount() {
125             return mIconResources.size();
126         }
127     }
128 
129     private static class AutoFitGridLayoutManager extends GridLayoutManager {
130         private final float mColumnWidth;
131 
AutoFitGridLayoutManager(Context context)132         AutoFitGridLayoutManager(Context context) {
133             super(context, /* spanCount= */ 1);
134             this.mColumnWidth = context
135                     .getResources()
136                     .getDimensionPixelSize(R.dimen.zen_mode_icon_list_item_size);
137         }
138 
139         @Override
onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state)140         public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
141             final int totalSpace = getWidth() - getPaddingRight() - getPaddingLeft();
142             final int spanCount = Math.max(1, (int) (totalSpace / mColumnWidth));
143             setSpanCount(spanCount);
144             super.onLayoutChildren(recycler, state);
145         }
146     }
147 }
148