Add overlay controls

This commit is contained in:
Oleksandr Balan
2022-06-30 01:15:24 +02:00
parent 8495cbf168
commit 973c54f39c
3 changed files with 108 additions and 81 deletions

View File

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

View File

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

View File

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