Skip to content

Commit 8c5ec0d

Browse files
committed
Switch theme choosing out of the preferences into the main menu
Includes fixes using dynamic colors.
1 parent 9eff651 commit 8c5ec0d

27 files changed

Lines changed: 359 additions & 70 deletions

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
### Changed
1313

14+
* Moved UI for theme switching from preferences screen to the main menu. Just open the burger menu
15+
and find the button straight on top.
16+
1417
### Deprecated
1518

1619
### Removed
@@ -19,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1922

2023
### Fixed
2124

25+
* Fix theme switching if either the old or the new theme is the dynamic theme from Material You.
26+
2227
### Security
2328

2429
## [0.32.0] - 2024-11-10

gauguin-app/src/main/kotlin/org/piepmeyer/gauguin/ui/ActivityUtils.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.view.WindowManager
55
import androidx.appcompat.app.AppCompatDelegate
66
import org.koin.core.component.KoinComponent
77
import org.koin.core.component.inject
8+
import org.piepmeyer.gauguin.R
89
import org.piepmeyer.gauguin.Theme
910
import org.piepmeyer.gauguin.preferences.ApplicationPreferences
1011

@@ -28,20 +29,19 @@ class ActivityUtils : KoinComponent {
2829
}
2930
}
3031

31-
fun configureNightMode() {
32+
fun configureTheme(activity: Activity) {
3233
when (applicationPreferences.theme) {
3334
Theme.LIGHT -> {
35+
activity.setTheme(R.style.AppTheme)
3436
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
3537
}
3638
Theme.DARK -> {
39+
activity.setTheme(R.style.AppTheme)
3740
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
3841
}
39-
Theme.SYSTEM_DEFAULT -> {
42+
Theme.SYSTEM_DEFAULT, Theme.DYNAMIC_COLORS -> {
4043
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
4144
}
42-
else -> {
43-
// Means usage of dynamic colors, in this case we do not have to set any mode by hand
44-
}
4545
}
4646
}
4747
}

gauguin-app/src/main/kotlin/org/piepmeyer/gauguin/ui/LoadGameListActivity.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class LoadGameListActivity : AppCompatActivity() {
2929
setContentView(R.layout.activity_savegame)
3030

3131
val recyclerView = findViewById<RecyclerView>(android.R.id.list)
32+
33+
activityUtils.configureTheme(this)
3234
activityUtils.configureFullscreen(this)
3335

3436
empty = findViewById(android.R.id.empty)
@@ -110,8 +112,7 @@ class LoadGameListActivity : AppCompatActivity() {
110112
deleteSaveGame(
111113
filename,
112114
)
113-
}
114-
.show()
115+
}.show()
115116
}
116117

117118
private fun deleteAllGamesDialog() {

gauguin-app/src/main/kotlin/org/piepmeyer/gauguin/ui/grid/GridPaintHolder.kt

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.piepmeyer.gauguin.ui.grid
22

3+
import android.content.Context
34
import android.graphics.Paint
45
import androidx.core.graphics.ColorUtils
56
import com.google.android.material.color.MaterialColors
@@ -9,6 +10,7 @@ import org.piepmeyer.gauguin.grid.GridCell
910

1011
class GridPaintHolder(
1112
gridUI: GridUI,
13+
context: Context,
1214
) {
1315
private val backgroundPaint: Paint = Paint()
1416

@@ -46,20 +48,20 @@ class GridPaintHolder(
4648
private val previewTextPaint: Paint = Paint()
4749

4850
init {
49-
val fontHolder = GridFontHolder(gridUI.context)
51+
val fontHolder = GridFontHolder(context)
5052

51-
backgroundPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorSurface)
53+
backgroundPaint.color = getColor(context, com.google.android.material.R.attr.colorSurface)
5254
backgroundPaint.style = Paint.Style.FILL
5355

5456
borderPaint.strokeWidth = 2f
5557
borderPaint.style = Paint.Style.STROKE
56-
borderPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorSecondary)
58+
borderPaint.color = getColor(context, com.google.android.material.R.attr.colorSecondary)
5759

5860
gridPaint.flags = Paint.ANTI_ALIAS_FLAG
5961
gridPaint.color =
6062
ColorUtils.blendARGB(
61-
gridUI.resources.getColor(R.color.gridCage, null),
62-
MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorSurface),
63+
getColor(context, R.attr.colorGridCage),
64+
getColor(context, com.google.android.material.R.attr.colorSurface),
6365
if (gridUI.isInEditMode) {
6466
0.0f
6567
} else {
@@ -72,24 +74,24 @@ class GridPaintHolder(
7274
selectedGridPaint = Paint(gridPaint)
7375
selectedGridPaint.color =
7476
ColorUtils.blendARGB(
75-
MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorSecondary),
76-
MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorSurface),
77+
getColor(context, com.google.android.material.R.attr.colorSecondary),
78+
getColor(context, com.google.android.material.R.attr.colorSurface),
7779
0.1f,
7880
)
7981

8082
warningGridPaint = Paint(gridPaint)
81-
warningGridPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorError)
83+
warningGridPaint.color = getColor(context, com.google.android.material.R.attr.colorError)
8284

8385
innerGridPaint.flags = Paint.ANTI_ALIAS_FLAG
8486
innerGridPaint.color = gridPaint.color
8587

8688
cageSelectedPaint.flags = Paint.ANTI_ALIAS_FLAG
8789
cageSelectedPaint.style = Paint.Style.STROKE
88-
cageSelectedPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorOnBackground)
90+
cageSelectedPaint.color = getColor(context, com.google.android.material.R.attr.colorOnBackground)
8991
cageSelectedPaint.typeface = fontHolder.fontValue
9092

