Skip to content

Commit 547e891

Browse files
committed
fix(theme): restore Material 3 FAB theming
1 parent fbecb5e commit 547e891

4 files changed

Lines changed: 49 additions & 44 deletions

File tree

app/src/main/java/io/nekohasekai/sagernet/ui/ThemedActivity.kt

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package io.nekohasekai.sagernet.ui
33
import android.content.res.Configuration
44
import android.os.Build
55
import android.os.Bundle
6-
import android.util.TypedValue
76
import android.widget.TextView
87
import androidx.annotation.StringRes
98
import androidx.appcompat.app.AppCompatActivity
@@ -14,7 +13,6 @@ import androidx.core.view.WindowInsetsCompat
1413
import androidx.core.view.updatePadding
1514
import com.google.android.material.appbar.AppBarLayout
1615
import com.google.android.material.color.DynamicColors
17-
import com.google.android.material.color.DynamicColorsOptions
1816
import com.google.android.material.snackbar.Snackbar
1917
import io.nekohasekai.sagernet.R
2018
import io.nekohasekai.sagernet.database.DataStore
@@ -36,11 +34,9 @@ abstract class ThemedActivity : AppCompatActivity {
3634
}
3735
Theme.applyNightTheme()
3836

39-
// Material 3 "to the bone": derive a full, correct M3 tonal palette for the active
40-
// theme. When the user picks the Dynamic (Material You) theme on Android 12+, seed
41-
// from the system wallpaper; otherwise seed from the selected theme's colorPrimary so
42-
// every theme (and pre-12 device) gets proper M3 roles (container/surface-variant/
43-
// outline/...) generated from its seed instead of hand-authored values.
37+
// Only the explicit Dynamic (Material You) theme should use wallpaper colors.
38+
// The hand-picked themes keep their legacy palettes instead of being reseeded
39+
// into Material 3's generated tonal roles.
4440
if (!isDialog) applyDynamicColors()
4541

4642
super.onCreate(savedInstanceState)
@@ -74,35 +70,14 @@ abstract class ThemedActivity : AppCompatActivity {
7470
}
7571

7672
/**
77-
* Apply Material 3 dynamic colors. For the Dynamic (Material You) theme on Android 12+ the
78-
* palette comes from the system wallpaper; for every other theme we seed a content-based
79-
* palette from the theme's own colorPrimary so all M3 roles are generated correctly
80-
* (works on all API levels, no hand-authored per-theme palettes).
73+
* Apply Material 3 dynamic color ONLY when the user explicitly picks the Dynamic
74+
* (Material You) theme, and only on Android 12+ where a wallpaper palette exists.
75+
* The hand-designed themes keep their own colors untouched — forcing a content-based
76+
* reseed on them mangled their palettes into arbitrary M3 tones.
8177
*/
8278
private fun applyDynamicColors() {
8379
if (DataStore.appTheme == Theme.DYNAMIC) {
84-
// Wallpaper-based; only takes effect on Android 12+, otherwise a no-op and the
85-
// base theme's colors stand.
8680
DynamicColors.applyToActivityIfAvailable(this)
87-
return
88-
}
89-
val seed = resolveColorAttr(com.google.android.material.R.attr.colorPrimary)
90-
if (seed == 0) return
91-
DynamicColors.applyToActivityIfAvailable(
92-
this,
93-
DynamicColorsOptions.Builder()
94-
.setContentBasedSource(seed)
95-
.build()
96-
)
97-
}
98-
99-
private fun resolveColorAttr(attr: Int): Int {
100-
val tv = TypedValue()
101-
theme.resolveAttribute(attr, tv, true)
102-
return if (tv.resourceId != 0) {
103-
androidx.core.content.ContextCompat.getColor(this, tv.resourceId)
104-
} else {
105-
tv.data
10681
}
10782
}
10883

app/src/main/res/layout/layout_main.xml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
android:nextFocusUp="@+id/fab"
2828
app:backgroundTint="?colorPrimary"
2929
app:contentInsetStart="0dp"
30+
app:fabAlignmentMode="center"
31+
app:fabAnchorMode="cradle"
3032
app:hideOnScroll="true"
3133
app:layout_scrollFlags="enterAlways|scroll">
3234

@@ -75,9 +77,8 @@
7577
</io.nekohasekai.sagernet.widget.StatsBar>
7678

