From 3e0b5a9f414c76912945305ba92ad4308b01c096 Mon Sep 17 00:00:00 2001 From: Hu Shenghao Date: Fri, 10 Jan 2025 15:35:04 +0800 Subject: [PATCH] feat: Enable EdgeToEdge on the Egg pages Signed-off-by: Hu Shenghao --- CHANGELOG.md | 5 ++ CHANGELOG_zh.md | 5 ++ app/build.gradle.kts | 4 +- .../com/dede/android_eggs/util/EdgeUtils.kt | 35 ------------ basic/consumer-rules.pro | 3 +- .../androidx/activity/EdgeToEdgeCompat.java | 57 +++++++++++++++---- basic/src/main/java/com/dede/basic/Utils.kt | 4 -- core/activity-actions/build.gradle.kts | 6 ++ .../ActivityActionDispatcher.kt | 4 +- .../util/actions/EggActivityAction.kt | 33 +++++++++++ .../util/actions/PlatLogoActivityAction.kt | 22 ------- eggs/Lollipop/src/main/AndroidManifest.xml | 3 +- .../java/com/android_l/egg/LLandActivity.java | 28 +++++++++ eggs/Marshmallow/src/main/AndroidManifest.xml | 3 +- .../java/com/android_m/egg/MLandActivity.java | 5 +- eggs/R/AndroidManifest.xml | 3 +- eggs/S/src/main/AndroidManifest.xml | 3 +- .../metadata/android/en-US/changelogs/58.txt | 2 + .../metadata/android/zh-CN/changelogs/58.txt | 2 + 19 files changed, 145 insertions(+), 82 deletions(-) delete mode 100644 app/src/main/java/com/dede/android_eggs/util/EdgeUtils.kt create mode 100644 core/activity-actions/src/main/java/com/dede/android_eggs/util/actions/EggActivityAction.kt delete mode 100644 core/activity-actions/src/main/java/com/dede/android_eggs/util/actions/PlatLogoActivityAction.kt create mode 100644 fastlane/metadata/android/en-US/changelogs/58.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/58.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 5996269b6..e9b41a2af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +### v3.4.0 + +- EdgeToEdge mode is enabled on the Easter Egg pages +- Upgrade project dependencies + ### v3.3.0 (2024-12-20) - Add Rocket Launcher Easter Egg [#286](https://github.com/hushenghao/AndroidEasterEggs/issues/286) diff --git a/CHANGELOG_zh.md b/CHANGELOG_zh.md index 24ca09717..22c69fed3 100644 --- a/CHANGELOG_zh.md +++ b/CHANGELOG_zh.md @@ -1,5 +1,10 @@ # 更新日志 +### v3.4.0 + +- 彩蛋相关页面开启了 EdgeToEdge 模式 +- 升级项目依赖项 + ### v3.3.0 (2024-12-20) - 添加 Rocket Launcher 彩蛋 [#286](https://github.com/hushenghao/AndroidEasterEggs/issues/286) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index de6f8b9e7..6c40127d2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -7,8 +7,8 @@ android { defaultConfig { applicationId = "com.dede.android_eggs" - versionCode = 57 - versionName = "3.3.0" + versionCode = 58 + versionName = "3.4.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" resourceConfigurations += listOf( diff --git a/app/src/main/java/com/dede/android_eggs/util/EdgeUtils.kt b/app/src/main/java/com/dede/android_eggs/util/EdgeUtils.kt deleted file mode 100644 index 2ccd5c3ee..000000000 --- a/app/src/main/java/com/dede/android_eggs/util/EdgeUtils.kt +++ /dev/null @@ -1,35 +0,0 @@ -@file:Suppress("NOTHING_TO_INLINE") - -package com.dede.android_eggs.util - -import android.view.View -import androidx.core.graphics.Insets -import androidx.core.view.OnApplyWindowInsetsListener -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsCompat.Type.InsetsType - - -object EdgeUtils { - - val DEFAULT_EDGE_MASK = - WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() - - inline fun T.onApplyWindowEdge( - @InsetsType typeMask: Int = DEFAULT_EDGE_MASK, - noinline onApplyWindowEdge: T.(edge: Insets) -> Unit, - ) { - this.onApplyWindowInsets { - onApplyWindowEdge(this, it.getInsets(typeMask)) - } - } - - inline fun T.onApplyWindowInsets(noinline onApplyWindowInsets: T.(insets: WindowInsetsCompat) -> Unit) { - ViewCompat.setOnApplyWindowInsetsListener(this, OnApplyWindowInsetsListener { v, insets -> - @Suppress("UNCHECKED_CAST") - onApplyWindowInsets(v as T, insets) - return@OnApplyWindowInsetsListener insets - }) - } - -} \ No newline at end of file diff --git a/basic/consumer-rules.pro b/basic/consumer-rules.pro index 5e2aa2def..993156d4a 100644 --- a/basic/consumer-rules.pro +++ b/basic/consumer-rules.pro @@ -5,4 +5,5 @@ # EdgeToEdgeCompat -keep class androidx.activity.EdgeToEdgeImpl { *; } --keep class * extends androidx.activity.EdgeToEdgeImpl { *; } \ No newline at end of file +-keep class * extends androidx.activity.EdgeToEdgeImpl { *; } +-keep class com.google.android.material.internal.EdgeToEdgeUtils { *; } diff --git a/basic/src/main/java/androidx/activity/EdgeToEdgeCompat.java b/basic/src/main/java/androidx/activity/EdgeToEdgeCompat.java index 6c30a23bc..5d9bdbdcc 100644 --- a/basic/src/main/java/androidx/activity/EdgeToEdgeCompat.java +++ b/basic/src/main/java/androidx/activity/EdgeToEdgeCompat.java @@ -6,12 +6,14 @@ import android.util.Log; import android.view.View; import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.core.view.WindowInsetsCompat; import com.dede.basic.utils.DynamicObjectUtils; import com.dede.basic.utils.dynamic.DynamicResult; -import org.jetbrains.annotations.Nullable; - /** * EdgeToEdge compat * @@ -19,9 +21,10 @@ */ public class EdgeToEdgeCompat { + public static final int EDGE_INSETS_MASK = WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout(); + private static final String TAG = "EdgeToEdgeCompat"; - @Nullable private final static EdgeToEdgeImpl impl = createEdgeToEdgeImpl(); /** @@ -30,7 +33,6 @@ public class EdgeToEdgeCompat { * @return EdgeToEdgeImpl instance * @see EdgeToEdge#enable(ComponentActivity) */ - @Nullable private static EdgeToEdgeImpl createEdgeToEdgeImpl() { String className = "androidx.activity.EdgeToEdgeBase"; final int[] apis = { @@ -43,17 +45,57 @@ private static EdgeToEdgeImpl createEdgeToEdgeImpl() { }; for (int api : apis) { if (Build.VERSION.SDK_INT >= api) { - className = "androidx.activity.EdgeToEdgeApi" + api; + className = "androidx.activity.EdgeToEdgeApi1" + api; break; } } DynamicResult dynamicResult = DynamicObjectUtils.asDynamicObject(className) .newInstance(new Class[0], new Object[0]); EdgeToEdgeImpl impl = DynamicResult.getTypeValue(dynamicResult, EdgeToEdgeImpl.class); + if (impl == null) { + impl = new MaterialEdgeToEdgeUtilsImpl(); + } Log.i(TAG, "EdgeToEdgeImpl: " + impl); return impl; } + private static class MaterialEdgeToEdgeUtilsImpl implements EdgeToEdgeImpl { + + private static int getScrimColor(SystemBarStyle systemBarStyle, boolean isDark) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + // support dark mode + return systemBarStyle.getScrimWithEnforcedContrast$activity_release(isDark); + } else { + return systemBarStyle.getScrim$activity_release(isDark); + } + } + + @Override + public void setUp(@NonNull SystemBarStyle statusBarStyle, + @NonNull SystemBarStyle navigationBarStyle, + @NonNull Window window, + @NonNull View view, + boolean statusBarIsDark, + boolean navigationBarIsDark) { + DynamicObjectUtils.asDynamicObject("com.google.android.material.internal.EdgeToEdgeUtils") + .invokeMethod("applyEdgeToEdge", + new Class[]{Window.class, boolean.class, Integer.class, Integer.class}, + new Object[]{window, true, getScrimColor(statusBarStyle, statusBarIsDark), getScrimColor(navigationBarStyle, navigationBarIsDark)}); + } + + @Override + public void adjustLayoutInDisplayCutoutMode(@NonNull Window window) { + WindowManager.LayoutParams attributes = window.getAttributes(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + attributes.layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + attributes.layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + } + } + } + private static boolean getDetectDarkMode(SystemBarStyle systemBarStyle, View view) { // internal val detectDarkMode: (Resources) -> Boolean // androidx.activity library @@ -67,11 +109,6 @@ public static void enable(Activity activity, SystemBarStyle statusBarStyle, Syst return; } - if (impl == null) { - Log.w(TAG, "enableEdgeToEdge, impl == null"); - return; - } - Window window = activity.getWindow(); View view = window.getDecorView(); boolean statusBarIsDark = getDetectDarkMode(statusBarStyle, view); diff --git a/basic/src/main/java/com/dede/basic/Utils.kt b/basic/src/main/java/com/dede/basic/Utils.kt index e2ca1efac..bca674da0 100644 --- a/basic/src/main/java/com/dede/basic/Utils.kt +++ b/basic/src/main/java/com/dede/basic/Utils.kt @@ -4,7 +4,6 @@ package com.dede.basic import android.animation.ValueAnimator -import android.app.Activity import android.content.Context import android.content.Intent import android.content.pm.PackageInfo @@ -73,7 +72,4 @@ object Utils { return null to -1L } - val Activity.isPlatLogoActivity: Boolean - get() = javaClass.simpleName == "PlatLogoActivity" - } diff --git a/core/activity-actions/build.gradle.kts b/core/activity-actions/build.gradle.kts index 4513987a7..1f239aa1d 100644 --- a/core/activity-actions/build.gradle.kts +++ b/core/activity-actions/build.gradle.kts @@ -15,7 +15,13 @@ dependencies { implementation(project(":eggs:Tiramisu")) implementation(project(":eggs:S")) implementation(project(":eggs:R")) + implementation(project(":eggs:Oreo")) implementation(project(":eggs:Nougat")) + implementation(project(":eggs:Marshmallow")) + implementation(project(":eggs:Lollipop")) + implementation(project(":eggs:KitKat")) + implementation(project(":eggs:JellyBean")) + implementation(project(":eggs:IceCreamSandwich")) implementation(libs.androidx.startup) implementation(platform(libs.androidx.compose.bom)) diff --git a/core/activity-actions/src/main/java/com/dede/android_eggs/activity_actions/ActivityActionDispatcher.kt b/core/activity-actions/src/main/java/com/dede/android_eggs/activity_actions/ActivityActionDispatcher.kt index b5225cc0d..9330a7fa9 100644 --- a/core/activity-actions/src/main/java/com/dede/android_eggs/activity_actions/ActivityActionDispatcher.kt +++ b/core/activity-actions/src/main/java/com/dede/android_eggs/activity_actions/ActivityActionDispatcher.kt @@ -8,7 +8,7 @@ import android.content.Context import android.os.Bundle import androidx.startup.Initializer import com.dede.android_eggs.activity_actions.noOpDelegate -import com.dede.android_eggs.util.actions.PlatLogoActivityAction +import com.dede.android_eggs.util.actions.EggActivityAction import com.dede.android_eggs.util.actions.RequestNotificationPermissionAction import com.dede.android_eggs.util.actions.WarningDialogAction @@ -34,7 +34,7 @@ internal class ActivityActionDispatcher : Application.ActivityLifecycleCallbacks } private val actions: Array = arrayOf( - PlatLogoActivityAction(), + EggActivityAction(), WarningDialogAction(), RequestNotificationPermissionAction(), ) diff --git a/core/activity-actions/src/main/java/com/dede/android_eggs/util/actions/EggActivityAction.kt b/core/activity-actions/src/main/java/com/dede/android_eggs/util/actions/EggActivityAction.kt new file mode 100644 index 000000000..8455ed872 --- /dev/null +++ b/core/activity-actions/src/main/java/com/dede/android_eggs/util/actions/EggActivityAction.kt @@ -0,0 +1,33 @@ +package com.dede.android_eggs.util.actions + +import android.app.Activity +import androidx.activity.EdgeToEdgeCompat +import com.dede.android_eggs.util.ActivityActionDispatcher +import com.dede.android_eggs.views.main.util.EasterEggShortcutsHelp + +internal class EggActivityAction : ActivityActionDispatcher.ActivityAction { + + private val edgeToEdgePagers: Set> = setOf( + com.android_o.egg.octo.Ocquarium::class.java, + com.android_m.egg.MLandActivity::class.java, + com.android_l.egg.LLandActivity::class.java, + com.android_k.egg.DessertCase::class.java, + com.android_j.egg.BeanBag::class.java, + com.android_i.egg.Nyandroid::class.java, + ) + + private val Activity.isPlatLogoActivity: Boolean + get() = javaClass.simpleName == "PlatLogoActivity" + + override fun onPreCreate(activity: Activity) { + if (activity.isPlatLogoActivity || edgeToEdgePagers.contains(activity.javaClass)) { + EdgeToEdgeCompat.enable(activity) + } + } + + override fun onCreate(activity: Activity) { + if (activity.isPlatLogoActivity) { + EasterEggShortcutsHelp.autoReportShortcutUsed(activity, activity.intent) + } + } +} diff --git a/core/activity-actions/src/main/java/com/dede/android_eggs/util/actions/PlatLogoActivityAction.kt b/core/activity-actions/src/main/java/com/dede/android_eggs/util/actions/PlatLogoActivityAction.kt deleted file mode 100644 index d5f4bc9e9..000000000 --- a/core/activity-actions/src/main/java/com/dede/android_eggs/util/actions/PlatLogoActivityAction.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.dede.android_eggs.util.actions - -import android.app.Activity -import androidx.activity.EdgeToEdgeCompat -import com.dede.android_eggs.util.ActivityActionDispatcher -import com.dede.android_eggs.views.main.util.EasterEggShortcutsHelp -import com.dede.basic.Utils.isPlatLogoActivity - -internal class PlatLogoActivityAction : ActivityActionDispatcher.ActivityAction { - - override fun onPreCreate(activity: Activity) { - if (activity.isPlatLogoActivity) { - EdgeToEdgeCompat.enable(activity) - } - } - - override fun onCreate(activity: Activity) { - if (activity.isPlatLogoActivity) { - EasterEggShortcutsHelp.autoReportShortcutUsed(activity, activity.intent) - } - } -} diff --git a/eggs/Lollipop/src/main/AndroidManifest.xml b/eggs/Lollipop/src/main/AndroidManifest.xml index a76f5c441..4d4f3d00c 100644 --- a/eggs/Lollipop/src/main/AndroidManifest.xml +++ b/eggs/Lollipop/src/main/AndroidManifest.xml @@ -19,7 +19,8 @@ android:label="@string/l_lland" android:launchMode="singleInstance" android:screenOrientation="locked" - android:theme="@android:style/Theme.Material.NoActionBar" /> + android:theme="@android:style/Theme.Material.NoActionBar.Fullscreen" /> + \ No newline at end of file diff --git a/eggs/Lollipop/src/main/java/com/android_l/egg/LLandActivity.java b/eggs/Lollipop/src/main/java/com/android_l/egg/LLandActivity.java index 04687668c..ac766efef 100644 --- a/eggs/Lollipop/src/main/java/com/android_l/egg/LLandActivity.java +++ b/eggs/Lollipop/src/main/java/com/android_l/egg/LLandActivity.java @@ -19,8 +19,17 @@ import android.app.Activity; import android.os.Bundle; import android.util.Log; +import android.view.View; +import android.view.ViewGroup; import android.widget.TextView; +import androidx.activity.EdgeToEdgeCompat; +import androidx.annotation.NonNull; +import androidx.core.graphics.Insets; +import androidx.core.view.OnApplyWindowInsetsListener; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + public class LLandActivity extends Activity { @Override @@ -31,5 +40,24 @@ public void onCreate(Bundle savedInstanceState) { world.setScoreField((TextView) findViewById(R.id.score)); world.setSplash(findViewById(R.id.welcome)); Log.v(LLand.TAG, "focus: " + world.requestFocus()); + + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.score), new OnApplyWindowInsetsListener() { + + private ViewGroup.MarginLayoutParams copyParams; + + @NonNull + @Override + public WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets) { + Insets edge = insets.getInsets(EdgeToEdgeCompat.EDGE_INSETS_MASK); + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)v.getLayoutParams(); + if (copyParams == null) { + copyParams = new ViewGroup.MarginLayoutParams(params); + } + params.topMargin = edge.top + copyParams.topMargin; + params.leftMargin = edge.left + copyParams.leftMargin; + v.setLayoutParams(params); + return insets; + } + }); } } diff --git a/eggs/Marshmallow/src/main/AndroidManifest.xml b/eggs/Marshmallow/src/main/AndroidManifest.xml index 9f64d5a00..975a7e0fa 100644 --- a/eggs/Marshmallow/src/main/AndroidManifest.xml +++ b/eggs/Marshmallow/src/main/AndroidManifest.xml @@ -21,6 +21,7 @@ android:label="@string/m_mland" android:launchMode="singleInstance" android:screenOrientation="locked" - android:theme="@android:style/Theme.Material.NoActionBar" /> + android:theme="@android:style/Theme.Material.NoActionBar.Fullscreen" /> + \ No newline at end of file diff --git a/eggs/Marshmallow/src/main/java/com/android_m/egg/MLandActivity.java b/eggs/Marshmallow/src/main/java/com/android_m/egg/MLandActivity.java index cc5f51d5d..7e6a0989b 100644 --- a/eggs/Marshmallow/src/main/java/com/android_m/egg/MLandActivity.java +++ b/eggs/Marshmallow/src/main/java/com/android_m/egg/MLandActivity.java @@ -21,6 +21,7 @@ import android.view.View; import android.view.ViewGroup; +import androidx.activity.EdgeToEdgeCompat; import androidx.annotation.NonNull; import androidx.core.graphics.Insets; import androidx.core.view.OnApplyWindowInsetsListener; @@ -48,9 +49,9 @@ public void onCreate(Bundle savedInstanceState) { @NonNull @Override public WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets) { - Insets edge = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + Insets edge = insets.getInsets(EdgeToEdgeCompat.EDGE_INSETS_MASK); v.setPadding(0, edge.top, 0, 0); - return WindowInsetsCompat.CONSUMED; + return insets; } }); } diff --git a/eggs/R/AndroidManifest.xml b/eggs/R/AndroidManifest.xml index 53763d3a7..1f6fb0c33 100644 --- a/eggs/R/AndroidManifest.xml +++ b/eggs/R/AndroidManifest.xml @@ -18,7 +18,8 @@ android:exported="true" android:icon="@drawable/r_icon" android:label="@string/r_egg_name" - android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar" /> + android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen" /> + + android:theme="@android:style/Theme.Wallpaper.NoTitleBar.Fullscreen" /> +