9193
cageTextPaint.flags = Paint.ANTI_ALIAS_FLAG
92-
cageTextPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorPrimary)
94+
cageTextPaint.color = getColor(context, com.google.android.material.R.attr.colorPrimary)
9395
cageTextPaint.typeface = fontHolder.fontCageText
9496

9597
val hsl = FloatArray(3)
@@ -100,66 +102,66 @@ class GridPaintHolder(
100102
cageTextPreviewModePaint.typeface = fontHolder.fontCageText
101103

102104
cageTextSelectedPaint.flags = Paint.ANTI_ALIAS_FLAG
103-
cageTextSelectedPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorPrimary)
105+
cageTextSelectedPaint.color = getColor(context, com.google.android.material.R.attr.colorPrimary)
104106
cageTextSelectedPaint.typeface = fontHolder.fontCageText
105107
cageTextSelectedFastFinishModePaint.flags = Paint.ANTI_ALIAS_FLAG
106-
cageTextSelectedFastFinishModePaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorSurface)
108+
cageTextSelectedFastFinishModePaint.color = getColor(context, com.google.android.material.R.attr.colorSurface)
107109
cageTextSelectedFastFinishModePaint.typeface = fontHolder.fontCageText
108110

109111
valuePaint.flags = Paint.ANTI_ALIAS_FLAG
110-
valuePaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorOnBackground)
112+
valuePaint.color = getColor(context, com.google.android.material.R.attr.colorOnBackground)
111113
valuePaint.typeface = fontHolder.fontValue
112114

113115
valueSelectedPaint.flags = Paint.ANTI_ALIAS_FLAG
114-
valueSelectedPaint.color = gridUI.resources.getColor(R.color.gridSelected, null)
116+
valueSelectedPaint.color = getColor(context, R.attr.colorGridSelected)
115117
valueSelectedPaint.typeface = fontHolder.fontValue
116118
valueSelectedFastFinishModePaint.flags = Paint.ANTI_ALIAS_FLAG
117-
valueSelectedFastFinishModePaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorSurface)
119+
valueSelectedFastFinishModePaint.color = getColor(context, com.google.android.material.R.attr.colorSurface)
118120
valueSelectedFastFinishModePaint.typeface = fontHolder.fontValue
119121

120122
possiblesPaint.flags = Paint.ANTI_ALIAS_FLAG
121-
possiblesPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorOnBackground)
123+
possiblesPaint.color = getColor(context, com.google.android.material.R.attr.colorOnBackground)
122124
possiblesPaint.typeface = fontHolder.fontPossibles
123125

