Final (?) touches to people/apps/sound circles
* Support comparing icon sets with a custom equivalence (needed because AppEntry doesn't implement equals(), and somewhat tricky because CircularIconPreference itself is not generic).
* Use final icons for allowed sounds.
* Use final appearance for +n icon.
Test: atest com.android.settings.notification.modes
Bug: 346551087
Flag: android.app.modes_ui
Change-Id: Iceadf4a182e607111afb72ff36bca872a62ae040
diff --git a/res/drawable/ic_zen_mode_sound_alarms.xml b/res/drawable/ic_zen_mode_sound_alarms.xml
new file mode 100644
index 0000000..b2761ca
--- /dev/null
+++ b/res/drawable/ic_zen_mode_sound_alarms.xml
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M480,880Q405,880 339.5,851.5Q274,823 225.5,774.5Q177,726 148.5,660.5Q120,595 120,520Q120,445 148.5,379.5Q177,314 225.5,265.5Q274,217 339.5,188.5Q405,160 480,160Q555,160 620.5,188.5Q686,217 734.5,265.5Q783,314 811.5,379.5Q840,445 840,520Q840,595 811.5,660.5Q783,726 734.5,774.5Q686,823 620.5,851.5Q555,880 480,880ZM480,520Q480,520 480,520Q480,520 480,520Q480,520 480,520Q480,520 480,520Q480,520 480,520Q480,520 480,520Q480,520 480,520Q480,520 480,520ZM592,688L648,632L520,504L520,320L440,320L440,536L592,688ZM224,94L280,150L110,320L54,264L224,94ZM736,94L906,264L850,320L680,150L736,94ZM480,800Q597,800 678.5,718.5Q760,637 760,520Q760,403 678.5,321.5Q597,240 480,240Q363,240 281.5,321.5Q200,403 200,520Q200,637 281.5,718.5Q363,800 480,800Z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_zen_mode_sound_events.xml b/res/drawable/ic_zen_mode_sound_events.xml
new file mode 100644
index 0000000..15035e4
--- /dev/null
+++ b/res/drawable/ic_zen_mode_sound_events.xml
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M580,720Q538,720 509,691Q480,662 480,620Q480,578 509,549Q538,520 580,520Q622,520 651,549Q680,578 680,620Q680,662 651,691Q622,720 580,720ZM200,880Q167,880 143.5,856.5Q120,833 120,800L120,240Q120,207 143.5,183.5Q167,160 200,160L240,160L240,80L320,80L320,160L640,160L640,80L720,80L720,160L760,160Q793,160 816.5,183.5Q840,207 840,240L840,800Q840,833 816.5,856.5Q793,880 760,880L200,880ZM200,800L760,800Q760,800 760,800Q760,800 760,800L760,400L200,400L200,800Q200,800 200,800Q200,800 200,800ZM200,320L760,320L760,240Q760,240 760,240Q760,240 760,240L200,240Q200,240 200,240Q200,240 200,240L200,320ZM200,320L200,240Q200,240 200,240Q200,240 200,240L200,240Q200,240 200,240Q200,240 200,240L200,320Z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_zen_mode_sound_media.xml b/res/drawable/ic_zen_mode_sound_media.xml
new file mode 100644
index 0000000..f2bedcb
--- /dev/null
+++ b/res/drawable/ic_zen_mode_sound_media.xml
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M400,840Q334,840 287,793Q240,746 240,680Q240,614 287,567Q334,520 400,520Q423,520 442.5,525.5Q462,531 480,542L480,120L720,120L720,280L560,280L560,680Q560,746 513,793Q466,840 400,840Z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_zen_mode_sound_reminders.xml b/res/drawable/ic_zen_mode_sound_reminders.xml
new file mode 100644
index 0000000..cd9490a
--- /dev/null
+++ b/res/drawable/ic_zen_mode_sound_reminders.xml
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M260,320L300,320L300,280Q300,263 288.5,251.5Q277,240 260,240Q243,240 231.5,251.5Q220,263 220,280Q220,297 231.5,308.5Q243,320 260,320ZM440,320Q457,320 468.5,308.5Q480,297 480,280Q480,263 468.5,251.5Q457,240 440,240Q423,240 411.5,251.5Q400,263 400,280L400,320L440,320ZM502,620L502,620L502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620L502,620ZM419,880Q391,880 366.5,868Q342,856 325,834L107,557L126,537Q146,516 174,512Q202,508 226,523L300,568L300,400L260,400Q210,400 175,365Q140,330 140,280Q140,230 175,195Q210,160 260,160Q271,160 280.5,162Q290,164 300,167L300,120Q300,103 311.5,91.5Q323,80 340,80Q357,80 369,91.5Q381,103 381,120L381,176Q395,168 409.5,164Q424,160 440,160Q490,160 525,195Q560,230 560,280Q560,330 525,365Q490,400 440,400L381,400L381,712L284,652L388,785Q394,792 402,796Q410,800 419,800L640,800Q673,800 696.5,776.5Q720,753 720,720L720,560Q720,543 708.5,531.5Q697,520 680,520L461,520L461,440L680,440Q730,440 765,475Q800,510 800,560L800,720Q800,786 753,833Q706,880 640,880L419,880Z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_zen_mode_sound_system.xml b/res/drawable/ic_zen_mode_sound_system.xml
new file mode 100644
index 0000000..2da05d8
--- /dev/null
+++ b/res/drawable/ic_zen_mode_sound_system.xml
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M419,880Q391,880 366.5,868Q342,856 325,834L107,557L126,537Q146,516 174,512Q202,508 226,523L300,568L300,240Q300,223 311.5,211.5Q323,200 340,200Q357,200 369,211.5Q381,223 381,240L381,712L284,652L388,785Q394,792 402,796Q410,800 419,800L640,800Q673,800 696.5,776.5Q720,753 720,720L720,560Q720,543 708.5,531.5Q697,520 680,520L461,520L461,440L680,440Q730,440 765,475Q800,510 800,560L800,720Q800,786 753,833Q706,880 640,880L419,880ZM167,340Q154,318 147,292.5Q140,267 140,240Q140,157 198.5,98.5Q257,40 340,40Q423,40 481.5,98.5Q540,157 540,240Q540,267 533,292.5Q526,318 513,340L444,300Q452,286 456,271.5Q460,257 460,240Q460,190 425,155Q390,120 340,120Q290,120 255,155Q220,190 220,240Q220,257 224,271.5Q228,286 236,300L167,340ZM502,620L502,620L502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620L502,620Z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/preference_circular_icons_plus_item_background.xml b/res/drawable/preference_circular_icons_plus_item_background.xml
index 8200a9b..faaa1fd 100644
--- a/res/drawable/preference_circular_icons_plus_item_background.xml
+++ b/res/drawable/preference_circular_icons_plus_item_background.xml
@@ -22,7 +22,4 @@
android:width="@dimen/zen_mode_circular_icon_diameter"
android:height="@dimen/zen_mode_circular_icon_diameter" />
<solid android:color="?androidprv:attr/materialColorSecondaryContainer" />
- <!-- TODO: b/346551087 - Include border (or not) according to final design
- <stroke android:width="1dp" android:color="?androidprv:attr/materialColorOnSecondaryContainer" />
- -->
</shape>
\ No newline at end of file
diff --git a/src/com/android/settings/notification/modes/CircularIconSet.java b/src/com/android/settings/notification/modes/CircularIconSet.java
index 18f82d9..eb7289a 100644
--- a/src/com/android/settings/notification/modes/CircularIconSet.java
+++ b/src/com/android/settings/notification/modes/CircularIconSet.java
@@ -20,8 +20,10 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.google.common.base.Equivalence;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
@@ -29,6 +31,7 @@
import com.google.common.util.concurrent.MoreExecutors;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -67,8 +70,25 @@
return MoreObjects.toStringHelper(this).add("items", mItems).toString();
}
- boolean hasSameItemsAs(CircularIconSet<?> other) {
- return other != null && this.mItems.equals(other.mItems);
+ @SuppressWarnings("unchecked")
+ <OtherT> boolean hasSameItemsAs(CircularIconSet<OtherT> other,
+ @Nullable Equivalence<OtherT> equivalence) {
+ if (other == null) {
+ return false;
+ }
+ if (other == this) {
+ return true;
+ }
+ if (equivalence == null) {
+ return mItems.equals(other.mItems);
+ }
+ // Check that types match before applying equivalence (statically unsafe). :(
+ Optional<Class<?>> thisItemClass = this.mItems.stream().findFirst().map(T::getClass);
+ Optional<Class<?>> otherItemClass = other.mItems.stream().findFirst().map(OtherT::getClass);
+ if (!thisItemClass.equals(otherItemClass)) {
+ return false;
+ }
+ return equivalence.pairwise().equivalent((Iterable<OtherT>) this.mItems, other.mItems);
}
int size() {
diff --git a/src/com/android/settings/notification/modes/CircularIconsPreference.java b/src/com/android/settings/notification/modes/CircularIconsPreference.java
index 5e8f720..1ce3476 100644
--- a/src/com/android/settings/notification/modes/CircularIconsPreference.java
+++ b/src/com/android/settings/notification/modes/CircularIconsPreference.java
@@ -41,6 +41,7 @@
import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.Utils;
+import com.google.common.base.Equivalence;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -105,8 +106,12 @@
}
}
- void displayIcons(CircularIconSet<?> iconSet) {
- if (mIconSet != null && mIconSet.hasSameItemsAs(iconSet)) {
+ <T> void displayIcons(CircularIconSet<T> iconSet) {
+ displayIcons(iconSet, null);
+ }
+
+ <T> void displayIcons(CircularIconSet<T> iconSet, @Nullable Equivalence<T> itemEquivalence) {
+ if (mIconSet != null && mIconSet.hasSameItemsAs(iconSet, itemEquivalence)) {
return;
}
mIconSet = iconSet;
@@ -189,7 +194,6 @@
}
// ... plus 0/1 TextViews at the end.
if (extraItems > 0 && !(getLastChild(mIconContainer) instanceof TextView)) {
- // TODO: b/346551087 - Check TODO in preference_circular_icons_plus_item_background
TextView plusView = (TextView) inflater.inflate(
R.layout.preference_circular_icons_plus_item, mIconContainer, false);
mIconContainer.addView(plusView);
diff --git a/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java
index 9bff2bb..962e016 100644
--- a/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java
@@ -40,6 +40,7 @@
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
+import com.google.common.base.Equivalence;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
@@ -47,6 +48,7 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+import java.util.Objects;
/**
* Preference with a link and summary about what apps can break through the mode
@@ -137,7 +139,8 @@
mPreference.setSummary(mSummaryHelper.getAppsSummary(mZenMode, apps));
mPreference.displayIcons(new CircularIconSet<>(apps,
- app -> Utils.getBadgedIcon(mContext, app.info)));
+ app -> Utils.getBadgedIcon(mContext, app.info)),
+ APP_ENTRY_EQUIVALENCE);
}
@VisibleForTesting
@@ -158,6 +161,19 @@
.toList());
}
+ private static final Equivalence<AppEntry> APP_ENTRY_EQUIVALENCE = new Equivalence<>() {
+ @Override
+ protected boolean doEquivalent(@NonNull AppEntry a, @NonNull AppEntry b) {
+ return a.info.uid == b.info.uid
+ && Objects.equals(a.info.packageName, b.info.packageName);
+ }
+
+ @Override
+ protected int doHash(@NonNull AppEntry entry) {
+ return Objects.hash(entry.info.uid, entry.info.packageName);
+ }
+ };
+
@VisibleForTesting
final ApplicationsState.Callbacks mAppSessionCallbacks =
new ApplicationsState.Callbacks() {
diff --git a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java
index 206ad42..d7bd517 100644
--- a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java
@@ -29,6 +29,7 @@
import androidx.annotation.NonNull;
import androidx.preference.Preference;
+import com.android.settings.R;
import com.android.settingslib.notification.modes.ZenMode;
import com.google.common.collect.ImmutableList;
@@ -41,19 +42,13 @@
*/
class ZenModeOtherLinkPreferenceController extends AbstractZenModePreferenceController {
- // TODO: b/346551087 - Use proper icons
private static final ImmutableMap</* @PriorityCategory */ Integer, /* @DrawableRes */ Integer>
PRIORITIES_TO_ICONS = ImmutableMap.of(
- PRIORITY_CATEGORY_ALARMS,
- com.android.internal.R.drawable.ic_audio_alarm,
- PRIORITY_CATEGORY_MEDIA,
- com.android.settings.R.drawable.ic_media_stream,
- PRIORITY_CATEGORY_SYSTEM,
- com.android.settings.R.drawable.ic_settings_keyboards,
- PRIORITY_CATEGORY_REMINDERS,
- com.android.internal.R.drawable.ic_popup_reminder,
- PRIORITY_CATEGORY_EVENTS,
- com.android.internal.R.drawable.ic_zen_mode_type_schedule_calendar);
+ PRIORITY_CATEGORY_ALARMS, R.drawable.ic_zen_mode_sound_alarms,
+ PRIORITY_CATEGORY_MEDIA, R.drawable.ic_zen_mode_sound_media,
+ PRIORITY_CATEGORY_SYSTEM, R.drawable.ic_zen_mode_sound_system,
+ PRIORITY_CATEGORY_REMINDERS, R.drawable.ic_zen_mode_sound_reminders,
+ PRIORITY_CATEGORY_EVENTS, R.drawable.ic_zen_mode_sound_events);
private final ZenModeSummaryHelper mSummaryHelper;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/CircularIconSetTest.java b/tests/robotests/src/com/android/settings/notification/modes/CircularIconSetTest.java
index 9e85243..826c9df 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/CircularIconSetTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/CircularIconSetTest.java
@@ -27,6 +27,7 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import com.google.common.base.Equivalence;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
@@ -54,33 +55,111 @@
}
@Test
- public void equals_sameItems_true() {
+ public void hasSameItemsAs_sameItems_true() {
CircularIconSet<Integer> items1 = new CircularIconSet<>(ImmutableList.of(1, 2),
num -> new ColorDrawable(Color.BLUE));
CircularIconSet<Integer> items2 = new CircularIconSet<>(ImmutableList.of(1, 2),
num -> new ColorDrawable(Color.GREEN));
- assertThat(items1.hasSameItemsAs(items2)).isTrue();
+ assertThat(items1.hasSameItemsAs(items2, null)).isTrue();
}
@Test
- public void equals_differentTypes_false() {
+ public void hasSameItemsAs_differentTypes_false() {
CircularIconSet<Integer> items1 = new CircularIconSet<>(ImmutableList.of(1, 2),
num -> new ColorDrawable(Color.BLUE));
CircularIconSet<String> items2 = new CircularIconSet<>(ImmutableList.of("a", "b"),
str -> new ColorDrawable(Color.GREEN));
- assertThat(items1.hasSameItemsAs(items2)).isFalse();
+ assertThat(items1.hasSameItemsAs(items2, null)).isFalse();
}
@Test
- public void equals_differentItems_false() {
+ public void hasSameItemsAs_differentItems_false() {
CircularIconSet<String> items1 = new CircularIconSet<>(ImmutableList.of("a", "b"),
str -> new ColorDrawable(Color.GREEN));
CircularIconSet<String> items2 = new CircularIconSet<>(ImmutableList.of("a", "b", "c"),
str -> new ColorDrawable(Color.GREEN));
- assertThat(items1.hasSameItemsAs(items2)).isFalse();
+ assertThat(items1.hasSameItemsAs(items2, null)).isFalse();
+ }
+
+ private static class WrapperWithoutEquals<T> {
+ private final T mValue;
+ private WrapperWithoutEquals(T value) {
+ mValue = value;
+ }
+ }
+
+ @Test
+ public void hasSameItemsAs_withEquivalence_trueIfEquivalentItems() {
+ CircularIconSet<WrapperWithoutEquals<Integer>> items1 = new CircularIconSet<>(
+ ImmutableList.of(
+ new WrapperWithoutEquals<>(1),
+ new WrapperWithoutEquals<>(2)),
+ unused -> new ColorDrawable(Color.BLACK));
+ CircularIconSet<WrapperWithoutEquals<Integer>> items2 = new CircularIconSet<>(
+ ImmutableList.of(
+ new WrapperWithoutEquals<>(1),
+ new WrapperWithoutEquals<>(2)),
+ unused -> new ColorDrawable(Color.BLACK));
+ CircularIconSet<WrapperWithoutEquals<Integer>> items3 = new CircularIconSet<>(
+ ImmutableList.of(
+ new WrapperWithoutEquals<>(2),
+ new WrapperWithoutEquals<>(3)),
+ unused -> new ColorDrawable(Color.BLACK));
+ // Needs special equivalence, equals is not enough.
+ assertThat(items1.hasSameItemsAs(items2, null)).isFalse();
+
+ Equivalence<WrapperWithoutEquals<Integer>> equivalence = new Equivalence<>() {
+ @Override
+ protected boolean doEquivalent(WrapperWithoutEquals<Integer> a,
+ WrapperWithoutEquals<Integer> b) {
+ return a.mValue.equals(b.mValue);
+ }
+
+ @Override
+ protected int doHash(WrapperWithoutEquals<Integer> t) {
+ return t.mValue;
+ }
+ };
+
+ assertThat(items1.hasSameItemsAs(items2, equivalence)).isTrue();
+ assertThat(items1.hasSameItemsAs(items3, equivalence)).isFalse();
+ }
+
+ @Test
+ public void hasSameItemsAs_withEquivalenceButDifferentTypes_falseAndNoClassCastExceptions() {
+ CircularIconSet<Integer> items1 = new CircularIconSet<>(ImmutableList.of(1, 2),
+ num -> new ColorDrawable(Color.BLUE));
+ CircularIconSet<String> items2 = new CircularIconSet<>(ImmutableList.of("one", "two"),
+ num -> new ColorDrawable(Color.GREEN));
+
+ Equivalence<String> stringEquivalence = new Equivalence<String>() {
+ @Override
+ protected boolean doEquivalent(String a, String b) {
+ return a.equals(b);
+ }
+
+ @Override
+ protected int doHash(String t) {
+ return t.hashCode();
+ }
+ };
+ Equivalence<Integer> integerEquivalence = new Equivalence<Integer>() {
+ @Override
+ protected boolean doEquivalent(Integer a, Integer b) {
+ return a.equals(b);
+ }
+
+ @Override
+ protected int doHash(Integer t) {
+ return t.hashCode();
+ }
+ };
+
+ assertThat(items1.hasSameItemsAs(items2, stringEquivalence)).isFalse();
+ assertThat(items2.hasSameItemsAs(items1, integerEquivalence)).isFalse();
}
@Test