feat: add Interaction and move ripple effect with name "rippleColor"

This commit is contained in:
2023-11-10 01:21:44 +08:00
parent 01cd400b90
commit d1c1a8eafe
3 changed files with 125 additions and 27 deletions

View File

@@ -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
) )

View File

@@ -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

View File

@@ -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,