124126
possiblesSelectedPaint.flags = Paint.ANTI_ALIAS_FLAG
125127
possiblesSelectedPaint.textSize = 6f
126-
possiblesSelectedPaint.color = gridUI.resources.getColor(R.color.gridSelected, null)
128+
possiblesSelectedPaint.color = getColor(context, R.attr.colorGridSelected)
127129
possiblesSelectedPaint.typeface = fontHolder.fontPossibles
128130
possiblesSelectedFastFinishModePaint.flags = Paint.ANTI_ALIAS_FLAG
129131
possiblesSelectedFastFinishModePaint.textSize = 6f
130-
possiblesSelectedFastFinishModePaint.color = gridUI.resources.getColor(R.color.gridSelectedText, null)
132+
possiblesSelectedFastFinishModePaint.color = getColor(context, R.attr.colorGridSelectedText)
131133
possiblesSelectedFastFinishModePaint.typeface = fontHolder.fontPossibles
132134

133135
previewTextPaint.flags = Paint.ANTI_ALIAS_FLAG
134136
previewTextPaint.textSize = 6f
135-
previewTextPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorOnTertiaryContainer)
137+
previewTextPaint.color = getColor(context, com.google.android.material.R.attr.colorOnTertiaryContainer)
136138
previewTextPaint.typeface = fontHolder.fontPossibles
137139

138-
previewPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorTertiaryContainer)
140+
previewPaint.color = getColor(context, com.google.android.material.R.attr.colorTertiaryContainer)
139141

140142
selectedPaint.flags = Paint.ANTI_ALIAS_FLAG
141-
selectedPaint.color = gridUI.resources.getColor(R.color.gridSelected, null)
143+
selectedPaint.color = getColor(context, R.attr.colorGridSelected)
142144
selectedPaint.style = Paint.Style.STROKE
143145

144146
selectedFastFinishModePaint.flags = Paint.ANTI_ALIAS_FLAG
145-
selectedFastFinishModePaint.color = gridUI.resources.getColor(R.color.gridSelected, null)
147+
selectedFastFinishModePaint.color = getColor(context, R.attr.colorGridSelected)
146148
selectedFastFinishModePaint.style = Paint.Style.FILL_AND_STROKE
147149
textOnSelectedFastFinishModePaint.flags = Paint.ANTI_ALIAS_FLAG
148-
textOnSelectedFastFinishModePaint.color = gridUI.resources.getColor(R.color.gridSelectedText, null)
150+
textOnSelectedFastFinishModePaint.color = getColor(context, R.attr.colorGridSelectedText)
149151

150152
lastModifiedPaint.color =
151153
ColorUtils.blendARGB(
152-
gridUI.resources.getColor(R.color.gridSelected, null),
153-
MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorSurface),
154+
getColor(context, R.attr.colorGridSelected),
155+
getColor(context, com.google.android.material.R.attr.colorSurface),
154156
0.5f,
155157
)
156158
lastModifiedPaint.style = Paint.Style.STROKE
157159
lastModifiedPaint.flags = Paint.ANTI_ALIAS_FLAG
158160

159-
warningTextPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorError)
161+
warningTextPaint.color = getColor(context, com.google.android.material.R.attr.colorError)
160162
warningTextPaint.typeface = fontHolder.fontValue
161163

162-
cheatedPaint.color = MaterialColors.getColor(gridUI, com.google.android.material.R.attr.colorSurfaceVariant)
164+
cheatedPaint.color = getColor(context, com.google.android.material.R.attr.colorSurfaceVariant)
163165

164166
errorBackgroundPaint.color =
165167
MaterialColors.compositeARGBWithAlpha(
@@ -232,4 +234,11 @@ class GridPaintHolder(
232234
fun gridPaint(): Paint = gridPaint
233235

234236
fun selectedGridPaint(): Paint = selectedGridPaint
237+
238+
companion object {
239+
fun getColor(
240+
context: Context,
241+
colorId: Int,
242+
): Int = MaterialColors.getColor(context, colorId, "ups")
243+
}
235244
}

gauguin-app/src/main/kotlin/org/piepmeyer/gauguin/ui/grid/GridUI.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.util.AttributeSet
77
import android.view.MotionEvent
88
import android.view.View
99
import android.view.View.OnTouchListener
10+
import com.google.android.material.color.MaterialColors
1011
import org.koin.core.component.KoinComponent
1112
import org.piepmeyer.gauguin.R
1213
import org.piepmeyer.gauguin.grid.Grid
@@ -47,7 +48,7 @@ class GridUI :
4748
updatePadding()
4849
}
4950