7779
<!-- FAB + its progress are declared AFTER the StatsBar so the airplane draws on top
78-
of the bottom bar and wins touch in the overlap region. (M2's BottomAppBar cut a
79-
cradle hole for the FAB; M3's bar fills it, so without this the bar covered and
80-
intercepted the FAB when connected.) -->
80+
of the bottom bar and wins touch in the overlap region. StatsBar opts into the
81+
legacy BottomAppBar cradle so the centered FAB docks into the bar. -->
8182
<!-- We double trackThickness as half of it will be invisible -->
8283
<com.google.android.material.progressindicator.CircularProgressIndicator
8384
android:id="@+id/fabProgress"
@@ -96,13 +97,11 @@
9697
android:id="@+id/fab"
9798
android:layout_width="wrap_content"
9899
android:layout_height="wrap_content"
99-
android:layout_margin="16dp"
100100
android:elevation="6dp"
101101
android:nextFocusDown="@+id/stats"
102-
app:backgroundTint="?attr/colorTertiaryContainer"
103-
app:tint="?attr/colorOnTertiaryContainer"
102+
app:backgroundTint="?attr/fabColorBackground"
103+
app:tint="?attr/fabStoppedColor"
104104
app:layout_anchor="@id/stats"
105-
app:layout_anchorGravity="top|end"
106105
app:pressedTranslationZ="6dp"
107106
app:srcCompat="@drawable/ic_service_idle" />
108107

app/src/main/res/values-v26/themes.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
<!-- Base application theme for API 26+ -->
33
<style name="Theme.SagerNet" parent="Theme.Material3.DayNight.NoActionBar">
44
<item name="actionBarStyle">@style/Widget.MaterialComponents.ActionBar.Solid</item>
5+
<item name="bottomAppBarStyle">@style/Widget.SagerNet.BottomAppBar</item>
6+
<item name="floatingActionButtonStyle">@style/Widget.SagerNet.FloatingActionButton</item>
57
<!-- Default nav-drawer selected-item fill; satisfies the
68
?itemShapeFillColor self-reference in @color/navigation_item. -->
79
<item name="itemShapeFillColor">?colorPrimary</item>
@@ -26,6 +28,7 @@
2628
<item name="colorPrimary">@color/material_pink_500</item>
2729
<item name="colorPrimaryDark">@color/material_pink_700</item>
2830
<item name="colorAccent">@color/material_pink_accent_200</item>
31+
<item name="colorOnPrimary">@color/white</item>
2932

3033
<item name="colorMaterial100">@color/material_pink_100</item>
3134
<item name="colorMaterial300">@color/material_pink_300</item>

app/src/main/res/values/themes.xml

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<resources>
2-
<!-- Base application theme. Migrated to Material 3. M3 derives the accent/variant
3-
roles from colorPrimary, but this app sets explicit per-theme palettes, so the
4-
key M3 color roles are populated below and per-theme overrides follow in each
5-
Theme.SagerNet.* variant. -->
2+
<!-- Base application theme. Migrated to Material 3 while keeping the app's
3+
hand-picked legacy palettes. Components that need legacy behavior get
4+
explicit SagerNet widget styles instead of relying on generated M3 tones. -->
65
<style name="Theme.SagerNet" parent="Theme.Material3.DayNight.NoActionBar">
76
<item name="actionBarStyle">@style/Widget.MaterialComponents.ActionBar.Solid</item>
7+
<item name="bottomAppBarStyle">@style/Widget.SagerNet.BottomAppBar</item>
8+
<item name="floatingActionButtonStyle">@style/Widget.SagerNet.FloatingActionButton</item>
89
<!-- Protocol/type label color; defaults to accent, Dracula overrides green. -->
910
<item name="protocolColor">?attr/accentOrTextSecondary</item>
1011
<!-- Per-theme semantic colors; default to primary text (no visible change),
@@ -31,6 +32,7 @@
3132
<item name="colorPrimary">@color/material_pink_500</item>
3233
<item name="colorPrimaryDark">@color/material_pink_700</item>
3334
<item name="colorAccent">@color/material_pink_accent_200</item>
35+
<item name="colorOnPrimary">@color/white</item>
3436

3537
<item name="colorMaterial100">@color/material_pink_100</item>
3638
<item name="colorMaterial300">@color/material_pink_300</item>
@@ -81,6 +83,8 @@
8183

8284
<style name="Theme.SagerNet.Dialog" parent="Theme.Material3.DayNight.Dialog.Alert">
8385
<item name="actionBarStyle">@style/Widget.MaterialComponents.ActionBar.Solid</item>
86+
<item name="bottomAppBarStyle">@style/Widget.SagerNet.BottomAppBar</item>
87+
<item name="floatingActionButtonStyle">@style/Widget.SagerNet.FloatingActionButton</item>
8488
<item name="protocolColor">?attr/accentOrTextSecondary</item>
8589
<item name="profileNameColor">?android:attr/textColorPrimary</item>
8690
<item name="statusConnectedColor">?attr/colorOnPrimary</item>
@@ -100,6 +104,7 @@
100104
<item name="colorPrimary">@color/material_pink_500</item>
101105
<item name="colorPrimaryDark">@color/material_pink_700</item>
102106
<item name="colorAccent">@color/material_pink_accent_200</item>
107+
<item name="colorOnPrimary">@color/white</item>
103108

104109
<item name="colorMaterial100">@color/material_pink_100</item>
105110
<item name="colorMaterial300">@color/material_pink_300</item>
@@ -187,7 +192,24 @@
187192
<item name="rippleColor">@color/chip_ripple_color</item>
188193
</style>
189194

