squashable

This commit is contained in:
Sad Ellie 2023-05-18 22:34:21 +03:00
parent d0b09beb7d
commit 3a6987bac0
2 changed files with 95 additions and 23 deletions

View File

@ -20,25 +20,18 @@ package com.sadellie.unitto.core.ui.common
import android.content.res.Configuration import android.content.res.Configuration
import android.view.HapticFeedbackConstants import android.view.HapticFeedbackConstants
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.animateIntAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import kotlinx.coroutines.launch
@Composable @Composable
fun BasicKeyboardButton( fun BasicKeyboardButton(
@ -52,21 +45,21 @@ fun BasicKeyboardButton(
contentHeight: Float contentHeight: Float
) { ) {
val view = LocalView.current val view = LocalView.current
val interactionSource = remember { MutableInteractionSource() } val coroutineScope = rememberCoroutineScope()
val isPressed by interactionSource.collectIsPressedAsState()
val cornerRadius: Int by animateIntAsState(
targetValue = if (isPressed) 30 else 50,
animationSpec = tween(easing = FastOutSlowInEasing),
)
UnittoButton( UnittoButton(
modifier = modifier, modifier = modifier,
onClick = onClick, onClick = {
onClick()
if (allowVibration) {
coroutineScope.launch {
view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
}
}
},
onLongClick = onLongClick, onLongClick = onLongClick,
shape = RoundedCornerShape(cornerRadius),
containerColor = containerColor, containerColor = containerColor,
contentPadding = PaddingValues(), contentPadding = PaddingValues()
interactionSource = interactionSource
) { ) {
Icon( Icon(
imageVector = icon, imageVector = icon,
@ -75,10 +68,6 @@ fun BasicKeyboardButton(
tint = iconColor tint = iconColor
) )
} }
LaunchedEffect(key1 = isPressed) {
if (isPressed and allowVibration) view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
}
} }
@Composable @Composable

View File

@ -0,0 +1,83 @@
/*
* Unitto is a unit converter for Android
* Copyright (c) 2023 Elshan Agaev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sadellie.unitto.core.ui.common
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateIntAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.clip
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.Dp
fun Modifier.squashable(
onClick: () -> Unit = {},
onLongClick: (() -> Unit)? = null,
interactionSource: MutableInteractionSource,
cornerRadiusRange: IntRange,
role: Role = Role.Button,
) = composed {
val isPressed by interactionSource.collectIsPressedAsState()
val cornerRadius: Int by animateIntAsState(
targetValue = if (isPressed) cornerRadiusRange.first else cornerRadiusRange.last,
animationSpec = tween(easing = FastOutSlowInEasing),
)
Modifier
.clip(RoundedCornerShape(cornerRadius))
.combinedClickable(
onClick = onClick,
onLongClick = onLongClick,
interactionSource = interactionSource,
indication = rememberRipple(),
role = role,
)
}
fun Modifier.squashable(
onClick: () -> Unit = {},
onLongClick: (() -> Unit)? = null,
interactionSource: MutableInteractionSource,
cornerRadiusRange: ClosedRange<Dp>,
role: Role = Role.Button,
) = composed {
val isPressed by interactionSource.collectIsPressedAsState()
val cornerRadius: Dp by animateDpAsState(
targetValue = if (isPressed) cornerRadiusRange.start else cornerRadiusRange.endInclusive,
animationSpec = tween(easing = FastOutSlowInEasing),
)
Modifier
.clip(RoundedCornerShape(cornerRadius))
.combinedClickable(
onClick = onClick,
onLongClick = onLongClick,
interactionSource = interactionSource,
indication = rememberRipple(),
role = role,
)
}