diff options
| author | 2021-05-25 20:09:05 +0800 | |
|---|---|---|
| committer | 2021-06-03 11:25:53 +0800 | |
| commit | ee50d90e9d41c877bed65fdfd39240c8693f57b4 (patch) | |
| tree | 739b9e92c3496e6232877cf1a91960359da3f268 | |
| parent | 6356587fb340d66e361cbc665a80d8b5d03069b4 (diff) | |
Improve the features of IllustrationPreference.
- Support the dynamic color.
The colors of the illustration's labels can be changed.
We create a mapping table of colors and labels.
According to this mapping table, preference can
apply the corresponding colors to the illustration.
- Support the middle ground view.
User can overlay a view on top of the illustration.
- Support the auto scale of illustration.
- Update the layout to prevent the animation cropping.
Fix: 189199177
Test: rebotest and see the UI.
Change-Id: Ib02cbc5bb99ab8014d7ee7ed630a6721968a49ab
8 files changed, 295 insertions, 15 deletions
diff --git a/packages/SettingsLib/IllustrationPreference/Android.bp b/packages/SettingsLib/IllustrationPreference/Android.bp index f8dd3849c2a1..5904589ed22e 100644 --- a/packages/SettingsLib/IllustrationPreference/Android.bp +++ b/packages/SettingsLib/IllustrationPreference/Android.bp @@ -19,5 +19,5 @@ android_library { ], sdk_version: "system_current", - min_sdk_version: "21", + min_sdk_version: "28", } diff --git a/packages/SettingsLib/IllustrationPreference/res/drawable/protection_background.xml b/packages/SettingsLib/IllustrationPreference/res/drawable/protection_background.xml index dd2fa5e0f214..0734aca2ab90 100644 --- a/packages/SettingsLib/IllustrationPreference/res/drawable/protection_background.xml +++ b/packages/SettingsLib/IllustrationPreference/res/drawable/protection_background.xml @@ -16,11 +16,7 @@ --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item - android:top="@dimen/settingslib_illustration_padding" - android:left="@dimen/settingslib_illustration_padding" - android:right="@dimen/settingslib_illustration_padding" - android:bottom="@dimen/settingslib_illustration_padding"> + <item> <shape android:shape="rectangle"> <solid android:color="@color/settingslib_protection_color"/> <corners android:radius="28dp"/> diff --git a/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml b/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml index 7d65aaea2512..54731f51248b 100644 --- a/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml +++ b/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml @@ -23,14 +23,33 @@ android:gravity="center" android:orientation="horizontal"> - <com.airbnb.lottie.LottieAnimationView - android:id="@+id/lottie_view" + <LinearLayout + android:layout_width="match_parent" + android:layout_height="300dp" + android:layout_gravity="center" + android:gravity="center_vertical" + android:padding="@dimen/settingslib_illustration_padding" + android:orientation="vertical"> + <com.airbnb.lottie.LottieAnimationView + android:id="@+id/lottie_view" + android:adjustViewBounds="true" + android:maxWidth="412dp" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center" + android:clipToOutline="true" + android:background="@drawable/protection_background" + android:importantForAccessibility="no"/> + </LinearLayout> + + <FrameLayout + android:id="@+id/middleground_layout" android:layout_width="412dp" android:layout_height="300dp" + android:padding="@dimen/settingslib_illustration_padding" + android:background="@android:color/transparent" android:layout_gravity="center" - android:clipToOutline="true" - android:background="@drawable/protection_background" - android:importantForAccessibility="no"/> + android:visibility="gone"/> <ImageView android:id="@+id/video_play_button" diff --git a/packages/SettingsLib/IllustrationPreference/res/values/colors.xml b/packages/SettingsLib/IllustrationPreference/res/values/colors.xml index e53a43e7953e..ead5174f9ee2 100644 --- a/packages/SettingsLib/IllustrationPreference/res/values/colors.xml +++ b/packages/SettingsLib/IllustrationPreference/res/values/colors.xml @@ -17,4 +17,46 @@ <resources> <color name="settingslib_protection_color">@android:color/white</color> + + <!-- Dynamic colors--> + <color name="settingslib_color_blue600">#1a73e8</color> + <color name="settingslib_color_blue400">#669df6</color> + <color name="settingslib_color_blue300">#8ab4f8</color> + <color name="settingslib_color_blue100">#d2e3fc</color> + <color name="settingslib_color_blue50">#e8f0fe</color> + <color name="settingslib_color_green600">#1e8e3e</color> + <color name="settingslib_color_green400">#5bb974</color> + <color name="settingslib_color_green100">#ceead6</color> + <color name="settingslib_color_green50">#e6f4ea</color> + <color name="settingslib_color_red600">#d93025</color> + <color name="settingslib_color_red400">#ee675c</color> + <color name="settingslib_color_red100">#fad2cf</color> + <color name="settingslib_color_red50">#fce8e6</color> + <color name="settingslib_color_yellow600">#f9ab00</color> + <color name="settingslib_color_yellow400">#fcc934</color> + <color name="settingslib_color_yellow100">#feefc3</color> + <color name="settingslib_color_yellow50">#fef7e0</color> + <color name="settingslib_color_grey900">#202124</color> + <color name="settingslib_color_grey800">#3c4043</color> + <color name="settingslib_color_grey700">#5f6368</color> + <color name="settingslib_color_grey600">#80868b</color> + <color name="settingslib_color_grey400">#bdc1c6</color> + <color name="settingslib_color_grey300">#dadce0</color> + <color name="settingslib_color_grey200">#e8eaed</color> + <color name="settingslib_color_orange600">#e8710a</color> + <color name="settingslib_color_orange400">#fa903e</color> + <color name="settingslib_color_orange300">#fcad70</color> + <color name="settingslib_color_orange100">#fedfc8</color> + <color name="settingslib_color_pink600">#e52592</color> + <color name="settingslib_color_pink400">#ff63b8</color> + <color name="settingslib_color_pink300">#ff8bcb</color> + <color name="settingslib_color_pink100">#fdcfe8</color> + <color name="settingslib_color_purple600">#9334e6</color> + <color name="settingslib_color_purple400">#af5cf7</color> + <color name="settingslib_color_purple300">#c58af9</color> + <color name="settingslib_color_purple100">#e9d2fd</color> + <color name="settingslib_color_cyan600">#12b5c8</color> + <color name="settingslib_color_cyan400">#4ecde6</color> + <color name="settingslib_color_cyan300">#78d9ec</color> + <color name="settingslib_color_cyan100">#cbf0f8</color> </resources> diff --git a/packages/SettingsLib/IllustrationPreference/res/values/dimens.xml b/packages/SettingsLib/IllustrationPreference/res/values/dimens.xml index 79562b962ad1..5e540d3740f9 100644 --- a/packages/SettingsLib/IllustrationPreference/res/values/dimens.xml +++ b/packages/SettingsLib/IllustrationPreference/res/values/dimens.xml @@ -17,5 +17,5 @@ <resources> <!-- Padding of illustration --> - <dimen name="settingslib_illustration_padding">16dp</dimen> + <dimen name="settingslib_illustration_padding">12dp</dimen> </resources> diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/ColorUtils.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/ColorUtils.java new file mode 100644 index 000000000000..cd2ddebe6367 --- /dev/null +++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/ColorUtils.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2021 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.settingslib.widget; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.ColorFilter; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.util.Pair; + +import com.airbnb.lottie.LottieAnimationView; +import com.airbnb.lottie.LottieProperty; +import com.airbnb.lottie.model.KeyPath; +import com.airbnb.lottie.value.LottieFrameInfo; +import com.airbnb.lottie.value.SimpleLottieValueCallback; + +import java.util.HashMap; + +/** + * ColorUtils is a util class which help the lottie illustration + * changes the color of tags in the json file. + */ + +public class ColorUtils { + + private static HashMap<String, Integer> sSysColors; + static { + sSysColors = new HashMap<>(); + sSysColors.put(".colorAccent", android.R.attr.colorAccent); + sSysColors.put(".colorPrimary", android.R.attr.colorPrimary); + sSysColors.put(".colorPrimaryDark", android.R.attr.colorPrimaryDark); + sSysColors.put(".colorSecondary", android.R.attr.colorSecondary); + } + + private static HashMap<String, Pair<Integer, Integer>> sFixedColors; + static { + sFixedColors = new HashMap<>(); + sFixedColors.put(".blue600", new Pair<Integer, Integer>( + R.color.settingslib_color_blue600, R.color.settingslib_color_blue400)); + sFixedColors.put(".green600", new Pair<Integer, Integer>( + R.color.settingslib_color_green600, R.color.settingslib_color_green400)); + sFixedColors.put(".red600", new Pair<Integer, Integer>( + R.color.settingslib_color_red600, R.color.settingslib_color_red400)); + sFixedColors.put(".yellow600", new Pair<Integer, Integer>( + R.color.settingslib_color_yellow600, R.color.settingslib_color_yellow400)); + sFixedColors.put(".blue400", new Pair<Integer, Integer>( + R.color.settingslib_color_blue400, R.color.settingslib_color_blue100)); + sFixedColors.put(".green400", new Pair<Integer, Integer>( + R.color.settingslib_color_green400, R.color.settingslib_color_green100)); + sFixedColors.put(".red400", new Pair<Integer, Integer>( + R.color.settingslib_color_red400, R.color.settingslib_color_red100)); + sFixedColors.put(".yellow400", new Pair<Integer, Integer>( + R.color.settingslib_color_yellow400, R.color.settingslib_color_yellow100)); + sFixedColors.put(".blue300", new Pair<Integer, Integer>( + R.color.settingslib_color_blue300, R.color.settingslib_color_blue50)); + sFixedColors.put(".blue50", new Pair<Integer, Integer>( + R.color.settingslib_color_blue50, R.color.settingslib_color_grey900)); + sFixedColors.put(".green50", new Pair<Integer, Integer>( + R.color.settingslib_color_green50, R.color.settingslib_color_grey900)); + sFixedColors.put(".red50", new Pair<Integer, Integer>( + R.color.settingslib_color_red50, R.color.settingslib_color_grey900)); + sFixedColors.put(".yellow50", new Pair<Integer, Integer>( + R.color.settingslib_color_yellow50, R.color.settingslib_color_grey900)); + // Secondary colors + sFixedColors.put(".orange600", new Pair<Integer, Integer>( + R.color.settingslib_color_orange600, R.color.settingslib_color_orange300)); + sFixedColors.put(".pink600", new Pair<Integer, Integer>( + R.color.settingslib_color_pink600, R.color.settingslib_color_pink300)); + sFixedColors.put(".purple600", new Pair<Integer, Integer>( + R.color.settingslib_color_purple600, R.color.settingslib_color_purple300)); + sFixedColors.put(".cyan600", new Pair<Integer, Integer>( + R.color.settingslib_color_cyan600, R.color.settingslib_color_cyan300)); + sFixedColors.put(".orange400", new Pair<Integer, Integer>( + R.color.settingslib_color_orange400, R.color.settingslib_color_orange100)); + sFixedColors.put(".pink400", new Pair<Integer, Integer>( + R.color.settingslib_color_pink400, R.color.settingslib_color_pink100)); + sFixedColors.put(".purple400", new Pair<Integer, Integer>( + R.color.settingslib_color_purple400, R.color.settingslib_color_purple100)); + sFixedColors.put(".cyan400", new Pair<Integer, Integer>( + R.color.settingslib_color_cyan400, R.color.settingslib_color_cyan100)); + sFixedColors.put(".gery400", new Pair<Integer, Integer>( + R.color.settingslib_color_grey400, R.color.settingslib_color_grey700)); + sFixedColors.put(".gery300", new Pair<Integer, Integer>( + R.color.settingslib_color_grey300, R.color.settingslib_color_grey600)); + sFixedColors.put(".gery200", new Pair<Integer, Integer>( + R.color.settingslib_color_grey200, R.color.settingslib_color_grey800)); + } + + private static boolean isDarkMode(Context context) { + return (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) + == Configuration.UI_MODE_NIGHT_YES; + } + + /** + * Apply the color of tags to the animation. + */ + public static void applyDynamicColors(Context context, LottieAnimationView animationView) { + for (String key : sSysColors.keySet()) { + final int color = sSysColors.get(key); + animationView.addValueCallback( + new KeyPath("**", key, "**"), + LottieProperty.COLOR_FILTER, + new SimpleLottieValueCallback<ColorFilter>() { + @Override + public ColorFilter getValue(LottieFrameInfo<ColorFilter> frameInfo) { + return new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN); + } + } + ); + } + for (String key : sFixedColors.keySet()) { + final Pair<Integer, Integer> fixedColorPair = sFixedColors.get(key); + final int color = isDarkMode(context) ? fixedColorPair.second : fixedColorPair.first; + animationView.addValueCallback( + new KeyPath("**", key, "**"), + LottieProperty.COLOR_FILTER, + new SimpleLottieValueCallback<ColorFilter>() { + @Override + public ColorFilter getValue(LottieFrameInfo<ColorFilter> frameInfo) { + return new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN); + } + } + ); + } + } +} diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java index 90b8a3210a42..7b2a0af269a6 100644 --- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java +++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java @@ -23,6 +23,7 @@ import android.os.Parcelable; import android.util.AttributeSet; import android.util.Log; import android.view.View; +import android.widget.FrameLayout; import android.widget.ImageView; import androidx.annotation.VisibleForTesting; @@ -38,10 +39,14 @@ import com.airbnb.lottie.LottieAnimationView; public class IllustrationPreference extends Preference implements OnPreferenceClickListener { static final String TAG = "IllustrationPreference"; + private int mAnimationId; private boolean mIsAnimating; + private boolean mIsAutoScale; private ImageView mPlayButton; private LottieAnimationView mIllustrationView; + private View mMiddleGroundView; + private FrameLayout mMiddleGroundLayout; public IllustrationPreference(Context context, AttributeSet attrs) { super(context, attrs); @@ -66,13 +71,20 @@ public class IllustrationPreference extends Preference implements OnPreferenceCl Log.w(TAG, "Invalid illustration resource id."); return; } + mMiddleGroundLayout = (FrameLayout) holder.findViewById(R.id.middleground_layout); mPlayButton = (ImageView) holder.findViewById(R.id.video_play_button); mIllustrationView = (LottieAnimationView) holder.findViewById(R.id.lottie_view); mIllustrationView.setAnimation(mAnimationId); mIllustrationView.loop(true); + ColorUtils.applyDynamicColors(getContext(), mIllustrationView); mIllustrationView.playAnimation(); updateAnimationStatus(mIsAnimating); - setOnPreferenceClickListener(this); + if (mIsAutoScale) { + enableAnimationAutoScale(mIsAutoScale); + } + if (mMiddleGroundView != null) { + enableMiddleGroundView(); + } } @Override @@ -102,16 +114,59 @@ public class IllustrationPreference extends Preference implements OnPreferenceCl return mIllustrationView.isAnimating(); } + /** + * Set the middle ground view to preference. The user + * can overlay a view on top of the animation. + */ + public void setMiddleGroundView(View view) { + mMiddleGroundView = view; + if (mMiddleGroundLayout == null) { + return; + } + enableMiddleGroundView(); + } + + /** + * Remove the middle ground view of preference. + */ + public void removeMiddleGroundView() { + if (mMiddleGroundLayout == null) { + return; + } + mMiddleGroundLayout.removeAllViews(); + mMiddleGroundLayout.setVisibility(View.GONE); + } + + /** + * Enables the auto scale feature of animation view. + */ + public void enableAnimationAutoScale(boolean enable) { + mIsAutoScale = enable; + if (mIllustrationView == null) { + return; + } + mIllustrationView.setScaleType( + mIsAutoScale ? ImageView.ScaleType.CENTER_CROP : ImageView.ScaleType.CENTER_INSIDE); + } + + private void enableMiddleGroundView() { + mMiddleGroundLayout.removeAllViews(); + mMiddleGroundLayout.addView(mMiddleGroundView); + mMiddleGroundLayout.setVisibility(View.VISIBLE); + } + private void init(Context context, AttributeSet attrs) { setLayoutResource(R.layout.illustration_preference); mIsAnimating = true; + mIsAutoScale = false; if (attrs != null) { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LottieAnimationView, 0 /*defStyleAttr*/, 0 /*defStyleRes*/); mAnimationId = a.getResourceId(R.styleable.LottieAnimationView_lottie_rawRes, 0); a.recycle(); } + setOnPreferenceClickListener(this); } private void updateAnimationStatus(boolean playAnimation) { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java index 4a14403b7ea3..f197cbb2ac70 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java @@ -22,6 +22,9 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; import com.airbnb.lottie.LottieAnimationView; @@ -41,14 +44,15 @@ public class IllustrationPreferenceTest { @Mock LottieAnimationView mAnimationView; + private Context mContext; private IllustrationPreference mPreference; @Before public void setUp() { MockitoAnnotations.initMocks(this); - final Context context = RuntimeEnvironment.application; + mContext = RuntimeEnvironment.application; final AttributeSet attributeSet = Robolectric.buildAttributeSet().build(); - mPreference = new IllustrationPreference(context, attributeSet); + mPreference = new IllustrationPreference(mContext, attributeSet); ReflectionHelpers.setField(mPreference, "mIllustrationView", mAnimationView); } @@ -65,4 +69,27 @@ public class IllustrationPreferenceTest { assertThat(mPreference.isAnimating()).isTrue(); } + + @Test + public void setMiddleGroundView_middleGroundView_shouldVisible() { + final View view = new View(mContext); + final FrameLayout layout = new FrameLayout(mContext); + layout.setVisibility(View.GONE); + ReflectionHelpers.setField(mPreference, "mMiddleGroundView", view); + ReflectionHelpers.setField(mPreference, "mMiddleGroundLayout", layout); + + mPreference.setMiddleGroundView(view); + + assertThat(layout.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void enableAnimationAutoScale_shouldChangeScaleType() { + final LottieAnimationView animationView = new LottieAnimationView(mContext); + ReflectionHelpers.setField(mPreference, "mIllustrationView", animationView); + + mPreference.enableAnimationAutoScale(true); + + assertThat(animationView.getScaleType()).isEqualTo(ImageView.ScaleType.CENTER_CROP); + } } |