Follow-up improvements to zen mode icon picker

* Propose icons from com.android.internal.R instead of android.R (as a proof of concept) since this is what we'll be doing with the final icons.
* Provide the icon options as a parameter to the controller (can also be used for testing).
* Fix some Lint warnings.

Test: atest ZenModeIconPickerListPreferenceControllerTest
Bug: 333901673
Flag: android.app.modes_ui
Change-Id: I023eed0fd5719c5c4540f8d145335f60d088e7fb
This commit is contained in:
Matías Hernández
2024-06-12 19:33:12 +02:00
parent 98a5dbfb42
commit 37bdf39ad6
6 changed files with 104 additions and 38 deletions

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification.modes;
import androidx.annotation.DrawableRes;
import com.google.common.collect.ImmutableList;
interface IconOptionsProvider {
ImmutableList<IconInfo> getIcons();
record IconInfo(@DrawableRes int resId, String description) { }
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification.modes;
import com.google.common.collect.ImmutableList;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
/** Temporary implementation of {@link IconOptionsProvider} until we have the real list. */
class TempIconOptionsProvider implements IconOptionsProvider {
@Override
public ImmutableList<IconInfo> getIcons() {
return ImmutableList.copyOf(
Arrays.stream(com.android.internal.R.drawable.class.getFields())
.filter(
f -> Modifier.isStatic(f.getModifiers())
&& Modifier.isFinal(f.getModifiers())
&& f.getName().startsWith("ic_"))
.limit(20)
.map(f -> {
try {
return new IconInfo(f.getInt(null), f.getName());
} catch (IllegalAccessException e) {
return null;
}
})
.filter(Objects::nonNull)
.sorted(Comparator.comparing(IconInfo::resId).reversed())
.toList());
}
}

View File

@@ -31,8 +31,6 @@ import com.android.settingslib.widget.ActionButtonsPreference;
class ZenModeActionsPreferenceController extends AbstractZenModePreferenceController {
private ActionButtonsPreference mPreference;
ZenModeActionsPreferenceController(@NonNull Context context, @NonNull String key,
@Nullable ZenModesBackend backend) {
super(context, key, backend);

View File

@@ -44,6 +44,7 @@ public class ZenModeIconPickerFragment extends ZenModeFragmentBase {
new ZenModeIconPickerIconPreferenceController(context, "current_icon", this,
mBackend),
new ZenModeIconPickerListPreferenceController(context, "icon_list", this,
mBackend));
// TODO: b/333901673 - Replace with correct icon list.
new TempIconOptionsProvider(), mBackend));
}
}

View File

@@ -37,22 +37,18 @@ import com.android.settingslib.widget.LayoutPreference;
import com.google.common.collect.ImmutableList;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
class ZenModeIconPickerListPreferenceController extends AbstractZenModePreferenceController {
private final DashboardFragment mFragment;
private IconAdapter mAdapter;
private final IconOptionsProvider mIconOptionsProvider;
@Nullable private IconAdapter mAdapter;
ZenModeIconPickerListPreferenceController(@NonNull Context context, @NonNull String key,
@NonNull DashboardFragment fragment, @Nullable ZenModesBackend backend) {
@NonNull DashboardFragment fragment, @NonNull IconOptionsProvider iconOptionsProvider,
@Nullable ZenModesBackend backend) {
super(context, key, backend);
mFragment = fragment;
mIconOptionsProvider = iconOptionsProvider;
}
@Override
@@ -64,24 +60,7 @@ class ZenModeIconPickerListPreferenceController extends AbstractZenModePreferenc
}
if (mAdapter == null) {
// TODO: b/333901673 - This is just an example; replace with correct list.
List<IconInfo> exampleIcons =
Arrays.stream(android.R.drawable.class.getFields())
.filter(
f -> Modifier.isStatic(f.getModifiers())
&& f.getName().startsWith("ic_"))
.sorted(Comparator.comparing(Field::getName))
.limit(20)
.map(f -> {
try {
return new IconInfo(f.getInt(null), f.getName());
} catch (IllegalAccessException e) {
return null;
}
})
.filter(Objects::nonNull)
.toList();
mAdapter = new IconAdapter(exampleIcons);
mAdapter = new IconAdapter(mIconOptionsProvider);
}
RecyclerView recyclerView = pref.findViewById(R.id.icon_list);
recyclerView.setLayoutManager(new AutoFitGridLayoutManager(mContext));
@@ -103,8 +82,6 @@ class ZenModeIconPickerListPreferenceController extends AbstractZenModePreferenc
// Nothing to do, the current icon is shown in a different preference.
}
private record IconInfo(@DrawableRes int resId, String description) { }
private class IconHolder extends RecyclerView.ViewHolder {
private final ImageView mImageView;
@@ -114,7 +91,7 @@ class ZenModeIconPickerListPreferenceController extends AbstractZenModePreferenc
mImageView = itemView.findViewById(R.id.icon_image_view);
}
void bindIcon(IconInfo icon) {
void bindIcon(IconOptionsProvider.IconInfo icon) {
mImageView.setImageDrawable(
IconUtil.makeIconCircle(itemView.getContext(), icon.resId()));
itemView.setContentDescription(icon.description());
@@ -124,10 +101,10 @@ class ZenModeIconPickerListPreferenceController extends AbstractZenModePreferenc
private class IconAdapter extends RecyclerView.Adapter<IconHolder> {
private final ImmutableList<IconInfo> mIconResources;
private final ImmutableList<IconOptionsProvider.IconInfo> mIconResources;
private IconAdapter(List<IconInfo> iconOptions) {
mIconResources = ImmutableList.copyOf(iconOptions);
private IconAdapter(IconOptionsProvider iconOptionsProvider) {
mIconResources = iconOptionsProvider.getIcons();
}
@NonNull

View File

@@ -34,6 +34,8 @@ import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.widget.LayoutPreference;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -61,7 +63,8 @@ public class ZenModeIconPickerListPreferenceControllerTest {
DashboardFragment fragment = mock(DashboardFragment.class);
mController = new ZenModeIconPickerListPreferenceController(
RuntimeEnvironment.getApplication(), "icon_list", fragment, mBackend);
RuntimeEnvironment.getApplication(), "icon_list", fragment,
new TestIconOptionsProvider(), mBackend);
mRecyclerView = new RecyclerView(context);
mRecyclerView.setId(R.id.icon_list);
@@ -75,7 +78,7 @@ public class ZenModeIconPickerListPreferenceControllerTest {
mController.displayPreference(mPreferenceScreen);
assertThat(mRecyclerView.getAdapter()).isNotNull();
assertThat(mRecyclerView.getAdapter().getItemCount()).isEqualTo(20);
assertThat(mRecyclerView.getAdapter().getItemCount()).isEqualTo(3);
}
@Test
@@ -88,4 +91,15 @@ public class ZenModeIconPickerListPreferenceControllerTest {
verify(mBackend).updateMode(captor.capture());
assertThat(captor.getValue().getRule().getIconResId()).isEqualTo(R.drawable.ic_android);
}
private static class TestIconOptionsProvider implements IconOptionsProvider {
@Override
public ImmutableList<IconInfo> getIcons() {
return ImmutableList.of(
new IconInfo(R.drawable.ic_android, "android"),
new IconInfo(R.drawable.ic_info, "info"),
new IconInfo(R.drawable.ic_hearing, "hearing"));
}
}
}