mirror of
https://github.com/fankes/pagecurl-multiplatform.git
synced 2025-09-06 18:55:28 +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.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.Text
|
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.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
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.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import eu.wewox.pagecurl.components.SettingsPopup
|
import eu.wewox.pagecurl.components.SettingsPopup
|
||||||
|
import eu.wewox.pagecurl.components.overlayControls
|
||||||
import eu.wewox.pagecurl.config.PageCurlConfig
|
import eu.wewox.pagecurl.config.PageCurlConfig
|
||||||
import eu.wewox.pagecurl.page.PageCurl
|
import eu.wewox.pagecurl.page.PageCurl
|
||||||
import eu.wewox.pagecurl.page.rememberPageCurlState
|
import eu.wewox.pagecurl.page.rememberPageCurlState
|
||||||
@@ -33,13 +37,31 @@ class MainActivity : ComponentActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContent {
|
setContent {
|
||||||
PageCurlTheme {
|
PageCurlTheme {
|
||||||
Column {
|
Box {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val state = rememberPageCurlState(max = 6)
|
val state = rememberPageCurlState(max = 6)
|
||||||
|
var showPopup by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
PageCurl(
|
PageCurl(
|
||||||
state = state,
|
state = state,
|
||||||
config = PageCurlConfig(),
|
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 ->
|
) { index ->
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -71,21 +93,27 @@ class MainActivity : ComponentActivity() {
|
|||||||
.background(Color.Black, RoundedCornerShape(topStartPercent = 100))
|
.background(Color.Black, RoundedCornerShape(topStartPercent = 100))
|
||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showPopup) {
|
||||||
SettingsPopup(
|
SettingsPopup(
|
||||||
onSnapToFirst = {
|
onSnapToFirst = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
state.snapTo(0)
|
state.snapTo(0)
|
||||||
|
showPopup = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSnapToLast = {
|
onSnapToLast = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
state.snapTo(state.max - 1)
|
state.snapTo(state.max - 1)
|
||||||
|
showPopup = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.align(Alignment.Center)
|
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
|
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.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.Card
|
import androidx.compose.material.Card
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.material.TextButton
|
import androidx.compose.material.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
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.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.composed
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Popup
|
import androidx.compose.ui.window.Popup
|
||||||
|
|
||||||
@@ -28,38 +18,23 @@ import androidx.compose.ui.window.Popup
|
|||||||
internal fun SettingsPopup(
|
internal fun SettingsPopup(
|
||||||
onSnapToFirst: () -> Unit,
|
onSnapToFirst: () -> Unit,
|
||||||
onSnapToLast: () -> 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(
|
Popup(
|
||||||
alignment = Alignment.Center,
|
alignment = Alignment.Center,
|
||||||
onDismissRequest = { showPopup = false }
|
onDismissRequest = onDismiss,
|
||||||
) {
|
) {
|
||||||
Card(
|
Card(
|
||||||
shape = RoundedCornerShape(24.dp),
|
shape = RoundedCornerShape(24.dp),
|
||||||
backgroundColor = MaterialTheme.colors.primary,
|
backgroundColor = MaterialTheme.colors.primary,
|
||||||
elevation = 16.dp
|
elevation = 16.dp,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
modifier = Modifier.padding(8.dp)
|
modifier = Modifier.padding(8.dp)
|
||||||
) {
|
) {
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = onSnapToFirst
|
||||||
onSnapToFirst()
|
|
||||||
showPopup = false
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "Go to first",
|
text = "Go to first",
|
||||||
@@ -67,10 +42,7 @@ internal fun SettingsPopup(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = onSnapToLast
|
||||||
onSnapToLast()
|
|
||||||
showPopup = false
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "Go to last",
|
text = "Go to last",
|
||||||
@@ -80,14 +52,4 @@ internal fun SettingsPopup(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Modifier.clickableWithoutRipple(onClick: () -> Unit) = composed {
|
|
||||||
clickable(
|
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
|
||||||
indication = null,
|
|
||||||
onClick = onClick
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user