190-
<style name="Widget.SagerNet.CardView" parent="Widget.Material3.CardView.Filled">
195+
<style name="Widget.SagerNet.BottomAppBar" parent="Widget.Material3.BottomAppBar">
196+
<item name="backgroundTint">?attr/colorPrimary</item>
197+
<item name="fabAlignmentMode">center</item>
198+
<item name="fabAlignmentModeEndMargin">@null</item>
199+
<item name="fabAnchorMode">cradle</item>
200+
<item name="menuAlignmentMode">auto</item>
201+
<item name="removeEmbeddedFabElevation">false</item>
202+
</style>
203+
204+
<style name="Widget.SagerNet.FloatingActionButton" parent="Widget.Material3.FloatingActionButton.Primary">
205+
<item name="backgroundTint">?attr/fabColorBackground</item>
206+
<item name="tint">?attr/colorOnPrimary</item>
207+
</style>
208+
209+
<!-- Use the Material 3 *Outlined* card as the base so M3's surface-tint elevation
210+
overlay is not applied; the app sets its own card background/stroke colors and an
211+
olive tint was bleeding through Filled cards on the custom (non-M3-role) themes. -->
212+
<style name="Widget.SagerNet.CardView" parent="Widget.Material3.CardView.Outlined">
191213
<item name="cardElevation">0dp</item>
192214
<item name="cardCornerRadius">@dimen/card_corner_radius</item>
193215
<item name="strokeColor">@color/card_stroke</item>
@@ -273,6 +295,7 @@
273295
<item name="colorPrimary">@color/material_amber_500</item>
274296
<item name="colorPrimaryDark">@color/material_amber_700</item>
275297
<item name="colorAccent">@color/material_amber_accent_200</item>
298+
<item name="colorOnPrimary">@color/black</item>
276299
<item name="colorMaterial100">@color/material_amber_100</item>
277300
<item name="colorMaterial300">@color/material_amber_300</item>
278301
<item name="cardElevatedSurfaceColor">@color/card_elevated_amber</item>
@@ -381,6 +404,7 @@
381404
<item name="colorPrimary">@color/material_lime_500</item>
382405
<item name="colorPrimaryDark">@color/material_lime_700</item>
383406
<item name="colorAccent">@color/material_lime_accent_200</item>
407+
<item name="colorOnPrimary">@color/black</item>
384408
<item name="colorMaterial100">@color/material_lime_100</item>
385409
<item name="colorMaterial300">@color/material_lime_300</item>
386410
<item name="cardElevatedSurfaceColor">@color/card_elevated_lime</item>
@@ -426,6 +450,7 @@
426450
<item name="colorPrimary">@color/material_yellow_500</item>
427451
<item name="colorPrimaryDark">@color/material_yellow_700</item>
428452
<item name="colorAccent">@color/material_yellow_accent_200</item>
453+
<item name="colorOnPrimary">@color/black</item>
429454
<item name="colorMaterial100">@color/material_yellow_100</item>
430455
<item name="colorMaterial300">@color/material_yellow_300</item>
431456
<item name="cardElevatedSurfaceColor">@color/card_elevated_yellow</item>
@@ -436,6 +461,7 @@
436461
<item name="colorPrimary">@color/material_amber_500</item>
437462
<item name="colorPrimaryDark">@color/material_amber_700</item>
438463
<item name="colorAccent">@color/material_amber_accent_200</item>
464+
<item name="colorOnPrimary">@color/black</item>
439465
<item name="colorMaterial100">@color/material_amber_100</item>
440466
<item name="colorMaterial300">@color/material_amber_300</item>
441467
<item name="cardElevatedSurfaceColor">@color/card_elevated_amber</item>
@@ -544,6 +570,7 @@
544570
<item name="colorPrimary">@color/material_lime_500</item>
545571
<item name="colorPrimaryDark">@color/material_lime_700</item>
546572
<item name="colorAccent">@color/material_lime_accent_200</item>
573+
<item name="colorOnPrimary">@color/black</item>
547574
<item name="colorMaterial100">@color/material_lime_100</item>
548575
<item name="colorMaterial300">@color/material_lime_300</item>
549576
<item name="cardElevatedSurfaceColor">@color/card_elevated_lime</item>
@@ -598,6 +625,7 @@
598625
<item name="colorPrimary">@color/material_yellow_500</item>
599626
<item name="colorPrimaryDark">@color/material_yellow_700</item>
600627
<item name="colorAccent">@color/material_yellow_accent_200</item>
628+
<item name="colorOnPrimary">@color/black</item>
601629
<item name="colorMaterial100">@color/material_yellow_100</item>
602630
<item name="colorMaterial300">@color/material_yellow_300</item>
603631
<item name="cardElevatedSurfaceColor">@color/card_elevated_yellow</item>

0 commit comments

Comments
 (0)