mirror of
https://github.com/fankes/pagecurl-multiplatform.git
synced 2025-09-05 18:25:20 +08:00
Add overlay controls
This commit is contained in:
@@ -8,12 +8,15 @@ import androidx.activity.compose.setContent
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -22,6 +25,7 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import eu.wewox.pagecurl.components.SettingsPopup
|
||||
import eu.wewox.pagecurl.components.overlayControls
|
||||
import eu.wewox.pagecurl.config.PageCurlConfig
|
||||
import eu.wewox.pagecurl.page.PageCurl
|
||||
import eu.wewox.pagecurl.page.rememberPageCurlState
|
||||
@@ -33,13 +37,31 @@ class MainActivity : ComponentActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
PageCurlTheme {
|
||||
Column {
|
||||
Box {
|
||||
val scope = rememberCoroutineScope()
|
||||
val state = rememberPageCurlState(max = 6)
|
||||
var showPopup by remember { mutableStateOf(false) }
|
||||
|
||||
PageCurl(
|
||||
state = state,
|
||||
config = PageCurlConfig(),
|
||||
modifier = Modifier.overlayControls(
|
||||
next = {
|
||||
scope.launch {
|
||||
val next = (state.current + 1).coerceAtMost(state.max - 1)
|
||||
state.snapTo(next)
|
||||
}
|
||||
},
|
||||
prev = {
|
||||
scope.launch {
|
||||
val prev = (state.current - 1).coerceAtLeast(0)
|
||||
state.snapTo(prev)
|
||||
}
|
||||
},
|
||||
center = {
|
||||
showPopup = true
|
||||
}
|
||||
)
|
||||
) { index ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
@@ -71,22 +93,28 @@ class MainActivity : ComponentActivity() {
|
||||
.background(Color.Black, RoundedCornerShape(topStartPercent = 100))
|
||||
.padding(16.dp)
|
||||
)
|
||||
|
||||
SettingsPopup(
|
||||
onSnapToFirst = {
|
||||
scope.launch {
|
||||
state.snapTo(0)
|
||||
}
|
||||
},
|
||||
onSnapToLast = {
|
||||
scope.launch {
|
||||
state.snapTo(state.max - 1)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (showPopup) {
|
||||
SettingsPopup(
|
||||
onSnapToFirst = {
|
||||
scope.launch {
|
||||
state.snapTo(0)
|
||||
showPopup = false
|
||||
}
|
||||
},
|
||||
onSnapToLast = {
|
||||
scope.launch {
|
||||
state.snapTo(state.max - 1)
|
||||
showPopup = false
|
||||
}
|
||||
},
|
||||
onDismiss = {
|
||||
showPopup = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,37 @@
|
||||
package eu.wewox.pagecurl.components
|
||||
|
||||
import androidx.compose.foundation.gestures.awaitFirstDown
|
||||
import androidx.compose.foundation.gestures.forEachGesture
|
||||
import androidx.compose.foundation.gestures.waitForUpOrCancellation
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.unit.center
|
||||
import androidx.compose.ui.unit.toOffset
|
||||
|
||||
internal fun Modifier.overlayControls(
|
||||
next: () -> Unit,
|
||||
prev: () -> Unit,
|
||||
center: () -> Unit,
|
||||
): Modifier = pointerInput(Unit) {
|
||||
forEachGesture {
|
||||
awaitPointerEventScope {
|
||||
val down = awaitFirstDown().also { it.consume() }
|
||||
val up = waitForUpOrCancellation() ?: return@awaitPointerEventScope
|
||||
up.consume()
|
||||
if ((down.position - up.position).getDistance() > viewConfiguration.touchSlop) {
|
||||
return@awaitPointerEventScope
|
||||
}
|
||||
|
||||
if ((up.position - size.center.toOffset()).getDistance() < 100f) {
|
||||
center()
|
||||
return@awaitPointerEventScope
|
||||
}
|
||||
|
||||
if (up.position.x < size.width / 2) {
|
||||
prev()
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,26 +1,16 @@
|
||||
package eu.wewox.pagecurl.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Popup
|
||||
|
||||
@@ -28,66 +18,38 @@ import androidx.compose.ui.window.Popup
|
||||
internal fun SettingsPopup(
|
||||
onSnapToFirst: () -> Unit,
|
||||
onSnapToLast: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
var showPopup by remember { mutableStateOf(false) }
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(100.dp)
|
||||
.clickableWithoutRipple {
|
||||
showPopup = true
|
||||
}
|
||||
)
|
||||
|
||||
if (showPopup) {
|
||||
Box(Modifier.fillMaxSize()) {
|
||||
Popup(
|
||||
alignment = Alignment.Center,
|
||||
onDismissRequest = { showPopup = false }
|
||||
Popup(
|
||||
alignment = Alignment.Center,
|
||||
onDismissRequest = onDismiss,
|
||||
) {
|
||||
Card(
|
||||
shape = RoundedCornerShape(24.dp),
|
||||
backgroundColor = MaterialTheme.colors.primary,
|
||||
elevation = 16.dp,
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) {
|
||||
Card(
|
||||
shape = RoundedCornerShape(24.dp),
|
||||
backgroundColor = MaterialTheme.colors.primary,
|
||||
elevation = 16.dp
|
||||
TextButton(
|
||||
onClick = onSnapToFirst
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) {
|
||||
TextButton(
|
||||
onClick = {
|
||||
onSnapToFirst()
|
||||
showPopup = false
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
text = "Go to first",
|
||||
color = MaterialTheme.colors.onPrimary
|
||||
)
|
||||
}
|
||||
TextButton(
|
||||
onClick = {
|
||||
onSnapToLast()
|
||||
showPopup = false
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
text = "Go to last",
|
||||
color = MaterialTheme.colors.onPrimary
|
||||
)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = "Go to first",
|
||||
color = MaterialTheme.colors.onPrimary
|
||||
)
|
||||
}
|
||||
TextButton(
|
||||
onClick = onSnapToLast
|
||||
) {
|
||||
Text(
|
||||
text = "Go to last",
|
||||
color = MaterialTheme.colors.onPrimary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Modifier.clickableWithoutRipple(onClick: () -> Unit) = composed {
|
||||
clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = null,
|
||||
onClick = onClick
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user