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 { class ZenModeActionsPreferenceController extends AbstractZenModePreferenceController {
private ActionButtonsPreference mPreference;
ZenModeActionsPreferenceController(@NonNull Context context, @NonNull String key, ZenModeActionsPreferenceController(@NonNull Context context, @NonNull String key,
@Nullable ZenModesBackend backend) { @Nullable ZenModesBackend backend) {
super(context, key, backend); super(context, key, backend);

View File

@@ -44,6 +44,7 @@ public class ZenModeIconPickerFragment extends ZenModeFragmentBase {
new ZenModeIconPickerIconPreferenceController(context, "current_icon", this, new ZenModeIconPickerIconPreferenceController(context, "current_icon", this,
mBackend), mBackend),
new ZenModeIconPickerListPreferenceController(context, "icon_list", this, 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 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 { class ZenModeIconPickerListPreferenceController extends AbstractZenModePreferenceController {
private final DashboardFragment mFragment; private final DashboardFragment mFragment;
private IconAdapter mAdapter; private final IconOptionsProvider mIconOptionsProvider;
@Nullable private IconAdapter mAdapter;
ZenModeIconPickerListPreferenceController(@NonNull Context context, @NonNull String key, 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); super(context, key, backend);
mFragment = fragment; mFragment = fragment;
mIconOptionsProvider = iconOptionsProvider;
} }
@Override @Override
@@ -64,24 +60,7 @@ class ZenModeIconPickerListPreferenceController extends AbstractZenModePreferenc
} }
if (mAdapter == null) { if (mAdapter == null) {
// TODO: b/333901673 - This is just an example; replace with correct list. mAdapter = new IconAdapter(mIconOptionsProvider);
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);
} }
RecyclerView recyclerView = pref.findViewById(R.id.icon_list); RecyclerView recyclerView = pref.findViewById(R.id.icon_list);
recyclerView.setLayoutManager(new AutoFitGridLayoutManager(mContext)); 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. // 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 class IconHolder extends RecyclerView.ViewHolder {
private final ImageView mImageView; private final ImageView mImageView;
@@ -114,7 +91,7 @@ class ZenModeIconPickerListPreferenceController extends AbstractZenModePreferenc
mImageView = itemView.findViewById(R.id.icon_image_view); mImageView = itemView.findViewById(R.id.icon_image_view);
} }
void bindIcon(IconInfo icon) { void bindIcon(IconOptionsProvider.IconInfo icon) {
mImageView.setImageDrawable( mImageView.setImageDrawable(
IconUtil.makeIconCircle(itemView.getContext(), icon.resId())); IconUtil.makeIconCircle(itemView.getContext(), icon.resId()));
itemView.setContentDescription(icon.description()); itemView.setContentDescription(icon.description());
@@ -124,10 +101,10 @@ class ZenModeIconPickerListPreferenceController extends AbstractZenModePreferenc
private class IconAdapter extends RecyclerView.Adapter<IconHolder> { private class IconAdapter extends RecyclerView.Adapter<IconHolder> {
private final ImmutableList<IconInfo> mIconResources; private final ImmutableList<IconOptionsProvider.IconInfo> mIconResources;
private IconAdapter(List<IconInfo> iconOptions) { private IconAdapter(IconOptionsProvider iconOptionsProvider) {
mIconResources = ImmutableList.copyOf(iconOptions); mIconResources = iconOptionsProvider.getIcons();
} }
@NonNull @NonNull

View File

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