Modifier.kt 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package eu.kanade.presentation.util
  2. import androidx.compose.foundation.background
  3. import androidx.compose.foundation.combinedClickable
  4. import androidx.compose.foundation.interaction.MutableInteractionSource
  5. import androidx.compose.foundation.isSystemInDarkTheme
  6. import androidx.compose.material3.LocalMinimumTouchTargetEnforcement
  7. import androidx.compose.material3.MaterialTheme
  8. import androidx.compose.runtime.remember
  9. import androidx.compose.ui.Modifier
  10. import androidx.compose.ui.composed
  11. import androidx.compose.ui.draw.alpha
  12. import androidx.compose.ui.input.key.Key
  13. import androidx.compose.ui.input.key.key
  14. import androidx.compose.ui.input.key.onPreviewKeyEvent
  15. import androidx.compose.ui.layout.LayoutModifier
  16. import androidx.compose.ui.layout.Measurable
  17. import androidx.compose.ui.layout.MeasureResult
  18. import androidx.compose.ui.layout.MeasureScope
  19. import androidx.compose.ui.platform.LocalViewConfiguration
  20. import androidx.compose.ui.platform.debugInspectorInfo
  21. import androidx.compose.ui.unit.Constraints
  22. import androidx.compose.ui.unit.DpSize
  23. import kotlin.math.roundToInt
  24. fun Modifier.selectedBackground(isSelected: Boolean): Modifier = composed {
  25. if (isSelected) {
  26. val alpha = if (isSystemInDarkTheme()) 0.16f else 0.22f
  27. background(MaterialTheme.colorScheme.secondary.copy(alpha = alpha))
  28. } else {
  29. this
  30. }
  31. }
  32. fun Modifier.secondaryItemAlpha(): Modifier = this.alpha(SecondaryItemAlpha)
  33. fun Modifier.clickableNoIndication(
  34. onLongClick: (() -> Unit)? = null,
  35. onClick: () -> Unit,
  36. ): Modifier = composed {
  37. this.combinedClickable(
  38. interactionSource = remember { MutableInteractionSource() },
  39. indication = null,
  40. onLongClick = onLongClick,
  41. onClick = onClick,
  42. )
  43. }
  44. /**
  45. * For TextField, the provided [action] will be invoked when
  46. * physical enter key is pressed.
  47. *
  48. * Naturally, the TextField should be set to single line only.
  49. */
  50. fun Modifier.runOnEnterKeyPressed(action: () -> Unit): Modifier = this.onPreviewKeyEvent {
  51. when (it.key) {
  52. Key.Enter, Key.NumPadEnter -> {
  53. action()
  54. true
  55. }
  56. else -> false
  57. }
  58. }
  59. @Suppress("ModifierInspectorInfo")
  60. fun Modifier.minimumTouchTargetSize(): Modifier = composed(
  61. inspectorInfo = debugInspectorInfo {
  62. name = "minimumTouchTargetSize"
  63. properties["README"] = "Adds outer padding to measure at least 48.dp (default) in " +
  64. "size to disambiguate touch interactions if the element would measure smaller"
  65. },
  66. ) {
  67. if (LocalMinimumTouchTargetEnforcement.current) {
  68. val size = LocalViewConfiguration.current.minimumTouchTargetSize
  69. MinimumTouchTargetModifier(size)
  70. } else {
  71. Modifier
  72. }
  73. }
  74. private class MinimumTouchTargetModifier(val size: DpSize) : LayoutModifier {
  75. override fun MeasureScope.measure(
  76. measurable: Measurable,
  77. constraints: Constraints,
  78. ): MeasureResult {
  79. val placeable = measurable.measure(constraints)
  80. // Be at least as big as the minimum dimension in both dimensions
  81. val width = maxOf(placeable.width, size.width.roundToPx())
  82. val height = maxOf(placeable.height, size.height.roundToPx())
  83. return layout(width, height) {
  84. val centerX = ((width - placeable.width) / 2f).roundToInt()
  85. val centerY = ((height - placeable.height) / 2f).roundToInt()
  86. placeable.place(centerX, centerY)
  87. }
  88. }
  89. override fun equals(other: Any?): Boolean {
  90. val otherModifier = other as? MinimumTouchTargetModifier ?: return false
  91. return size == otherModifier.size
  92. }
  93. override fun hashCode(): Int {
  94. return size.hashCode()
  95. }
  96. }