50-
private val paintHolder = GridPaintHolder(this)
51+
private var paintHolder = GridPaintHolder(this, context)
5152
var isPreviewMode = false
5253
private var previewStillCalculating = false
5354
private var maximumCellSizeInDP = gridUiInjectionStrategy.maximumCellSizeInDP()
@@ -77,6 +78,9 @@ class GridUI :
7778
}
7879

7980
fun updateTheme() {
81+
paintHolder = GridPaintHolder(this, context)
82+
rebuildCellsFromGrid()
83+
8084
this.invalidate()
8185
}
8286

gauguin-app/src/main/kotlin/org/piepmeyer/gauguin/ui/main/FerrisWheelConfigurer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class FerrisWheelConfigurer(
5959
listOf(
6060
cabin(com.google.android.material.R.attr.colorPrimaryVariant),
6161
cabin(com.google.android.material.R.attr.colorSecondaryVariant),
62-
cabinFromColor(R.color.gridSelected),
62+
cabin(R.attr.colorGridSelected),
6363
)
6464

6565
private fun cabinColorsLight(): List<CabinStyle> =

gauguin-app/src/main/kotlin/org/piepmeyer/gauguin/ui/main/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ class MainActivity : AppCompatActivity() {
209209
}
210210

211211
private fun configureActivity() {
212-
activityUtils.configureNightMode()
212+
activityUtils.configureTheme(this)
213213
activityUtils.configureKeepScreenOn(this)
214214
activityUtils.configureFullscreen(this)
215215

gauguin-app/src/main/kotlin/org/piepmeyer/gauguin/ui/main/MainNavigationViewService.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.content.Intent
44
import android.net.Uri
55
import android.view.View
66
import android.view.ViewGroup
7+
import android.widget.Button
78
import androidx.appcompat.view.ContextThemeWrapper
89
import androidx.core.view.marginStart
910
import androidx.core.view.updateLayoutParams
@@ -160,6 +161,16 @@ class MainNavigationViewService(
160161
binding.gridview.addOnLayoutChangeListener { _, _, _, right, _, _, _, _, _ ->
161162
updateMainBottomBarMargins(right)
162163
}
164+
165+
binding.mainNavigationView.findViewById<Button>(R.id.navigation_drawer_choose_theme).setOnClickListener {
166+
ThemeChooserBalloon(mainActivity).showBalloon(
167+
baseView = it,
168+
inflater = mainActivity.layoutInflater,
169+
parent = binding.mainNavigationView,
170+
lifecycleOwner = mainActivity,
171+
anchorView = it,
172+
)
173+
}
163174
}
164175

165176
fun updateMainBottomBarMargins() {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.piepmeyer.gauguin.ui.main
2+
3+
import android.app.Activity
4+
import android.view.LayoutInflater
5+
import android.view.View
6+
import android.view.ViewGroup
7+
import androidx.lifecycle.LifecycleOwner
8+
import com.google.android.material.color.MaterialColors
9+
import com.skydoves.balloon.ArrowPositionRules
10+
import com.skydoves.balloon.BalloonAnimation
11+
import com.skydoves.balloon.BalloonSizeSpec
12+
import com.skydoves.balloon.createBalloon
13+
14+
class ThemeChooserBalloon(
15+
private val mainActivity: Activity,
16+
) {
17+
fun showBalloon(
18+
baseView: View,
19+
inflater: LayoutInflater,
20+
parent: ViewGroup,
21+
lifecycleOwner: LifecycleOwner,
22+
anchorView: View,
23+
) {
24+
val fragment = ThemeChooserFragment(mainActivity)
25+
26+
val view = fragment.onCreateView(inflater, parent, null)
27+
28+
val balloon =
29+
createBalloon(baseView.context) {
30+
setLayout(view)
31+
setWidth(BalloonSizeSpec.WRAP)
32+
setHeight(BalloonSizeSpec.WRAP)
33+
setBackgroundColor(
34+
MaterialColors.getColor(baseView, com.google.android.material.R.attr.colorSecondary),
35+
)
36+
setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR)
37+
setArrowSize(10)
38+
setArrowPosition(0.5f)
39+
setPadding(8)
40+
paddingBottom = 16
41+
setCornerRadius(8f)
42+
setBalloonAnimation(BalloonAnimation.FADE)
43+
44+
setLifecycleOwner(lifecycleOwner)
45+
46+
build()
47+
}
48+
49+
balloon.showAlignBottom(anchorView)
50+
}
51+
}

0 commit comments

Comments
 (0)