fix: 首次提交
This commit is contained in:
33
SettingsLib/IllustrationPreference/Android.bp
Normal file
33
SettingsLib/IllustrationPreference/Android.bp
Normal file
@@ -0,0 +1,33 @@
|
||||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "frameworks_base_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["frameworks_base_license"],
|
||||
}
|
||||
|
||||
android_library {
|
||||
name: "SettingsLibIllustrationPreference",
|
||||
use_resource_processor: true,
|
||||
defaults: [
|
||||
"SettingsLintDefaults",
|
||||
],
|
||||
|
||||
srcs: ["src/**/*.java"],
|
||||
resource_dirs: ["res"],
|
||||
|
||||
static_libs: [
|
||||
"SettingsLibColor",
|
||||
"androidx.preference_preference",
|
||||
"lottie",
|
||||
],
|
||||
|
||||
sdk_version: "system_current",
|
||||
min_sdk_version: "28",
|
||||
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
"com.android.permission",
|
||||
],
|
||||
}
|
||||
23
SettingsLib/IllustrationPreference/AndroidManifest.xml
Normal file
23
SettingsLib/IllustrationPreference/AndroidManifest.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.settingslib.widget.preference.illustration">
|
||||
|
||||
<uses-sdk android:minSdkVersion="28" />
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/settingslib_protection_color"/>
|
||||
<corners android:radius="28dp"/>
|
||||
<size android:width="@dimen/settingslib_illustration_width"
|
||||
android:height="@dimen/settingslib_illustration_height"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:importantForAccessibility="noHideDescendants"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/illustration_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="@dimen/settingslib_illustration_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/background_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@drawable/protection_background"/>
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/lottie_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:maxWidth="@dimen/settingslib_illustration_width"
|
||||
android:maxHeight="@dimen/settingslib_illustration_height"
|
||||
android:adjustViewBounds="true"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/middleground_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"/>
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<color name="settingslib_protection_color">@android:color/black</color>
|
||||
</resources>
|
||||
22
SettingsLib/IllustrationPreference/res/values/attrs.xml
Normal file
22
SettingsLib/IllustrationPreference/res/values/attrs.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2023 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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<declare-styleable name="IllustrationPreference">
|
||||
<attr name="dynamicColor" format="boolean" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
20
SettingsLib/IllustrationPreference/res/values/colors.xml
Normal file
20
SettingsLib/IllustrationPreference/res/values/colors.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<color name="settingslib_protection_color">@android:color/white</color>
|
||||
</resources>
|
||||
24
SettingsLib/IllustrationPreference/res/values/dimens.xml
Normal file
24
SettingsLib/IllustrationPreference/res/values/dimens.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- Padding of illustration -->
|
||||
<dimen name="settingslib_illustration_padding">16dp</dimen>
|
||||
|
||||
<dimen name="settingslib_illustration_width">412dp</dimen>
|
||||
<dimen name="settingslib_illustration_height">300dp</dimen>
|
||||
</resources>
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.android.settingslib.color.R;
|
||||
|
||||
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;
|
||||
|
||||
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 : 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);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* 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.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.Animatable2;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.RawRes;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.vectordrawable.graphics.drawable.Animatable2Compat;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.airbnb.lottie.LottieDrawable;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import com.android.settingslib.widget.preference.illustration.R;
|
||||
|
||||
/**
|
||||
* IllustrationPreference is a preference that can play lottie format animation
|
||||
*/
|
||||
public class IllustrationPreference extends Preference {
|
||||
|
||||
private static final String TAG = "IllustrationPreference";
|
||||
|
||||
private static final boolean IS_ENABLED_LOTTIE_ADAPTIVE_COLOR = false;
|
||||
private static final int SIZE_UNSPECIFIED = -1;
|
||||
|
||||
private int mMaxHeight = SIZE_UNSPECIFIED;
|
||||
private int mImageResId;
|
||||
private boolean mCacheComposition = true;
|
||||
private boolean mIsAutoScale;
|
||||
private Uri mImageUri;
|
||||
private Drawable mImageDrawable;
|
||||
private View mMiddleGroundView;
|
||||
private OnBindListener mOnBindListener;
|
||||
|
||||
private boolean mLottieDynamicColor;
|
||||
|
||||
/**
|
||||
* Interface to listen in on when {@link #onBindViewHolder(PreferenceViewHolder)} occurs.
|
||||
*/
|
||||
public interface OnBindListener {
|
||||
/**
|
||||
* Called when when {@link #onBindViewHolder(PreferenceViewHolder)} occurs.
|
||||
* @param animationView the animation view for this preference.
|
||||
*/
|
||||
void onBind(LottieAnimationView animationView);
|
||||
}
|
||||
|
||||
private final Animatable2.AnimationCallback mAnimationCallback =
|
||||
new Animatable2.AnimationCallback() {
|
||||
@Override
|
||||
public void onAnimationEnd(Drawable drawable) {
|
||||
((Animatable) drawable).start();
|
||||
}
|
||||
};
|
||||
|
||||
private final Animatable2Compat.AnimationCallback mAnimationCallbackCompat =
|
||||
new Animatable2Compat.AnimationCallback() {
|
||||
@Override
|
||||
public void onAnimationEnd(Drawable drawable) {
|
||||
((Animatable) drawable).start();
|
||||
}
|
||||
};
|
||||
|
||||
public IllustrationPreference(Context context) {
|
||||
super(context);
|
||||
init(context, /* attrs= */ null);
|
||||
}
|
||||
|
||||
public IllustrationPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public IllustrationPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public IllustrationPreference(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
|
||||
final ImageView backgroundView =
|
||||
(ImageView) holder.findViewById(R.id.background_view);
|
||||
final FrameLayout middleGroundLayout =
|
||||
(FrameLayout) holder.findViewById(R.id.middleground_layout);
|
||||
final LottieAnimationView illustrationView =
|
||||
(LottieAnimationView) holder.findViewById(R.id.lottie_view);
|
||||
|
||||
// To solve the problem of non-compliant illustrations, we set the frame height
|
||||
// to 300dp and set the length of the short side of the screen to
|
||||
// the width of the frame.
|
||||
final int screenWidth = getContext().getResources().getDisplayMetrics().widthPixels;
|
||||
final int screenHeight = getContext().getResources().getDisplayMetrics().heightPixels;
|
||||
final FrameLayout illustrationFrame = (FrameLayout) holder.findViewById(
|
||||
R.id.illustration_frame);
|
||||
final LayoutParams lp = (LayoutParams) illustrationFrame.getLayoutParams();
|
||||
lp.width = screenWidth < screenHeight ? screenWidth : screenHeight;
|
||||
illustrationFrame.setLayoutParams(lp);
|
||||
|
||||
illustrationView.setCacheComposition(mCacheComposition);
|
||||
handleImageWithAnimation(illustrationView);
|
||||
handleImageFrameMaxHeight(backgroundView, illustrationView);
|
||||
|
||||
if (mIsAutoScale) {
|
||||
illustrationView.setScaleType(mIsAutoScale
|
||||
? ImageView.ScaleType.CENTER_CROP
|
||||
: ImageView.ScaleType.CENTER_INSIDE);
|
||||
}
|
||||
|
||||
handleMiddleGroundView(middleGroundLayout);
|
||||
|
||||
if (IS_ENABLED_LOTTIE_ADAPTIVE_COLOR) {
|
||||
ColorUtils.applyDynamicColors(getContext(), illustrationView);
|
||||
}
|
||||
|
||||
if (mLottieDynamicColor) {
|
||||
LottieColorUtils.applyDynamicColors(getContext(), illustrationView);
|
||||
}
|
||||
|
||||
if (mOnBindListener != null) {
|
||||
mOnBindListener.onBind(illustrationView);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener to be notified when the views are binded.
|
||||
*/
|
||||
public void setOnBindListener(OnBindListener listener) {
|
||||
mOnBindListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the middle ground view to preference. The user
|
||||
* can overlay a view on top of the animation.
|
||||
*/
|
||||
public void setMiddleGroundView(View view) {
|
||||
if (view != mMiddleGroundView) {
|
||||
mMiddleGroundView = view;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the middle ground view of preference.
|
||||
*/
|
||||
public void removeMiddleGroundView() {
|
||||
mMiddleGroundView = null;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the auto scale feature of animation view.
|
||||
*/
|
||||
public void enableAnimationAutoScale(boolean enable) {
|
||||
if (enable != mIsAutoScale) {
|
||||
mIsAutoScale = enable;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lottie illustration resource id.
|
||||
*/
|
||||
public void setLottieAnimationResId(int resId) {
|
||||
if (resId != mImageResId) {
|
||||
resetImageResourceCache();
|
||||
mImageResId = resId;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lottie illustration resource id.
|
||||
*/
|
||||
public int getLottieAnimationResId() {
|
||||
return mImageResId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the image drawable to display image in {@link LottieAnimationView}.
|
||||
*
|
||||
* @param imageDrawable the drawable of an image
|
||||
*/
|
||||
public void setImageDrawable(Drawable imageDrawable) {
|
||||
if (imageDrawable != mImageDrawable) {
|
||||
resetImageResourceCache();
|
||||
mImageDrawable = imageDrawable;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the image drawable from display image in {@link LottieAnimationView}.
|
||||
*
|
||||
* @return the drawable of an image
|
||||
*/
|
||||
public Drawable getImageDrawable() {
|
||||
return mImageDrawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the image uri to display image in {@link LottieAnimationView}.
|
||||
*
|
||||
* @param imageUri the Uri of an image
|
||||
*/
|
||||
public void setImageUri(Uri imageUri) {
|
||||
if (imageUri != mImageUri) {
|
||||
resetImageResourceCache();
|
||||
mImageUri = imageUri;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the image uri from display image in {@link LottieAnimationView}.
|
||||
*
|
||||
* @return the Uri of an image
|
||||
*/
|
||||
public Uri getImageUri() {
|
||||
return mImageUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum height of the views, still use the specific one if the maximum height was
|
||||
* larger than the specific height from XML.
|
||||
*
|
||||
* @param maxHeight the maximum height of the frame views in terms of pixels.
|
||||
*/
|
||||
public void setMaxHeight(int maxHeight) {
|
||||
if (maxHeight != mMaxHeight) {
|
||||
mMaxHeight = maxHeight;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lottie illustration apply dynamic color.
|
||||
*/
|
||||
public void applyDynamicColor() {
|
||||
mLottieDynamicColor = true;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the lottie illustration apply dynamic color or not.
|
||||
*/
|
||||
public boolean isApplyDynamicColor() {
|
||||
return mLottieDynamicColor;
|
||||
}
|
||||
|
||||
private void resetImageResourceCache() {
|
||||
mImageDrawable = null;
|
||||
mImageUri = null;
|
||||
mImageResId = 0;
|
||||
}
|
||||
|
||||
private void handleMiddleGroundView(ViewGroup middleGroundLayout) {
|
||||
middleGroundLayout.removeAllViews();
|
||||
|
||||
if (mMiddleGroundView != null) {
|
||||
middleGroundLayout.addView(mMiddleGroundView);
|
||||
middleGroundLayout.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
middleGroundLayout.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleImageWithAnimation(LottieAnimationView illustrationView) {
|
||||
if (mImageDrawable != null) {
|
||||
resetAnimations(illustrationView);
|
||||
illustrationView.setImageDrawable(mImageDrawable);
|
||||
final Drawable drawable = illustrationView.getDrawable();
|
||||
if (drawable != null) {
|
||||
startAnimation(drawable);
|
||||
}
|
||||
}
|
||||
|
||||
if (mImageUri != null) {
|
||||
resetAnimations(illustrationView);
|
||||
illustrationView.setImageURI(mImageUri);
|
||||
final Drawable drawable = illustrationView.getDrawable();
|
||||
if (drawable != null) {
|
||||
startAnimation(drawable);
|
||||
} else {
|
||||
// The lottie image from the raw folder also returns null because the ImageView
|
||||
// couldn't handle it now.
|
||||
startLottieAnimationWith(illustrationView, mImageUri);
|
||||
}
|
||||
}
|
||||
|
||||
if (mImageResId > 0) {
|
||||
resetAnimations(illustrationView);
|
||||
illustrationView.setImageResource(mImageResId);
|
||||
final Drawable drawable = illustrationView.getDrawable();
|
||||
if (drawable != null) {
|
||||
startAnimation(drawable);
|
||||
} else {
|
||||
// The lottie image from the raw folder also returns null because the ImageView
|
||||
// couldn't handle it now.
|
||||
startLottieAnimationWith(illustrationView, mImageResId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleImageFrameMaxHeight(ImageView backgroundView, ImageView illustrationView) {
|
||||
if (mMaxHeight == SIZE_UNSPECIFIED) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Resources res = backgroundView.getResources();
|
||||
final int frameWidth = res.getDimensionPixelSize(R.dimen.settingslib_illustration_width);
|
||||
final int frameHeight = res.getDimensionPixelSize(R.dimen.settingslib_illustration_height);
|
||||
final int restrictedMaxHeight = Math.min(mMaxHeight, frameHeight);
|
||||
backgroundView.setMaxHeight(restrictedMaxHeight);
|
||||
illustrationView.setMaxHeight(restrictedMaxHeight);
|
||||
|
||||
// Ensures the illustration view size is smaller than or equal to the background view size.
|
||||
final float aspectRatio = (float) frameWidth / frameHeight;
|
||||
illustrationView.setMaxWidth((int) (restrictedMaxHeight * aspectRatio));
|
||||
}
|
||||
|
||||
private void startAnimation(Drawable drawable) {
|
||||
if (!(drawable instanceof Animatable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (drawable instanceof Animatable2) {
|
||||
((Animatable2) drawable).registerAnimationCallback(mAnimationCallback);
|
||||
} else if (drawable instanceof Animatable2Compat) {
|
||||
((Animatable2Compat) drawable).registerAnimationCallback(mAnimationCallbackCompat);
|
||||
} else if (drawable instanceof AnimationDrawable) {
|
||||
((AnimationDrawable) drawable).setOneShot(false);
|
||||
}
|
||||
|
||||
((Animatable) drawable).start();
|
||||
}
|
||||
|
||||
private static void startLottieAnimationWith(LottieAnimationView illustrationView,
|
||||
Uri imageUri) {
|
||||
final InputStream inputStream =
|
||||
getInputStreamFromUri(illustrationView.getContext(), imageUri);
|
||||
illustrationView.setFailureListener(
|
||||
result -> Log.w(TAG, "Invalid illustration image uri: " + imageUri, result));
|
||||
illustrationView.setAnimation(inputStream, /* cacheKey= */ null);
|
||||
illustrationView.setRepeatCount(LottieDrawable.INFINITE);
|
||||
illustrationView.playAnimation();
|
||||
}
|
||||
|
||||
private static void startLottieAnimationWith(LottieAnimationView illustrationView,
|
||||
@RawRes int rawRes) {
|
||||
illustrationView.setFailureListener(
|
||||
result -> Log.w(TAG, "Invalid illustration resource id: " + rawRes, result));
|
||||
illustrationView.setAnimation(rawRes);
|
||||
illustrationView.setRepeatCount(LottieDrawable.INFINITE);
|
||||
illustrationView.playAnimation();
|
||||
}
|
||||
|
||||
private static void resetAnimations(LottieAnimationView illustrationView) {
|
||||
resetAnimation(illustrationView.getDrawable());
|
||||
|
||||
illustrationView.cancelAnimation();
|
||||
}
|
||||
|
||||
private static void resetAnimation(Drawable drawable) {
|
||||
if (!(drawable instanceof Animatable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (drawable instanceof Animatable2) {
|
||||
((Animatable2) drawable).clearAnimationCallbacks();
|
||||
} else if (drawable instanceof Animatable2Compat) {
|
||||
((Animatable2Compat) drawable).clearAnimationCallbacks();
|
||||
}
|
||||
|
||||
((Animatable) drawable).stop();
|
||||
}
|
||||
|
||||
private static InputStream getInputStreamFromUri(Context context, Uri uri) {
|
||||
try {
|
||||
return context.getContentResolver().openInputStream(uri);
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.w(TAG, "Cannot find content uri: " + uri, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
setLayoutResource(R.layout.illustration_preference);
|
||||
|
||||
mIsAutoScale = false;
|
||||
if (attrs != null) {
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
com.airbnb.lottie.R.styleable.LottieAnimationView, 0 /*defStyleAttr*/, 0 /*defStyleRes*/);
|
||||
mImageResId = a.getResourceId(com.airbnb.lottie.R.styleable.LottieAnimationView_lottie_rawRes, 0);
|
||||
mCacheComposition = a.getBoolean(
|
||||
com.airbnb.lottie.R.styleable.LottieAnimationView_lottie_cacheComposition, true);
|
||||
|
||||
a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.IllustrationPreference, 0 /*defStyleAttr*/, 0 /*defStyleRes*/);
|
||||
mLottieDynamicColor = a.getBoolean(R.styleable.IllustrationPreference_dynamicColor,
|
||||
false);
|
||||
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
|
||||
import com.android.settingslib.color.R;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.airbnb.lottie.LottieProperty;
|
||||
import com.airbnb.lottie.model.KeyPath;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Util class which dynamically changes the color of tags in a lottie json file between Dark Theme
|
||||
* (DT) and Light Theme (LT). This class assumes the json file is for Dark Theme.
|
||||
*/
|
||||
public class LottieColorUtils {
|
||||
private static final Map<String, Integer> DARK_TO_LIGHT_THEME_COLOR_MAP;
|
||||
|
||||
static {
|
||||
HashMap<String, Integer> map = new HashMap<>();
|
||||
map.put(
|
||||
".grey600",
|
||||
R.color.settingslib_color_grey400);
|
||||
map.put(
|
||||
".grey800",
|
||||
R.color.settingslib_color_grey300);
|
||||
map.put(
|
||||
".grey900",
|
||||
R.color.settingslib_color_grey50);
|
||||
map.put(
|
||||
".red400",
|
||||
R.color.settingslib_color_red600);
|
||||
map.put(
|
||||
".black",
|
||||
android.R.color.white);
|
||||
map.put(
|
||||
".blue400",
|
||||
R.color.settingslib_color_blue600);
|
||||
map.put(
|
||||
".green400",
|
||||
R.color.settingslib_color_green600);
|
||||
map.put(
|
||||
".green200",
|
||||
R.color.settingslib_color_green500);
|
||||
map.put(
|
||||
".red200",
|
||||
R.color.settingslib_color_red500);
|
||||
DARK_TO_LIGHT_THEME_COLOR_MAP = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
private LottieColorUtils() {
|
||||
}
|
||||
|
||||
private static boolean isDarkMode(Context context) {
|
||||
return (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
|
||||
== Configuration.UI_MODE_NIGHT_YES;
|
||||
}
|
||||
|
||||
/** Applies dynamic colors based on DT vs. LT. The LottieAnimationView should be Dark Theme. */
|
||||
public static void applyDynamicColors(Context context,
|
||||
LottieAnimationView lottieAnimationView) {
|
||||
// Assume the default for the lottie is dark mode
|
||||
if (isDarkMode(context)) {
|
||||
return;
|
||||
}
|
||||
for (String key : DARK_TO_LIGHT_THEME_COLOR_MAP.keySet()) {
|
||||
final int color = context.getColor(DARK_TO_LIGHT_THEME_COLOR_MAP.get(key));
|
||||
lottieAnimationView.addValueCallback(
|
||||
new KeyPath("**", key, "**"),
|
||||
LottieProperty.COLOR_FILTER,
|
||||
frameInfo -> new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user