mirror of
https://github.com/BetterAndroid/FlexiUI.git
synced 2025-09-08 11:34:18 +08:00
feat: add Interaction and move ripple effect with name "rippleColor"
This commit is contained in:
@@ -25,14 +25,11 @@ package com.highcapable.flexiui.component
|
|||||||
|
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.selection.toggleable
|
|
||||||
import androidx.compose.material.ripple.rememberRipple
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
@@ -49,12 +46,14 @@ import androidx.compose.ui.unit.Dp
|
|||||||
import com.highcapable.flexiui.LocalColors
|
import com.highcapable.flexiui.LocalColors
|
||||||
import com.highcapable.flexiui.LocalShapes
|
import com.highcapable.flexiui.LocalShapes
|
||||||
import com.highcapable.flexiui.LocalSizes
|
import com.highcapable.flexiui.LocalSizes
|
||||||
|
import com.highcapable.flexiui.interaction.rippleClickable
|
||||||
|
import com.highcapable.flexiui.interaction.rippleToggleable
|
||||||
import com.highcapable.flexiui.utils.borderOrNot
|
import com.highcapable.flexiui.utils.borderOrNot
|
||||||
import com.highcapable.flexiui.utils.orElse
|
import com.highcapable.flexiui.utils.orElse
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class ButtonColors(
|
data class ButtonColors(
|
||||||
val fillColor: Color,
|
val rippleColor: Color,
|
||||||
val contentColor: Color,
|
val contentColor: Color,
|
||||||
val backgroundColor: Color
|
val backgroundColor: Color
|
||||||
)
|
)
|
||||||
@@ -78,12 +77,12 @@ fun Button(
|
|||||||
content: @Composable RowScope.() -> Unit
|
content: @Composable RowScope.() -> Unit
|
||||||
) {
|
) {
|
||||||
var sModifier = modifier.clip(shape = shape)
|
var sModifier = modifier.clip(shape = shape)
|
||||||
sModifier = if (enabled) sModifier.clickable(
|
sModifier = if (enabled) sModifier.rippleClickable(
|
||||||
onClick = onClick,
|
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
role = Role.Button,
|
role = Role.Button,
|
||||||
indication = rememberRipple(color = colors.fillColor),
|
rippleColor = colors.rippleColor,
|
||||||
interactionSource = interactionSource
|
interactionSource = interactionSource,
|
||||||
|
onClick = onClick
|
||||||
) else sModifier.alpha(0.5f)
|
) else sModifier.alpha(0.5f)
|
||||||
sModifier = sModifier.background(color = colors.backgroundColor, shape = shape)
|
sModifier = sModifier.background(color = colors.backgroundColor, shape = shape)
|
||||||
sModifier = sModifier.borderOrNot(border = border, shape = shape)
|
sModifier = sModifier.borderOrNot(border = border, shape = shape)
|
||||||
@@ -117,18 +116,19 @@ fun Button(
|
|||||||
fun IconButton(
|
fun IconButton(
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
fillColor: Color = Button.colors.fillColor,
|
rippleColor: Color = Button.colors.rippleColor,
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier.clickable(
|
modifier = modifier.rippleClickable(
|
||||||
onClick = onClick,
|
rippleColor = rippleColor,
|
||||||
|
bounded = false,
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
role = Role.Button,
|
role = Role.Button,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
indication = rememberRipple(bounded = false, color = fillColor)
|
onClick = onClick
|
||||||
),
|
),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) { content() }
|
) { content() }
|
||||||
@@ -139,19 +139,20 @@ fun IconToggleButton(
|
|||||||
checked: Boolean,
|
checked: Boolean,
|
||||||
onCheckedChange: (Boolean) -> Unit,
|
onCheckedChange: (Boolean) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
fillColor: Color = Button.colors.fillColor,
|
rippleColor: Color = Button.colors.rippleColor,
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier.toggleable(
|
modifier = modifier.rippleToggleable(
|
||||||
value = checked,
|
value = checked,
|
||||||
|
rippleColor = rippleColor,
|
||||||
|
bounded = false,
|
||||||
onValueChange = onCheckedChange,
|
onValueChange = onCheckedChange,
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
role = Role.Checkbox,
|
role = Role.Checkbox,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource
|
||||||
indication = rememberRipple(bounded = false, color = fillColor)
|
|
||||||
),
|
),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) { content() }
|
) { content() }
|
||||||
@@ -214,7 +215,7 @@ private fun defaultButtonShape() = LocalShapes.current.tertiary
|
|||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
private fun defaultButtonInBoxColors() = ButtonColors(
|
private fun defaultButtonInBoxColors() = ButtonColors(
|
||||||
fillColor = LocalColors.current.themeSecondary,
|
rippleColor = LocalColors.current.themeSecondary,
|
||||||
contentColor = LocalColors.current.textPrimary,
|
contentColor = LocalColors.current.textPrimary,
|
||||||
backgroundColor = LocalColors.current.foregroundSecondary
|
backgroundColor = LocalColors.current.foregroundSecondary
|
||||||
)
|
)
|
||||||
@@ -222,7 +223,7 @@ private fun defaultButtonInBoxColors() = ButtonColors(
|
|||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
private fun defaultButtonOutBoxColors() = ButtonColors(
|
private fun defaultButtonOutBoxColors() = ButtonColors(
|
||||||
fillColor = LocalColors.current.foregroundSecondary,
|
rippleColor = LocalColors.current.foregroundSecondary,
|
||||||
contentColor = Color.White,
|
contentColor = Color.White,
|
||||||
backgroundColor = LocalColors.current.themePrimary
|
backgroundColor = LocalColors.current.themePrimary
|
||||||
)
|
)
|
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Flexi UI - A flexible and useful UI component library.
|
||||||
|
* Copyright (C) 2019-2023 HighCapable
|
||||||
|
* https://github.com/BetterAndroid/FlexiUI
|
||||||
|
*
|
||||||
|
* Apache License Version 2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* This file is created by fankes on 2023/11/10.
|
||||||
|
*/
|
||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package com.highcapable.flexiui.interaction
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Indication
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.material.ripple.rememberRipple
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.semantics.Role
|
||||||
|
import com.highcapable.flexiui.LocalColors
|
||||||
|
import androidx.compose.foundation.clickable as foundationClickable
|
||||||
|
import androidx.compose.foundation.selection.toggleable as foundationToggleable
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Modifier.clickable(
|
||||||
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
|
indication: Indication? = null,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
onClickLabel: String? = null,
|
||||||
|
role: Role? = null,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) = foundationClickable(interactionSource, indication, enabled, onClickLabel, role, onClick)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Modifier.toggleable(
|
||||||
|
value: Boolean,
|
||||||
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
|
indication: Indication? = null,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
role: Role? = null,
|
||||||
|
onValueChange: (Boolean) -> Unit
|
||||||
|
) = foundationToggleable(value, interactionSource, indication, enabled, role, onValueChange)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Modifier.rippleClickable(
|
||||||
|
rippleColor: Color = Interaction.rippleColor,
|
||||||
|
bounded: Boolean = true,
|
||||||
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
|
enabled: Boolean = true,
|
||||||
|
onClickLabel: String? = null,
|
||||||
|
role: Role? = null,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) = clickable(
|
||||||
|
onClick = onClick,
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
indication = rememberRipple(bounded = bounded, color = rippleColor),
|
||||||
|
enabled = enabled,
|
||||||
|
onClickLabel = onClickLabel,
|
||||||
|
role = role
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Modifier.rippleToggleable(
|
||||||
|
value: Boolean,
|
||||||
|
rippleColor: Color = Interaction.rippleColor,
|
||||||
|
bounded: Boolean = true,
|
||||||
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
|
enabled: Boolean = true,
|
||||||
|
role: Role? = null,
|
||||||
|
onValueChange: (Boolean) -> Unit
|
||||||
|
) = toggleable(
|
||||||
|
value = value,
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
indication = rememberRipple(bounded = bounded, color = rippleColor),
|
||||||
|
enabled = enabled,
|
||||||
|
role = role,
|
||||||
|
onValueChange = onValueChange
|
||||||
|
)
|
||||||
|
|
||||||
|
object Interaction {
|
||||||
|
val rippleColor: Color
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
get() = defaultInteractionRippleColor()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
private fun defaultInteractionRippleColor() = LocalColors.current.themeSecondary
|
@@ -27,7 +27,6 @@ import androidx.compose.foundation.ContextMenuItem
|
|||||||
import androidx.compose.foundation.ContextMenuRepresentation
|
import androidx.compose.foundation.ContextMenuRepresentation
|
||||||
import androidx.compose.foundation.ContextMenuState
|
import androidx.compose.foundation.ContextMenuState
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.IntrinsicSize
|
import androidx.compose.foundation.layout.IntrinsicSize
|
||||||
@@ -40,7 +39,6 @@ import androidx.compose.foundation.layout.sizeIn
|
|||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.ripple.rememberRipple
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
@@ -76,13 +74,13 @@ import androidx.compose.ui.window.rememberPopupPositionProviderAtPosition
|
|||||||
import com.highcapable.flexiui.LocalColors
|
import com.highcapable.flexiui.LocalColors
|
||||||
import com.highcapable.flexiui.LocalShapes
|
import com.highcapable.flexiui.LocalShapes
|
||||||
import com.highcapable.flexiui.LocalSizes
|
import com.highcapable.flexiui.LocalSizes
|
||||||
|
import com.highcapable.flexiui.interaction.rippleClickable
|
||||||
import com.highcapable.flexiui.utils.orElse
|
import com.highcapable.flexiui.utils.orElse
|
||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class ContextMenuStyle(
|
data class ContextMenuStyle(
|
||||||
val backgroundColor: Color,
|
val backgroundColor: Color,
|
||||||
val fillColor: Color,
|
|
||||||
val textColor: Color,
|
val textColor: Color,
|
||||||
val padding: Dp,
|
val padding: Dp,
|
||||||
val shadowSize: Dp,
|
val shadowSize: Dp,
|
||||||
@@ -130,7 +128,6 @@ internal class DesktopContextMenuRepresentation(private val style: ContextMenuSt
|
|||||||
) {
|
) {
|
||||||
items().forEach { item ->
|
items().forEach { item ->
|
||||||
MenuItemContent(
|
MenuItemContent(
|
||||||
fillColor = style.fillColor,
|
|
||||||
shape = shape,
|
shape = shape,
|
||||||
onClick = {
|
onClick = {
|
||||||
state.status = ContextMenuState.Status.Closed
|
state.status = ContextMenuState.Status.Closed
|
||||||
@@ -146,7 +143,6 @@ internal class DesktopContextMenuRepresentation(private val style: ContextMenuSt
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun MenuItemContent(
|
private fun MenuItemContent(
|
||||||
fillColor: Color,
|
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
content: @Composable RowScope.() -> Unit
|
content: @Composable RowScope.() -> Unit
|
||||||
@@ -155,9 +151,8 @@ private fun MenuItemContent(
|
|||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(shape)
|
.clip(shape)
|
||||||
.clickable(
|
.rippleClickable(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
indication = rememberRipple(color = fillColor),
|
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
)
|
)
|
||||||
.onHover { hovered = it }
|
.onHover { hovered = it }
|
||||||
@@ -200,7 +195,6 @@ object DesktopContextMenu {
|
|||||||
val LocalContextMenuStyle = compositionLocalOf {
|
val LocalContextMenuStyle = compositionLocalOf {
|
||||||
ContextMenuStyle(
|
ContextMenuStyle(
|
||||||
backgroundColor = Color.Unspecified,
|
backgroundColor = Color.Unspecified,
|
||||||
fillColor = Color.Unspecified,
|
|
||||||
textColor = Color.Unspecified,
|
textColor = Color.Unspecified,
|
||||||
padding = Dp.Unspecified,
|
padding = Dp.Unspecified,
|
||||||
shadowSize = Dp.Unspecified,
|
shadowSize = Dp.Unspecified,
|
||||||
@@ -212,7 +206,6 @@ val LocalContextMenuStyle = compositionLocalOf {
|
|||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
internal fun defaultContextMenuStyle() = ContextMenuStyle(
|
internal fun defaultContextMenuStyle() = ContextMenuStyle(
|
||||||
backgroundColor = LocalContextMenuStyle.current.backgroundColor.orElse() ?: LocalColors.current.foregroundPrimary,
|
backgroundColor = LocalContextMenuStyle.current.backgroundColor.orElse() ?: LocalColors.current.foregroundPrimary,
|
||||||
fillColor = LocalContextMenuStyle.current.fillColor.orElse() ?: LocalColors.current.themeSecondary,
|
|
||||||
textColor = LocalContextMenuStyle.current.textColor.orElse() ?: LocalColors.current.textPrimary,
|
textColor = LocalContextMenuStyle.current.textColor.orElse() ?: LocalColors.current.textPrimary,
|
||||||
padding = LocalContextMenuStyle.current.padding.orElse() ?: LocalSizes.current.spacingTertiary,
|
padding = LocalContextMenuStyle.current.padding.orElse() ?: LocalSizes.current.spacingTertiary,
|
||||||
shadowSize = LocalContextMenuStyle.current.shadowSize.orElse() ?: LocalSizes.current.zoomSizeTertiary,
|
shadowSize = LocalContextMenuStyle.current.shadowSize.orElse() ?: LocalSizes.current.zoomSizeTertiary,
|
||||||
|
Reference in New Issue
Block a user