refactor: add dynamic font scaling support and integrate ProvideDynamicTypeFontScale across modules
This commit is contained in:
1 parent
df38936893
commit
abeb484258
12 files changed
+172
-30
No files matched your search
@@ -1,9 +1,18 @@
|
||||
plugins {
|
||||
id("gwenedeg.kmp.library")
|
||||
id("gwenedeg.compose")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
androidLibrary {
|
||||
namespace = "bzh.ajaury.chombev.core.accessibility"
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
// UI - Compose
|
||||
implementation(libs.compose.runtime)
|
||||
implementation(libs.compose.ui)
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package bzh.ajaury.chombev.core.accessibility.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
/** No-op: the font scale already follows the system setting. */
|
||||
@Composable
|
||||
actual fun ProvideDynamicTypeFontScale(content: @Composable () -> Unit) = content()
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package bzh.ajaury.chombev.core.accessibility.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
/**
|
||||
* Applies the system text size to [content] as soon as the user changes it.
|
||||
*
|
||||
* Only needed on iOS, see its implementation. Every Compose scene must be wrapped: the root one
|
||||
* and each dialog or bottom sheet, which iOS renders in a scene of its own that does not inherit
|
||||
* the font scale provided by the root one.
|
||||
*/
|
||||
@Composable
|
||||
expect fun ProvideDynamicTypeFontScale(content: @Composable () -> Unit)
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package bzh.ajaury.chombev.core.accessibility.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Density
|
||||
import platform.Foundation.NSNotificationCenter
|
||||
import platform.Foundation.NSOperationQueue
|
||||
import platform.UIKit.UIApplication
|
||||
import platform.UIKit.UIContentSizeCategoryAccessibilityExtraExtraExtraLarge
|
||||
import platform.UIKit.UIContentSizeCategoryAccessibilityExtraExtraLarge
|
||||
import platform.UIKit.UIContentSizeCategoryAccessibilityExtraLarge
|
||||
import platform.UIKit.UIContentSizeCategoryAccessibilityLarge
|
||||
import platform.UIKit.UIContentSizeCategoryAccessibilityMedium
|
||||
import platform.UIKit.UIContentSizeCategoryDidChangeNotification
|
||||
import platform.UIKit.UIContentSizeCategoryExtraExtraExtraLarge
|
||||
import platform.UIKit.UIContentSizeCategoryExtraExtraLarge
|
||||
import platform.UIKit.UIContentSizeCategoryExtraLarge
|
||||
import platform.UIKit.UIContentSizeCategoryExtraSmall
|
||||
import platform.UIKit.UIContentSizeCategoryLarge
|
||||
import platform.UIKit.UIContentSizeCategoryMedium
|
||||
import platform.UIKit.UIContentSizeCategorySmall
|
||||
|
||||
/**
|
||||
* Applies the system text size (Dynamic Type) to [content] as soon as the user changes it.
|
||||
*
|
||||
* Compose Multiplatform reads the font scale once, when the Compose scene is created, so a change
|
||||
* made in the iOS settings only shows once the scene is created again: after the app restarts for
|
||||
* the root scene, or when it is opened again for a dialog or bottom sheet. Workaround for CMP-10365
|
||||
* (https://youtrack.jetbrains.com/issue/CMP-10365), fixed in Compose Multiplatform 1.13.0: remove
|
||||
* it once the project is upgraded.
|
||||
*/
|
||||
@Composable
|
||||
actual fun ProvideDynamicTypeFontScale(content: @Composable () -> Unit) {
|
||||
var contentSizeCategory by remember {
|
||||
mutableStateOf(UIApplication.sharedApplication.preferredContentSizeCategory)
|
||||
}
|
||||
|
||||
DisposableEffect(Unit) {
|
||||
val notificationCenter = NSNotificationCenter.defaultCenter
|
||||
val observer = notificationCenter.addObserverForName(
|
||||
name = UIContentSizeCategoryDidChangeNotification,
|
||||
`object` = null,
|
||||
queue = NSOperationQueue.mainQueue,
|
||||
) { _ ->
|
||||
contentSizeCategory = UIApplication.sharedApplication.preferredContentSizeCategory
|
||||
}
|
||||
onDispose { notificationCenter.removeObserver(observer) }
|
||||
}
|
||||
|
||||
val density = LocalDensity.current
|
||||
// Only the font scale is overridden: the pixel density stays the one Compose computed.
|
||||
val fontScale = contentSizeCategoryToFontScale[contentSizeCategory] ?: density.fontScale
|
||||
CompositionLocalProvider(
|
||||
LocalDensity provides Density(density = density.density, fontScale = fontScale),
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
// Same mapping as Compose Multiplatform (`uiContentSizeCategoryToFontScaleMap`, which is private),
|
||||
// so that the font scale matches the one Compose computes when the scene is created.
|
||||
private val contentSizeCategoryToFontScale = mapOf(
|
||||
UIContentSizeCategoryExtraSmall to 0.8f,
|
||||
UIContentSizeCategorySmall to 0.85f,
|
||||
UIContentSizeCategoryMedium to 0.9f,
|
||||
UIContentSizeCategoryLarge to 1f,
|
||||
UIContentSizeCategoryExtraLarge to 1.1f,
|
||||
UIContentSizeCategoryExtraExtraLarge to 1.2f,
|
||||
UIContentSizeCategoryExtraExtraExtraLarge to 1.3f,
|
||||
UIContentSizeCategoryAccessibilityMedium to 1.4f,
|
||||
UIContentSizeCategoryAccessibilityLarge to 1.5f,
|
||||
UIContentSizeCategoryAccessibilityExtraLarge to 1.6f,
|
||||
UIContentSizeCategoryAccessibilityExtraExtraLarge to 1.7f,
|
||||
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge to 1.8f,
|
||||
)
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package bzh.ajaury.chombev.core.accessibility.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
/** No-op: the font scale already follows the system setting. */
|
||||
@Composable
|
||||
actual fun ProvideDynamicTypeFontScale(content: @Composable () -> Unit) = content()
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package bzh.ajaury.chombev.core.accessibility.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
/** No-op: the font scale already follows the system setting. */
|
||||
@Composable
|
||||
actual fun ProvideDynamicTypeFontScale(content: @Composable () -> Unit) = content()
|
||||
Reference in new issue
Block a user