mirror of
https://github.com/fankes/pagecurl-multiplatform.git
synced 2025-09-06 18:55:28 +08:00
Add forward & backward
This commit is contained in:
@@ -3,24 +3,83 @@ package eu.wewox.pagecurl
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
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.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.Surface
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
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.Modifier
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.graphics.Color
|
||||||
import eu.wewox.pagecurl.page.Page
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import eu.wewox.pagecurl.config.PageCurlConfig
|
||||||
|
import eu.wewox.pagecurl.page.PageCurl
|
||||||
import eu.wewox.pagecurl.ui.theme.PageCurlTheme
|
import eu.wewox.pagecurl.ui.theme.PageCurlTheme
|
||||||
|
import eu.wewox.pagecurl.utils.Data
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContent {
|
setContent {
|
||||||
PageCurlTheme {
|
PageCurlTheme {
|
||||||
// A surface container using the 'background' color from the theme
|
var current by remember { mutableStateOf(0) }
|
||||||
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
val count = 6
|
||||||
Page()
|
PageCurl(
|
||||||
|
current = current,
|
||||||
|
count = count,
|
||||||
|
onCurrentChange = {
|
||||||
|
current = it
|
||||||
|
},
|
||||||
|
config = PageCurlConfig(),
|
||||||
|
) { index ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color.White)
|
||||||
|
) {
|
||||||
|
when (index) {
|
||||||
|
0 -> {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.drawable.img_sleep),
|
||||||
|
contentDescription = null,
|
||||||
|
contentScale = ContentScale.Crop,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
count - 1 -> {
|
||||||
|
Text(
|
||||||
|
text = "The End",
|
||||||
|
fontSize = 34.sp,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Text(
|
||||||
|
text = if (index % 2 == 1) Data.Lorem1 else Data.Lorem2,
|
||||||
|
fontSize = 22.sp,
|
||||||
|
modifier = Modifier.padding(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = index.toString(),
|
||||||
|
color = Color.White,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.BottomEnd)
|
||||||
|
.background(Color.Black, RoundedCornerShape(topStartPercent = 100))
|
||||||
|
.padding(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
app/src/main/java/eu/wewox/pagecurl/config/CurlConfig.kt
Normal file
46
app/src/main/java/eu/wewox/pagecurl/config/CurlConfig.kt
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package eu.wewox.pagecurl.config
|
||||||
|
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.geometry.Rect
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.unit.DpOffset
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
data class PageCurlConfig(
|
||||||
|
val curl: CurlConfig = CurlConfig(),
|
||||||
|
val interaction: InteractionConfig = InteractionConfig()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class InteractionConfig(
|
||||||
|
val forward: CurlDirection.Forward = CurlDirection.Forward(
|
||||||
|
Rect(Offset(0.5f, 0.0f), Offset(1.0f, 1.0f)),
|
||||||
|
Rect(Offset(0.0f, 0.0f), Offset(0.5f, 1.0f)),
|
||||||
|
),
|
||||||
|
val backward: CurlDirection.Backward = CurlDirection.Backward(forward.end, forward.start),
|
||||||
|
)
|
||||||
|
|
||||||
|
sealed interface CurlDirection {
|
||||||
|
val start: Rect
|
||||||
|
val end: Rect
|
||||||
|
|
||||||
|
data class Forward(override val start: Rect, override val end: Rect) : CurlDirection
|
||||||
|
data class Backward(override val start: Rect, override val end: Rect) : CurlDirection
|
||||||
|
}
|
||||||
|
|
||||||
|
data class CurlConfig(
|
||||||
|
val backPage: BackPageConfig = BackPageConfig(),
|
||||||
|
val shadow: ShadowConfig = ShadowConfig(),
|
||||||
|
)
|
||||||
|
|
||||||
|
data class BackPageConfig(
|
||||||
|
val color: Color = Color.White,
|
||||||
|
val contentAlpha: Float = 0.1f,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ShadowConfig(
|
||||||
|
val color: Color = Color.Black,
|
||||||
|
val alpha: Float = 0.2f,
|
||||||
|
val radius: Dp = 15.dp,
|
||||||
|
val offset: DpOffset = DpOffset((-5).dp, 0.dp),
|
||||||
|
)
|
@@ -7,7 +7,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.CacheDrawScope
|
import androidx.compose.ui.draw.CacheDrawScope
|
||||||
import androidx.compose.ui.draw.drawWithCache
|
import androidx.compose.ui.draw.drawWithCache
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.geometry.toRect
|
||||||
import androidx.compose.ui.graphics.Paint
|
import androidx.compose.ui.graphics.Paint
|
||||||
import androidx.compose.ui.graphics.Path
|
import androidx.compose.ui.graphics.Path
|
||||||
import androidx.compose.ui.graphics.asAndroidPath
|
import androidx.compose.ui.graphics.asAndroidPath
|
||||||
@@ -18,43 +18,29 @@ import androidx.compose.ui.graphics.drawscope.rotateRad
|
|||||||
import androidx.compose.ui.graphics.drawscope.withTransform
|
import androidx.compose.ui.graphics.drawscope.withTransform
|
||||||
import androidx.compose.ui.graphics.nativeCanvas
|
import androidx.compose.ui.graphics.nativeCanvas
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import androidx.compose.ui.unit.DpOffset
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import eu.wewox.pagecurl.config.CurlConfig
|
||||||
import eu.wewox.pagecurl.utils.Polygon
|
import eu.wewox.pagecurl.utils.Polygon
|
||||||
import eu.wewox.pagecurl.utils.lineLineIntersection
|
import eu.wewox.pagecurl.utils.lineLineIntersection
|
||||||
import eu.wewox.pagecurl.utils.rotate
|
import eu.wewox.pagecurl.utils.rotate
|
||||||
import java.lang.Float.max
|
import java.lang.Float.max
|
||||||
import kotlin.math.atan2
|
import kotlin.math.atan2
|
||||||
|
|
||||||
data class CurlConfig(
|
|
||||||
val backPage: BackPageConfig = BackPageConfig(),
|
|
||||||
val shadow: ShadowConfig = ShadowConfig()
|
|
||||||
) {
|
|
||||||
data class BackPageConfig(
|
|
||||||
val color: Color = Color.White,
|
|
||||||
val contentAlpha: Float = 0.1f,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class ShadowConfig(
|
|
||||||
val color: Color = Color.Black,
|
|
||||||
val alpha: Float = 0.2f,
|
|
||||||
val radius: Dp = 15.dp,
|
|
||||||
val offset: DpOffset = DpOffset((-5).dp, 0.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Modifier.drawCurl(
|
fun Modifier.drawCurl(
|
||||||
config: CurlConfig = CurlConfig(),
|
config: CurlConfig = CurlConfig(),
|
||||||
posA: Offset?,
|
posA: Offset,
|
||||||
posB: Offset?,
|
posB: Offset,
|
||||||
): Modifier = drawWithCache {
|
): Modifier = drawWithCache {
|
||||||
fun drawOnlyContent() =
|
fun drawOnlyContent() =
|
||||||
onDrawWithContent {
|
onDrawWithContent {
|
||||||
drawContent()
|
drawContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (posA == null || posB == null) {
|
if (posA == size.toRect().topLeft && posB == size.toRect().bottomLeft) {
|
||||||
|
return@drawWithCache onDrawWithContent { }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (posA == size.toRect().topRight && posB == size.toRect().bottomRight) {
|
||||||
return@drawWithCache drawOnlyContent()
|
return@drawWithCache drawOnlyContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,29 +1,62 @@
|
|||||||
package eu.wewox.pagecurl.page
|
package eu.wewox.pagecurl.page
|
||||||
|
|
||||||
import androidx.compose.foundation.gestures.awaitFirstDown
|
import androidx.compose.foundation.gestures.awaitFirstDown
|
||||||
|
import androidx.compose.foundation.gestures.drag
|
||||||
import androidx.compose.foundation.gestures.forEachGesture
|
import androidx.compose.foundation.gestures.forEachGesture
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.geometry.Rect
|
||||||
|
import androidx.compose.ui.input.pointer.consumeAllChanges
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.input.pointer.positionChangeConsumed
|
import androidx.compose.ui.unit.IntSize
|
||||||
|
import eu.wewox.pagecurl.config.CurlDirection
|
||||||
|
import eu.wewox.pagecurl.utils.rotate
|
||||||
|
import kotlin.math.PI
|
||||||
|
|
||||||
fun Modifier.curlGesture(
|
fun Modifier.curlGesture(
|
||||||
|
enabled: Boolean,
|
||||||
|
direction: CurlDirection,
|
||||||
|
onStart: () -> Unit,
|
||||||
onCurl: (Offset, Offset) -> Unit,
|
onCurl: (Offset, Offset) -> Unit,
|
||||||
|
onEnd: () -> Unit,
|
||||||
onCancel: () -> Unit,
|
onCancel: () -> Unit,
|
||||||
): Modifier = pointerInput(true) {
|
): Modifier = pointerInput(enabled) {
|
||||||
|
if (!enabled) {
|
||||||
|
return@pointerInput
|
||||||
|
}
|
||||||
|
|
||||||
|
val startRect by lazy { direction.start.multiply(size) }
|
||||||
|
val endRect by lazy { direction.end.multiply(size) }
|
||||||
forEachGesture {
|
forEachGesture {
|
||||||
awaitPointerEventScope {
|
awaitPointerEventScope {
|
||||||
awaitFirstDown(requireUnconsumed = false)
|
val down = awaitFirstDown(requireUnconsumed = false)
|
||||||
do {
|
if (!startRect.contains(down.position)) {
|
||||||
val event = awaitPointerEvent()
|
return@awaitPointerEventScope
|
||||||
val canceled = event.changes.any { it.positionChangeConsumed() }
|
}
|
||||||
val posA = event.changes.getOrNull(0)?.position
|
|
||||||
val posB = event.changes.getOrNull(1)?.position
|
val dragStart = down.position.copy(x = size.width.toFloat())
|
||||||
if (posA != null && posB != null) {
|
|
||||||
onCurl(posA, posB)
|
onStart()
|
||||||
}
|
|
||||||
} while (!canceled && event.changes.any { it.pressed })
|
var dragCurrent = dragStart
|
||||||
onCancel()
|
drag(down.id) { change ->
|
||||||
|
dragCurrent = change.position
|
||||||
|
change.consumeAllChanges()
|
||||||
|
val vector = (dragStart - dragCurrent).rotate(PI.toFloat() / 2)
|
||||||
|
onCurl(dragCurrent - vector, dragCurrent + vector)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endRect.contains(dragCurrent)) {
|
||||||
|
onEnd()
|
||||||
|
} else {
|
||||||
|
onCancel()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Rect.multiply(size: IntSize): Rect =
|
||||||
|
Rect(
|
||||||
|
topLeft = Offset(size.width * left, size.height * top),
|
||||||
|
bottomRight = Offset(size.width * right, size.height * bottom),
|
||||||
|
)
|
||||||
|
@@ -1,64 +0,0 @@
|
|||||||
package eu.wewox.pagecurl.page
|
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material.Text
|
|
||||||
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.Modifier
|
|
||||||
import androidx.compose.ui.geometry.Offset
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import eu.wewox.pagecurl.utils.Data
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun Page() {
|
|
||||||
Text(
|
|
||||||
text = Data.Lorem2,
|
|
||||||
fontSize = 22.sp,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.background(Color.White)
|
|
||||||
.padding(16.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
var posA by remember { mutableStateOf<Offset?>(null) }
|
|
||||||
var posB by remember { mutableStateOf<Offset?>(null) }
|
|
||||||
|
|
||||||
Box(
|
|
||||||
Modifier
|
|
||||||
.curlGesture(
|
|
||||||
onCurl = { a, b ->
|
|
||||||
posA = a
|
|
||||||
posB = b
|
|
||||||
},
|
|
||||||
onCancel = {
|
|
||||||
posA = null
|
|
||||||
posB = null
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.drawCurl(CurlConfig(), posA, posB)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = Data.Lorem1,
|
|
||||||
fontSize = 22.sp,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.background(Color.White)
|
|
||||||
.padding(16.dp)
|
|
||||||
)
|
|
||||||
// Image(
|
|
||||||
// painter = painterResource(R.drawable.img_sleep),
|
|
||||||
// contentDescription = null,
|
|
||||||
// contentScale = ContentScale.Crop,
|
|
||||||
// modifier = Modifier
|
|
||||||
// .fillMaxSize()
|
|
||||||
// )
|
|
||||||
}
|
|
||||||
}
|
|
133
app/src/main/java/eu/wewox/pagecurl/page/PageCurl.kt
Normal file
133
app/src/main/java/eu/wewox/pagecurl/page/PageCurl.kt
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
package eu.wewox.pagecurl.page
|
||||||
|
|
||||||
|
import androidx.compose.animation.core.Animatable
|
||||||
|
import androidx.compose.animation.core.AnimationVector4D
|
||||||
|
import androidx.compose.animation.core.TwoWayConverter
|
||||||
|
import androidx.compose.animation.core.VisibilityThreshold
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.rememberUpdatedState
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import eu.wewox.pagecurl.config.CurlDirection
|
||||||
|
import eu.wewox.pagecurl.config.PageCurlConfig
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PageCurl(
|
||||||
|
current: Int,
|
||||||
|
count: Int,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onCurrentChange: (Int) -> Unit,
|
||||||
|
config: PageCurlConfig = PageCurlConfig(),
|
||||||
|
content: @Composable (Int) -> Unit
|
||||||
|
) {
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val updatedCurrent by rememberUpdatedState(current)
|
||||||
|
|
||||||
|
BoxWithConstraints(modifier) {
|
||||||
|
val maxWidthPx = constraints.maxWidth.toFloat()
|
||||||
|
val maxHeightPx = constraints.maxHeight.toFloat()
|
||||||
|
val left = Curl(Offset(0f, 0f), Offset(0f, maxHeightPx))
|
||||||
|
val right = Curl(Offset(maxWidthPx, 0f), Offset(maxWidthPx, maxHeightPx))
|
||||||
|
|
||||||
|
val forward = remember { Animatable(right, Curl.VectorConverter, Curl.VisibilityThreshold) }
|
||||||
|
val backward = remember { Animatable(left, Curl.VectorConverter, Curl.VisibilityThreshold) }
|
||||||
|
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.curlGesture(
|
||||||
|
enabled = updatedCurrent < count - 1,
|
||||||
|
scope = scope,
|
||||||
|
direction = config.interaction.forward,
|
||||||
|
start = right,
|
||||||
|
end = left,
|
||||||
|
animatable = forward,
|
||||||
|
onChange = { onCurrentChange(updatedCurrent + 1) }
|
||||||
|
)
|
||||||
|
.curlGesture(
|
||||||
|
enabled = updatedCurrent > 0,
|
||||||
|
scope = scope,
|
||||||
|
direction = config.interaction.backward,
|
||||||
|
start = left,
|
||||||
|
end = right,
|
||||||
|
animatable = backward,
|
||||||
|
onChange = { onCurrentChange(updatedCurrent - 1) }
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (updatedCurrent + 1 < count) {
|
||||||
|
content(updatedCurrent + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedCurrent < count) {
|
||||||
|
Box(Modifier.drawCurl(config.curl, forward.value.a, forward.value.b)) {
|
||||||
|
content(updatedCurrent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedCurrent > 0) {
|
||||||
|
Box(Modifier.drawCurl(config.curl, backward.value.a, backward.value.b)) {
|
||||||
|
content(updatedCurrent - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Modifier.curlGesture(
|
||||||
|
enabled: Boolean,
|
||||||
|
scope: CoroutineScope,
|
||||||
|
direction: CurlDirection,
|
||||||
|
start: Curl,
|
||||||
|
end: Curl,
|
||||||
|
animatable: Animatable<Curl, AnimationVector4D>,
|
||||||
|
onChange: () -> Unit,
|
||||||
|
): Modifier =
|
||||||
|
curlGesture(
|
||||||
|
enabled = enabled,
|
||||||
|
direction = direction,
|
||||||
|
onStart = {
|
||||||
|
scope.launch {
|
||||||
|
animatable.snapTo(start)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCurl = { a, b ->
|
||||||
|
scope.launch {
|
||||||
|
animatable.animateTo(Curl(a, b))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onEnd = {
|
||||||
|
scope.launch {
|
||||||
|
try {
|
||||||
|
animatable.animateTo(end)
|
||||||
|
} finally {
|
||||||
|
onChange()
|
||||||
|
animatable.snapTo(start)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCancel = {
|
||||||
|
scope.launch {
|
||||||
|
animatable.animateTo(start)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
private data class Curl(val a: Offset, val b: Offset) {
|
||||||
|
companion object {
|
||||||
|
val VectorConverter: TwoWayConverter<Curl, AnimationVector4D> =
|
||||||
|
TwoWayConverter(
|
||||||
|
convertToVector = { AnimationVector4D(it.a.x, it.a.y, it.b.x, it.b.y) },
|
||||||
|
convertFromVector = { Curl(Offset(it.v1, it.v2), Offset(it.v3, it.v4)) }
|
||||||
|
)
|
||||||
|
|
||||||
|
val VisibilityThreshold: Curl =
|
||||||
|
Curl(Offset.VisibilityThreshold, Offset.VisibilityThreshold)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,12 +1,12 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
compose_version = '1.0.1'
|
compose_version = '1.2.0-alpha07'
|
||||||
}
|
}
|
||||||
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application' version '7.1.1' apply false
|
id 'com.android.application' version '7.1.1' apply false
|
||||||
id 'com.android.library' version '7.1.1' apply false
|
id 'com.android.library' version '7.1.1' apply false
|
||||||
id 'org.jetbrains.kotlin.android' version '1.5.21' apply false
|
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
|
Reference in New Issue
Block a user