mirror of
https://github.com/AllanWang/Frost-for-Facebook.git
synced 2024-09-19 15:11:42 +02:00
Add shake effect
This commit is contained in:
parent
d0ed236ea6
commit
1dab81ee38
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2023 Allan Wang
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.pitchedapps.frost.compose.effects
|
||||
|
||||
import androidx.compose.animation.core.animate
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.platform.debugInspectorInfo
|
||||
import androidx.compose.ui.platform.inspectable
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.cancelChildren
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* State for tracking shaking animation
|
||||
*
|
||||
* Note: Used some other material states as reference. This however will recompose the function
|
||||
* holding the state during shakes.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberShakeState(): ShakeState {
|
||||
val scope = rememberCoroutineScope()
|
||||
val state = remember(scope) { ShakeState(scope) }
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
class ShakeState
|
||||
internal constructor(
|
||||
private val animationScope: CoroutineScope,
|
||||
) {
|
||||
|
||||
private val job = SupervisorJob()
|
||||
|
||||
private var _rotation by mutableFloatStateOf(0f)
|
||||
|
||||
internal val rotation
|
||||
get() = _rotation
|
||||
|
||||
fun shake() {
|
||||
job.cancelChildren()
|
||||
animationScope.launch(job) {
|
||||
animate(
|
||||
_rotation,
|
||||
0f,
|
||||
initialVelocity = 200f,
|
||||
animationSpec =
|
||||
spring(
|
||||
dampingRatio = 0.3f,
|
||||
stiffness = 200f,
|
||||
),
|
||||
) { value, _ ->
|
||||
_rotation = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Modifier.shake(state: ShakeState, enabled: Boolean = true) =
|
||||
inspectable(
|
||||
inspectorInfo =
|
||||
debugInspectorInfo {
|
||||
name = "shake"
|
||||
properties["enabled"] = enabled
|
||||
},
|
||||
) {
|
||||
Modifier.rotate(state.rotation)
|
||||
}
|
@ -16,9 +16,12 @@
|
||||
*/
|
||||
package com.pitchedapps.frost.tabselector
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
@ -37,6 +40,8 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pitchedapps.frost.compose.effects.rememberShakeState
|
||||
import com.pitchedapps.frost.compose.effects.shake
|
||||
import com.pitchedapps.frost.facebook.FbItem
|
||||
import com.pitchedapps.frost.facebook.tab
|
||||
|
||||
@ -63,6 +68,7 @@ fun TabSelectorScreen(modifier: Modifier = Modifier) {
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun TabSelector(
|
||||
modifier: Modifier,
|
||||
@ -74,7 +80,17 @@ fun TabSelector(
|
||||
modifier = modifier,
|
||||
columns = GridCells.Fixed(4),
|
||||
) {
|
||||
items(unselected, key = { it.key }) { TabItem(data = it) }
|
||||
items(unselected, key = { it.key }) {
|
||||
val shakeState = rememberShakeState()
|
||||
TabItem(
|
||||
modifier =
|
||||
Modifier.animateItemPlacement().shake(shakeState).clickable {
|
||||
shakeState.shake()
|
||||
// onSelect(listOf(it))
|
||||
},
|
||||
data = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +104,7 @@ fun TabItem(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.padding(4.dp),
|
||||
modifier = Modifier.padding(4.dp).size(24.dp),
|
||||
imageVector = data.icon,
|
||||
contentDescription = data.title,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user