From 282cf8a4035d3b234b8af020e940380b17d143e7 Mon Sep 17 00:00:00 2001 From: Neko Qiqi Date: Wed, 13 Mar 2024 00:08:00 +0800 Subject: [PATCH] feat: home - icons - app animated background blu some of them from HyperHelper by HowieHChen --- .../module/app/Home/Phone/HomeT.java | 6 +- .../module/hook/home/title/AppBlurAnim.kt | 333 ++++++++++++++++++ .../ui/fragment/home/HomeTitleSettings.java | 7 + .../hyperceiler/utils/api/HyperHelperApis.kt | 11 + .../hyperceiler/utils/blur/MiBlurView.kt | 190 ++++++++++ app/src/main/res/values-zh-rCN/strings.xml | 8 + app/src/main/res/values/strings.xml | 8 + app/src/main/res/xml/home_title.xml | 80 +++++ 8 files changed, 641 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/sevtinge/hyperceiler/module/hook/home/title/AppBlurAnim.kt create mode 100644 app/src/main/java/com/sevtinge/hyperceiler/utils/api/HyperHelperApis.kt create mode 100644 app/src/main/java/com/sevtinge/hyperceiler/utils/blur/MiBlurView.kt diff --git a/app/src/main/java/com/sevtinge/hyperceiler/module/app/Home/Phone/HomeT.java b/app/src/main/java/com/sevtinge/hyperceiler/module/app/Home/Phone/HomeT.java index cccd79cf51..9c0c617c77 100644 --- a/app/src/main/java/com/sevtinge/hyperceiler/module/app/Home/Phone/HomeT.java +++ b/app/src/main/java/com/sevtinge/hyperceiler/module/app/Home/Phone/HomeT.java @@ -110,6 +110,7 @@ import com.sevtinge.hyperceiler.module.hook.home.recent.TaskViewVertical; import com.sevtinge.hyperceiler.module.hook.home.recent.UnlockPin; import com.sevtinge.hyperceiler.module.hook.home.title.AnimParamCustom; +import com.sevtinge.hyperceiler.module.hook.home.title.AppBlurAnim; import com.sevtinge.hyperceiler.module.hook.home.title.BigIconCorner; import com.sevtinge.hyperceiler.module.hook.home.title.DisableHideFile; import com.sevtinge.hyperceiler.module.hook.home.title.DisableHideTheme; @@ -202,7 +203,7 @@ public void handleLoadPackage() { initHook(new PinyinArrangement(), mPrefsMap.getBoolean("home_drawer_pinyin")); // 最近任务 - initHook(BlurLevel.INSTANCE, mPrefsMap.getStringAsInt("home_recent_blur_level", 6) != 6); + initHook(BlurLevel.INSTANCE, mPrefsMap.getStringAsInt("home_recent_blur_level", 6) != 6 && !mPrefsMap.getBoolean("home_title_app_blur_enable")); initHook(DisableRecentViewWallpaperDarken.INSTANCE, mPrefsMap.getBoolean("home_recent_disable_wallpaper_dimming")); initHook(HideStatusBarWhenEnterRecent.INSTANCE, mPrefsMap.getBoolean("home_recent_hide_status_bar_in_task_view")); initHook(RemoveCardAnim.INSTANCE, mPrefsMap.getBoolean("home_recent_modify_animation")); @@ -232,6 +233,7 @@ public void handleLoadPackage() { initHook(DisableHideGoogle.INSTANCE, mPrefsMap.getBoolean("home_title_disable_hide_google")); initHook(new FakeNonDefaultIcon(), mPrefsMap.getBoolean("fake_non_default_icon")); initHook(new AnimParamCustom(), mPrefsMap.getBoolean("home_title_custom_anim_param_main")); + initHook(AppBlurAnim.INSTANCE, mPrefsMap.getBoolean("home_title_app_blur_enable")); // initHook(new IconScaleHook()/*, mPrefsMap.getInt("home_title_icon_scale", 100) != 100*/); // 标题 @@ -285,7 +287,7 @@ public void handleLoadPackage() { // 实验性功能 initHook(BlurWhenShowShortcutMenu.INSTANCE, mPrefsMap.getBoolean("home_other_shortcut_background_blur")); - initHook(FolderBlur.INSTANCE, mPrefsMap.getBoolean("home_folder_blur")); + initHook(FolderBlur.INSTANCE, mPrefsMap.getBoolean("home_folder_blur") && !mPrefsMap.getBoolean("home_title_app_blur_enable")); initHook(new FoldDock(), mPrefsMap.getBoolean("home_other_fold_dock")); // initHook(new AllAppsBlur); // ?? initHook(new FixAnimation(), mPrefsMap.getBoolean("home_title_fix_animation")); diff --git a/app/src/main/java/com/sevtinge/hyperceiler/module/hook/home/title/AppBlurAnim.kt b/app/src/main/java/com/sevtinge/hyperceiler/module/hook/home/title/AppBlurAnim.kt new file mode 100644 index 0000000000..230ecd5bd6 --- /dev/null +++ b/app/src/main/java/com/sevtinge/hyperceiler/module/hook/home/title/AppBlurAnim.kt @@ -0,0 +1,333 @@ +package com.sevtinge.hyperceiler.module.hook.home.title + +import android.app.* +import android.view.* +import android.view.animation.* +import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass +import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder +import com.sevtinge.hyperceiler.module.base.* +import com.sevtinge.hyperceiler.utils.* +import com.sevtinge.hyperceiler.utils.blur.* +import com.sevtinge.hyperceiler.utils.log.* +import de.robv.android.xposed.* +import java.util.concurrent.* + +object AppBlurAnim : BaseHook() { + private val appsBlurRadius by lazy { + mPrefsMap.getInt("home_title_app_blur_radius", 100) + } + private val appsDimAlpha by lazy { + mPrefsMap.getInt("home_title_app_dim_alpha", 50) + } + private val wallBlurRadius by lazy { + mPrefsMap.getInt("home_title_app_blur_radius", 100) + } + private val wallDimAlpha by lazy { + mPrefsMap.getInt("home_title_app_dim_alpha", 50) + } + private val minusBlurRadius by lazy { + mPrefsMap.getInt("home_title_app_blur_radius", 100) + } + private val minusDimAlpha by lazy { + mPrefsMap.getInt("home_title_app_dim_alpha", 50) + } + private val minusOverlapMode by lazy { + true + } + private val minusShowLaunch by lazy { + true + } + private val fixSmallWindowAnim by lazy { + mPrefsMap.getBoolean("home_title_fix_small_window") + } + private var isStartingApp: Boolean = false + + private val blurUtil by lazy { + loadClass("com.miui.home.launcher.common.BlurUtilities") + } + private val blur by lazy { + loadClass("com.miui.home.launcher.common.BlurUtils") + } + private val mainThreadExecutor by lazy { + loadClass("com.miui.home.recents.TouchInteractionService") + .getStaticObjectFieldOrNull("MAIN_THREAD_EXECUTOR") as Executor + } + private val overviewState by lazy { + loadClass("com.miui.home.launcher.LauncherState") + .getStaticObjectFieldOrNull("OVERVIEW") + } + + // by HyperHelper + override fun init() { + var transitionBlurView : MiBlurView? = null + var wallpaperBlurView : MiBlurView? = null + var minusBlurView : MiBlurView? = null + + blurUtil.methodFinder().filterByName("setBackgroundBlurEnabled") + .filterStatic().first() + .hookAfterMethod { param -> + val launcher = param.args[0] + transitionBlurView = MiBlurView(launcher as Activity) + transitionBlurView?.let { + it.setBlur(appsBlurRadius) + it.setDim(appsDimAlpha) + //it.setBackgroundColor(1204495145) + it.setPassWindowBlur(true) + } + + wallpaperBlurView = MiBlurView(launcher) + wallpaperBlurView?.let { + it.setBlur(wallBlurRadius) + it.setDim(wallDimAlpha) + //it.setBackgroundColor(1204495145) + it.setPassWindowBlur(true) + } + + minusBlurView = MiBlurView(launcher) + minusBlurView?.let { + it.setBlur(minusBlurRadius) + it.setDim(minusDimAlpha) + it.setNonlinear(false, LinearInterpolator()) + it.setPassWindowBlur(true) + } + + val viewGroup = XposedHelpers.getObjectField(launcher, "mLauncherView") as ViewGroup + viewGroup.addView(transitionBlurView, viewGroup.indexOfChild( + XposedHelpers.getObjectField(launcher, "mOverviewPanel") as View + ).coerceAtLeast(0)) + viewGroup.addView(wallpaperBlurView, 0) + if (minusOverlapMode) { + viewGroup.addView(minusBlurView) + } + else { + viewGroup.addView(minusBlurView, 0) + } + } + + // Remove blur view from Launcher + loadClass("com.miui.home.recents.views.FloatingIconView").methodFinder() + .filterByName("onLauncherDestroy").first() + .hookAfterMethod { + val viewGroup = + XposedHelpers.getObjectField(it.args[0], "mLauncherView") as ViewGroup + if (transitionBlurView?.isAttachedToWindow == true) { + viewGroup.removeView(transitionBlurView) + } + if (wallpaperBlurView?.isAttachedToWindow == true) { + viewGroup.removeView(wallpaperBlurView) + } + if (minusBlurView?.isAttachedToWindow == true) { + viewGroup.removeView(minusBlurView) + } + transitionBlurView = null + wallpaperBlurView = null + minusBlurView = null + } + + blur.methodFinder().filterByName("fastBlur").filterByParamCount(3) + .first().hookBeforeMethod { + wallpaperBlurView?.show(it.args[2] as Boolean, it.args[0] as Float) + it.result = null + } + + blur.methodFinder().filterByName("fastBlur").filterByParamCount(4) + .first().hookBeforeMethod { + wallpaperBlurView?.showWithDuration(it.args[2] as Boolean, it.args[0] as Float, 350) + it.result = null + } + + // Blur when launching app + blur.methodFinder().filterByName("fastBlurWhenStartOpenOrCloseApp") + .first().hookBeforeMethod { + val isOpen = it.args[0] as Boolean + if (isOpen) { + XposedLogUtils.logD("111") + transitionBlurView?.show(true) + isStartingApp = true + } + else { + XposedLogUtils.logD("222") + // "isOpen" seems to always be true + if (shouldBlurWallpaper(it.args[1] ?: return@hookBeforeMethod)) { + wallpaperBlurView?.show(false) + } + transitionBlurView?.show(false) + transitionBlurView?.hide(true) + } + it.result = null + } + + blur.methodFinder().filterByName("fastBlurWhenFinishOpenOrCloseApp") + .first().replaceMethod { + transitionBlurView?.hide(false) + if (shouldBlurWallpaper(it.args[0] ?: return@replaceMethod null)) { + wallpaperBlurView?.show(false) + } + else { + wallpaperBlurView?.hide(false) + } + if (isStartingApp) { + isStartingApp = false + } else { + + } + } + + // Widely used + blur.methodFinder().filterByName("fastBlurWhenUseCompleteRecentsBlur") + .first().replaceMethod { + val useAnim = it.args[2] as Boolean + mainThreadExecutor.execute { + if (useAnim) { + transitionBlurView?.show(true, it.args[1] as Float) + + isStartingApp = false + } else if (isStartingApp) { + transitionBlurView?.restore() + } else { + transitionBlurView?.show(false, it.args[1] as Float) + } + } + } + + // Use with "fastBlurWhenUseCompleteRecentsBlur" + blur.methodFinder().filterByName("resetBlurWhenUseCompleteRecentsBlur") + .first().replaceMethod { + mainThreadExecutor.execute { + val useAnim = it.args[1] as Boolean + if (shouldBlurWallpaper(it.args[0] ?: return@execute)) { + wallpaperBlurView?.show(false) + } + transitionBlurView?.hide(useAnim) + } + } + + // Blur when entering recent tasks + // Skip when triggered by a gesture in the app + blur.methodFinder().filterByName("fastBlurWhenEnterRecents") + .first().replaceMethod { + if (XposedHelpers.getBooleanField(it.args[1], "mIsFromFsGesture")) { + return@replaceMethod null + } + transitionBlurView?.show(it.args[2] as Boolean) + } + + // Reset blur when exiting recent tasks + // Skip when triggered by a gesture in the app + blur.methodFinder().filterByName("fastBlurWhenExitRecents") + .first().replaceMethod { + if (XposedHelpers.getBooleanField(it.args[1], "mIsFromFsGesture")) { + return@replaceMethod null + } + val useAnim = it.args[2] as Boolean + if (shouldBlurWallpaper(it.args[0] ?: return@replaceMethod null)) { + wallpaperBlurView?.show(false) + } + // Forced animation to avoid flickering when opening a small window + // not sure if it has a negative effect for now + transitionBlurView?.hide(useAnim || fixSmallWindowAnim) + } + + + blur.methodFinder().filterByName("resetBlur") + .first().replaceMethod { + mainThreadExecutor.execute { + val useAnim = it.args[1] as Boolean + if (shouldBlurWallpaper(it.args[0] ?: return@execute)) { + wallpaperBlurView?.show(false) + } +// if (useAnim) { +// transitionBlurView.show(false) +// } + if (isStartingApp && !useAnim) { + transitionBlurView?.hide(true) + } + else { + transitionBlurView?.hide(useAnim) + } + isStartingApp = false + } + } + + blur.methodFinder().filterByName("fastBlurWhenEnterFolderPicker") + .first().replaceMethod { + wallpaperBlurView?.showWithDuration( + it.args[2] as Boolean, it.args[1] as Float, it.args[3] as Int + ) + } + + blur.methodFinder().filterByName("fastBlurWhenExitFolderPicker") + .first().replaceMethod { + val useAnim = it.args[2] as Boolean + if (shouldBlurWallpaper(it.args[0] ?: return@replaceMethod null)) { + return@replaceMethod null + } + if ( + XposedHelpers.getObjectField( + XposedHelpers.getObjectField( + it.args[0],"mStateManager" + ), + "mState" + ) == overviewState + ) { + return@replaceMethod null + } + wallpaperBlurView?.showWithDuration( + useAnim, it.args[1] as Float, it.args[3] as Int + ) + } + + // Beginning of the uncertainty section + blur.methodFinder().filterByName("fastBlurWhenEnterMultiWindowMode") + .first().replaceMethod { + if ( + XposedHelpers.getObjectField( + XposedHelpers.getObjectField(it.args[0] ?: return@replaceMethod null,"mStateManager"), + "mState" + ) == overviewState + ) { + transitionBlurView?.show(it.args[1] as Boolean) + } else { + // 原逻辑没有 else 分支 + } + } + + blur.methodFinder().filterByName("fastBlurWhenGestureResetTaskView") + .first().replaceMethod { + if ( + XposedHelpers.getObjectField( + XposedHelpers.getObjectField(it.args[0] ?: return@replaceMethod null,"mStateManager"), + "mState" + ) == overviewState + ) { + transitionBlurView?.show(it.args[1] as Boolean) + } else { + // 原逻辑没有 else 分支 + } + } + + blur.methodFinder().filterByName("restoreBlurRatioAfterAndroidS") + .first().replaceMethod { + transitionBlurView?.restore(true) + } + + blur.methodFinder().filterByName("fastBlurWhenOpenOrCloseFolder") + .first().replaceMethod { + val useAnim = it.args[1] as Boolean + if (shouldBlurWallpaper(it.args[0] ?: return@replaceMethod null)) { + wallpaperBlurView?.show(useAnim) + } + else { + wallpaperBlurView?.hide(useAnim) + } + } + + // 模糊缺失暂时不写.png + } + + private fun shouldBlurWallpaper(launcher: Any): Boolean { +// val isInNormalEditing = XposedHelpers.callMethod(launcher, "isInNormalEditing") as Boolean +// val isFoldShowing = XposedHelpers.callMethod(launcher, "isFolderShowing") as Boolean + return (XposedHelpers.callMethod(launcher, "isShouldBlur") as Boolean) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sevtinge/hyperceiler/ui/fragment/home/HomeTitleSettings.java b/app/src/main/java/com/sevtinge/hyperceiler/ui/fragment/home/HomeTitleSettings.java index 21dd62ca3d..5e3217e454 100644 --- a/app/src/main/java/com/sevtinge/hyperceiler/ui/fragment/home/HomeTitleSettings.java +++ b/app/src/main/java/com/sevtinge/hyperceiler/ui/fragment/home/HomeTitleSettings.java @@ -20,6 +20,7 @@ import static com.sevtinge.hyperceiler.utils.devicesdk.MiDeviceAppUtilsKt.isPad; import static com.sevtinge.hyperceiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; +import static com.sevtinge.hyperceiler.utils.devicesdk.SystemSDKKt.isMoreHyperOSVersion; import android.content.Intent; import android.os.Bundle; @@ -33,6 +34,7 @@ import com.sevtinge.hyperceiler.ui.fragment.sub.AppPicker; import moralnorm.preference.Preference; +import moralnorm.preference.PreferenceCategory; import moralnorm.preference.SwitchPreference; public class HomeTitleSettings extends SettingsPreferenceFragment { @@ -42,6 +44,7 @@ public class HomeTitleSettings extends SettingsPreferenceFragment { SwitchPreference mDisableHideTheme; Preference mIconTitleCustomization; RecommendPreference mRecommend; + PreferenceCategory mAppBlur; @Override public int getContentResId() { @@ -60,6 +63,8 @@ public View.OnClickListener addRestartListener() { public void initPrefs() { mIconTitleCustomization = findPreference("prefs_key_home_title_title_icontitlecustomization"); mDisableMonoChrome = findPreference("prefs_key_home_other_icon_mono_chrome"); + mAppBlur = findPreference("prefs_key_home_title_app_blur_hyper"); + mDisableMonoChrome.setVisible(isMoreAndroidVersion(33)); mDisableMonoChrome.setOnPreferenceChangeListener((preference, o) -> true); mDisableMonetColor = findPreference("prefs_key_home_other_icon_monet_color"); @@ -67,6 +72,8 @@ public void initPrefs() { mDisableMonetColor.setOnPreferenceChangeListener((preference, o) -> true); mDisableHideTheme = findPreference("prefs_key_home_title_disable_hide_theme"); mDisableHideTheme.setVisible(isPad()); + mAppBlur.setVisible(isMoreHyperOSVersion(1f)); + mIconTitleCustomization.setOnPreferenceClickListener(preference -> { Intent intent = new Intent(getActivity(), SubPickerActivity.class); intent.putExtra("mode", AppPicker.INPUT_MODE); diff --git a/app/src/main/java/com/sevtinge/hyperceiler/utils/api/HyperHelperApis.kt b/app/src/main/java/com/sevtinge/hyperceiler/utils/api/HyperHelperApis.kt new file mode 100644 index 0000000000..fbcec383dc --- /dev/null +++ b/app/src/main/java/com/sevtinge/hyperceiler/utils/api/HyperHelperApis.kt @@ -0,0 +1,11 @@ +package com.sevtinge.hyperceiler.utils.api + +object HyperHelperApis { + fun linearInterpolate(start: Float, stop: Float, amount: Float): Float { + return start + (stop - start) * amount + } + + fun linearInterpolate(start: Int, stop: Int, amount: Float): Int { + return start + ((stop - start) * amount).toInt() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sevtinge/hyperceiler/utils/blur/MiBlurView.kt b/app/src/main/java/com/sevtinge/hyperceiler/utils/blur/MiBlurView.kt new file mode 100644 index 0000000000..63fc0105c3 --- /dev/null +++ b/app/src/main/java/com/sevtinge/hyperceiler/utils/blur/MiBlurView.kt @@ -0,0 +1,190 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This file is part of XiaomiHelper project + * Copyright (C) 2023 HowieHChen, howie.dev@outlook.com + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.sevtinge.hyperceiler.utils.blur + +import android.animation.* +import android.content.* +import android.graphics.* +import android.view.* +import android.view.animation.* +import android.view.animation.Interpolator +import android.widget.* +import com.sevtinge.hyperceiler.utils.api.HyperHelperApis.linearInterpolate +import com.sevtinge.hyperceiler.utils.blur.MiBlurUtils.* +import com.sevtinge.hyperceiler.utils.blur.MiBlurUtilsKt.clearAllBlur +import com.sevtinge.hyperceiler.utils.blur.MiBlurUtilsKt.setMiBackgroundBlurRadius +import kotlin.math.* + +class MiBlurView(context: Context): View(context) { + companion object { + const val DEFAULT_ANIM_DURATION = 250 + const val DEFAULT_BLUR_ENABLED = true + const val DEFAULT_BLUR_MAX_RADIUS = 100 + const val DEFAULT_DIM_ENABLED = true + const val DEFAULT_DIM_MAX_ALPHA = 64 + const val DEFAULT_NONLINEAR_ENABLED = false + } + + private var mainAnimator: ValueAnimator? = null + private var animCurrentRatio = 0.0f + private var animCount = 0 + private var allowRestoreDirectly = false + private var isBlurInitialized = false + // Personalized Configurations + private var blurEnabled = DEFAULT_BLUR_ENABLED + private var blurMaxRadius = DEFAULT_BLUR_MAX_RADIUS + private var dimEnabled = DEFAULT_DIM_ENABLED + private var dimMaxAlpha = DEFAULT_DIM_MAX_ALPHA + private var nonlinearEnabled = DEFAULT_NONLINEAR_ENABLED + private var nonlinearInterpolator: Interpolator = LinearInterpolator() + private var passWindowBlurEnabled = false + + init { + this.layoutParams = FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + this.setBackgroundColor(Color.TRANSPARENT) + this.visibility = GONE + } + + fun setPassWindowBlur(enabled: Boolean) { + passWindowBlurEnabled = enabled + } + + fun setBlur(maxRadius: Int) { + blurMaxRadius = maxRadius + if (blurMaxRadius <= 0) { + blurEnabled = false + } + } + + fun setDim(maxAlpha: Int) { + dimMaxAlpha = maxAlpha + if (maxAlpha <= 0) { + dimEnabled = false + } + } + + fun setNonlinear(useNonlinear: Boolean, interpolator: Interpolator) { + nonlinearEnabled = useNonlinear + nonlinearInterpolator = interpolator + } + + fun show(useAnim: Boolean, targetRatio: Float = 1.0f) { + this.visibility = VISIBLE + applyBlur(targetRatio, useAnim) + } + + fun hide(useAnim: Boolean, targetRatio: Float = 0.0f) { + this.visibility = VISIBLE + applyBlur(targetRatio, useAnim) + } + + fun restore(directly: Boolean = false) { + this.visibility = VISIBLE + if (!directly) { + applyBlur(animCurrentRatio, false) + } + else if (allowRestoreDirectly) { + allowRestoreDirectly = false + if (blurEnabled && !isBlurInitialized) { + initBlur() + } + applyBlurDirectly(animCurrentRatio) + } + } + + fun showWithDuration(useAnim: Boolean, targetRatio: Float, duration: Int) { + this.visibility = VISIBLE + applyBlur(targetRatio, useAnim, duration) + } + + private fun applyBlur(ratio: Float, useAnim: Boolean, duration: Int = DEFAULT_ANIM_DURATION) { + val targetRatio = ratio.coerceIn(0.0f, 1.0f) + if (mainAnimator?.isRunning == true) { + mainAnimator?.cancel() + } + if (blurEnabled && !isBlurInitialized) { + initBlur() + } + if (!useAnim || animCurrentRatio == targetRatio) { + applyBlurDirectly(targetRatio) + } + else { + val currentRatio = animCurrentRatio + if (mainAnimator == null) { + mainAnimator = ValueAnimator() + } + mainAnimator?.let { + it.setFloatValues(currentRatio, targetRatio) + it.duration = (abs(currentRatio - targetRatio) * duration).toLong() + it.interpolator = LinearInterpolator() + it.removeAllUpdateListeners() + it.addUpdateListener { animator -> + animCount++ + val animaValue = animator.animatedValue as Float + if ((animCount % 2 != 1 || animaValue == currentRatio) && animaValue != targetRatio) { + return@addUpdateListener + } + applyBlurDirectly( + if (nonlinearEnabled) { nonlinearInterpolator.getInterpolation(animaValue) } + else { animaValue } + ) + } + animCount = 0 + it.start() + } + } + } + + private fun applyBlurDirectly(ratio: Float) { + val blurRadius = linearInterpolate(0, blurMaxRadius, ratio) + if (blurEnabled) { + this.setMiBackgroundBlurRadius(blurRadius) + } + if (dimEnabled) { + this.setBackgroundColor( + linearInterpolate(0, dimMaxAlpha, ratio).shl(24) + ) + } + animCurrentRatio = ratio + allowRestoreDirectly = true + if (ratio == 0.0f || blurRadius == 0) { + releaseBlur() + } + } + + private fun initBlur() { + if (isBlurInitialized) return + this.clearAllBlur() + setPassWindowBlurEnabled(this, passWindowBlurEnabled) + setMiBackgroundBlurMode(this, 1) + setMiViewBlurMode(this, 1) + isBlurInitialized = true + } + + private fun releaseBlur() { + if (!isBlurInitialized) return + isBlurInitialized = false + this.visibility = GONE + this.clearAllBlur() + } +} \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 73cbcb3dd3..b00c8cedfd 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1200,6 +1200,14 @@ 图标与标题 图标 图标动画 + 应用模糊 + 应用动画背景模糊 + 一次模糊遮罩模糊半径 + 一次模糊遮罩背景不透明度 + 二次模糊遮罩模糊半径 + 二次模糊遮罩背景不透明度 + 额外修复小窗动画 + 实验性功能,强制使用动画以避免拖动应用进入小窗时闪烁,不介意勿用 标题 文字滚动 过长的应用名称将以滚动进行显示,不再使用换行 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6a23922477..a37df0c2ea 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1171,6 +1171,14 @@ Icon and Title Icon Icon Animation + App Blur + Enable app animated background blur + App animation background blur radius + App animation background mask transparency + Wallpaper blur radius + Wallpaper mask transparency + Additional fix for small window animation + Experimental function, force the use of animation to avoid flickering when dragging the application into a small window, don\'t use it if you don\'t mind Title Text scroll App names that are too long will be scrolled instead of wrapping diff --git a/app/src/main/res/xml/home_title.xml b/app/src/main/res/xml/home_title.xml index cbd0e67979..9c5fce5d39 100644 --- a/app/src/main/res/xml/home_title.xml +++ b/app/src/main/res/xml/home_title.xml @@ -115,6 +115,86 @@ + + + + + + + + + + + + + + + + + + +