Browse Source

Move ImageViewer to build154.

pull/397/head
Roman Sedaikin 3 years ago
parent
commit
3097fa3713
  1. 2
      examples/imageviewer/build.gradle.kts
  2. 25
      examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/view/FullImageScreen.kt
  3. 28
      examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/view/MainScreen.kt
  4. 38
      examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/view/Draggable.kt
  5. 3
      examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/view/Scalable.kt
  6. 24
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/FullImageScreen.kt
  7. 30
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/MainScreen.kt
  8. 4
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/Toast.kt
  9. 18
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/Zoomable.kt

2
examples/imageviewer/build.gradle.kts

@ -11,7 +11,7 @@ buildscript {
dependencies {
// __LATEST_COMPOSE_RELEASE_VERSION__
classpath("org.jetbrains.compose:compose-gradle-plugin:0.3.0-build150")
classpath("org.jetbrains.compose:compose-gradle-plugin:0.3.0-build154")
classpath("com.android.tools.build:gradle:4.0.1")
// __KOTLIN_COMPOSE_VERSION__
classpath(kotlin("gradle-plugin", version = "1.4.30"))

25
examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/view/FullImageScreen.kt

@ -12,8 +12,8 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.preferredHeight
import androidx.compose.foundation.layout.preferredSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.CircularProgressIndicator
@ -21,6 +21,7 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@ -70,11 +71,11 @@ fun setImageFullScreen(
private fun setLoadingScreen() {
Box {
Surface(color = MiniatureColor, modifier = Modifier.preferredHeight(44.dp)) {}
Surface(color = MiniatureColor, modifier = Modifier.height(44.dp)) {}
Box {
Surface(color = DarkGray, elevation = 4.dp, shape = CircleShape) {
CircularProgressIndicator(
modifier = Modifier.preferredSize(50.dp).padding(3.dp, 3.dp, 4.dp, 4.dp),
modifier = Modifier.size(50.dp).padding(3.dp, 3.dp, 4.dp, 4.dp),
color = DarkGreen
)
}
@ -88,7 +89,7 @@ fun setToolBar(
content: ContentState
) {
val scrollState = rememberScrollState()
Surface(color = MiniatureColor, modifier = Modifier.preferredHeight(44.dp)) {
Surface(color = MiniatureColor, modifier = Modifier.height(44.dp)) {
Row(modifier = Modifier.padding(end = 30.dp)) {
Surface(
color = Transparent,
@ -105,7 +106,7 @@ fun setToolBar(
Image(
icBack(),
contentDescription = null,
modifier = Modifier.preferredSize(38.dp)
modifier = Modifier.size(38.dp)
)
}
}
@ -120,7 +121,7 @@ fun setToolBar(
Surface(
color = Color(255, 255, 255, 40),
modifier = Modifier.preferredSize(154.dp, 38.dp)
modifier = Modifier.size(154.dp, 38.dp)
.align(Alignment.CenterVertically),
shape = CircleShape
) {
@ -138,7 +139,7 @@ fun setToolBar(
fun FilterButton(
content: ContentState,
type: FilterType,
modifier: Modifier = Modifier.preferredSize(38.dp)
modifier: Modifier = Modifier.size(38.dp)
) {
Box(
modifier = Modifier.background(color = Transparent).clip(CircleShape)
@ -170,14 +171,14 @@ fun getFilterImage(type: FilterType, content: ContentState): Painter {
@Composable
fun setImage(content: ContentState) {
val drag = DragHandler()
val scale = ScaleHandler()
val drag = remember { DragHandler() }
val scale = remember { ScaleHandler() }
Surface(
color = DarkGray,
modifier = Modifier.fillMaxSize()
) {
Draggable(onDrag = drag, modifier = Modifier.fillMaxSize()) {
Draggable(dragHandler = drag, modifier = Modifier.fillMaxSize()) {
Scalable(onScale = scale, modifier = Modifier.fillMaxSize()) {
val bitmap = imageByGesture(content, scale, drag)
Image(
@ -207,7 +208,7 @@ fun imageByGesture(
} else {
content.swipePrevious()
}
drag.onCancel()
drag.cancel()
}
return bitmap

28
examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/view/MainScreen.kt

@ -13,9 +13,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.preferredHeight
import androidx.compose.foundation.layout.preferredSize
import androidx.compose.foundation.layout.preferredWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Card
import androidx.compose.material.CircularProgressIndicator
@ -71,7 +71,7 @@ fun setLoadingScreen(content: ContentState) {
Box(modifier = Modifier.align(Alignment.Center)) {
Surface(color = DarkGray, elevation = 4.dp, shape = CircleShape) {
CircularProgressIndicator(
modifier = Modifier.preferredSize(50.dp).padding(4.dp),
modifier = Modifier.size(50.dp).padding(4.dp),
color = DarkGreen
)
}
@ -102,7 +102,7 @@ fun setTitleBar(text: String, content: ContentState) {
TopAppBar(
backgroundColor = DarkGreen,
title = {
Row(Modifier.preferredHeight(50.dp)) {
Row(Modifier.height(50.dp)) {
Text(
text,
color = Foreground,
@ -123,7 +123,7 @@ fun setTitleBar(text: String, content: ContentState) {
Image(
icRefresh(),
contentDescription = null,
modifier = Modifier.preferredSize(35.dp)
modifier = Modifier.size(35.dp)
)
}
}
@ -139,7 +139,7 @@ fun setPreviewImageUI(content: ContentState) {
}) {
Card(
backgroundColor = DarkGray,
modifier = Modifier.preferredHeight(250.dp),
modifier = Modifier.height(250.dp),
shape = RectangleShape,
elevation = 1.dp
) {
@ -166,7 +166,7 @@ fun setMiniatureUI(
Card(
backgroundColor = MiniatureColor,
modifier = Modifier.padding(start = 10.dp, end = 10.dp).preferredHeight(70.dp)
modifier = Modifier.padding(start = 10.dp, end = 10.dp).height(70.dp)
.fillMaxWidth()
.clickable {
content.setMainImage(picture)
@ -183,8 +183,8 @@ fun setMiniatureUI(
Image(
picture.image.asImageBitmap(),
contentDescription = null,
modifier = Modifier.preferredHeight(70.dp)
.preferredWidth(90.dp)
modifier = Modifier.height(70.dp)
.width(90.dp)
.padding(start = 1.dp, top = 1.dp, end = 1.dp, bottom = 1.dp),
contentScale = ContentScale.Crop
)
@ -197,8 +197,8 @@ fun setMiniatureUI(
)
Clickable(
modifier = Modifier.preferredHeight(70.dp)
.preferredWidth(30.dp),
modifier = Modifier.height(70.dp)
.width(30.dp),
onClick = {
showPopUpMessage(
"${content.getString(R.string.picture)} " +
@ -213,8 +213,8 @@ fun setMiniatureUI(
Image(
icDots(),
contentDescription = null,
modifier = Modifier.preferredHeight(70.dp)
.preferredWidth(30.dp)
modifier = Modifier.height(70.dp)
.width(30.dp)
.padding(start = 1.dp, top = 25.dp, end = 1.dp, bottom = 25.dp),
contentScale = ContentScale.FillHeight
)

38
examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/view/Draggable.kt

@ -1,33 +1,40 @@
package example.imageviewer.view
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.input.pointer.consumePositionChange
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.gesture.DragObserver
import androidx.compose.ui.gesture.rawDragGestureFilter
import example.imageviewer.core.EventLocker
import example.imageviewer.style.Transparent
@Composable
fun Draggable(
onDrag: DragHandler,
dragHandler: DragHandler,
modifier: Modifier = Modifier,
children: @Composable() () -> Unit
) {
Surface(
color = Transparent,
modifier = modifier.rawDragGestureFilter(
dragObserver = onDrag,
canStartDragging = { true }
)
modifier = modifier.pointerInput(Unit) {
detectDragGestures(
onDragStart = { dragHandler.reset() },
onDragEnd = { dragHandler.reset() },
onDragCancel = { dragHandler.cancel() },
) { change, dragAmount ->
dragHandler.drag(dragAmount)
change.consumePositionChange()
}
}
) {
children()
}
}
class DragHandler : DragObserver {
class DragHandler {
private val amount = mutableStateOf(Point(0f, 0f))
private val distance = mutableStateOf(Point(0f, 0f))
@ -41,33 +48,24 @@ class DragHandler : DragObserver {
return distance.value
}
override fun onStart(downPosition: Offset) {
fun reset() {
distance.value = Point(Offset.Zero)
locker.unlock()
}
override fun onStop(velocity: Offset) {
distance.value = Point(Offset.Zero)
locker.unlock()
}
override fun onCancel() {
fun cancel() {
distance.value = Point(Offset.Zero)
locker.lock()
}
override fun onDrag(dragDistance: Offset): Offset {
fun drag(dragDistance: Offset) {
if (locker.isLocked()) {
val dx = dragDistance.x
val dy = dragDistance.y
distance.value = Point(distance.value.x + dx, distance.value.y + dy)
amount.value = Point(amount.value.x + dx, amount.value.y + dy)
return dragDistance
}
return Offset.Zero
}
}

3
examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/view/Scalable.kt

@ -18,7 +18,7 @@ fun Scalable(
) {
Surface(
color = Transparent,
modifier = modifier.pointerInput {
modifier = modifier.pointerInput(Unit) {
detectTapGestures(onDoubleTap = { onScale.resetFactor() })
detectTransformGestures { _, _, zoom, _ ->
onScale.onScale(zoom)
@ -33,6 +33,7 @@ class ScaleHandler(private val maxFactor: Float = 5f, private val minFactor: Flo
val factor = mutableStateOf(1f)
fun resetFactor() {
println("scale reset")
if (factor.value > minFactor)
factor.value = minFactor
}

24
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/FullImageScreen.kt

@ -9,8 +9,8 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.preferredHeight
import androidx.compose.foundation.layout.preferredSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.ScrollState
@ -77,11 +77,11 @@ fun setImageFullScreen(
private fun setLoadingScreen() {
Box {
Surface(color = MiniatureColor, modifier = Modifier.preferredHeight(44.dp)) {}
Surface(color = MiniatureColor, modifier = Modifier.height(44.dp)) {}
Box(modifier = Modifier.align(Alignment.Center)) {
Surface(color = DarkGray, elevation = 4.dp, shape = CircleShape) {
CircularProgressIndicator(
modifier = Modifier.preferredSize(50.dp).padding(3.dp, 3.dp, 4.dp, 4.dp),
modifier = Modifier.size(50.dp).padding(3.dp, 3.dp, 4.dp, 4.dp),
color = DarkGreen
)
}
@ -97,7 +97,7 @@ fun setToolBar(
val backButtonHover = remember { mutableStateOf(false) }
Surface(
color = MiniatureColor,
modifier = Modifier.preferredHeight(44.dp)
modifier = Modifier.height(44.dp)
) {
Row(modifier = Modifier.padding(end = 30.dp)) {
Surface(
@ -125,7 +125,7 @@ fun setToolBar(
Image(
icBack(),
contentDescription = null,
modifier = Modifier.preferredSize(38.dp)
modifier = Modifier.size(38.dp)
)
}
}
@ -140,11 +140,11 @@ fun setToolBar(
Surface(
color = Color(255, 255, 255, 40),
modifier = Modifier.preferredSize(154.dp, 38.dp)
modifier = Modifier.size(154.dp, 38.dp)
.align(Alignment.CenterVertically),
shape = CircleShape
) {
val state = rememberScrollState(0f)
val state = rememberScrollState(0)
Row(modifier = Modifier.horizontalScroll(state)) {
Row {
for (type in FilterType.values()) {
@ -161,7 +161,7 @@ fun setToolBar(
fun FilterButton(
content: ContentState,
type: FilterType,
modifier: Modifier = Modifier.preferredSize(38.dp)
modifier: Modifier = Modifier.size(38.dp)
) {
val filterButtonHover = remember { mutableStateOf(false) }
Box(
@ -203,14 +203,14 @@ fun getFilterImage(type: FilterType, content: ContentState): ImageBitmap {
@Composable
fun setImage(content: ContentState) {
val drag = DragHandler()
val scale = ScaleHandler()
val drag = remember { DragHandler() }
val scale = remember { ScaleHandler() }
Surface(
color = DarkGray,
modifier = Modifier.fillMaxSize()
) {
Draggable(onDrag = drag, modifier = Modifier.fillMaxSize()) {
Draggable(dragHandler = drag, modifier = Modifier.fillMaxSize()) {
Zoomable(
onScale = scale,
modifier = Modifier.fillMaxSize()

30
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/MainScreen.kt

@ -14,9 +14,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.preferredHeight
import androidx.compose.foundation.layout.preferredSize
import androidx.compose.foundation.layout.preferredWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.foundation.rememberScrollState
@ -79,7 +79,7 @@ private fun setLoadingScreen(content: ContentState) {
Box(modifier = Modifier.align(Alignment.Center)) {
Surface(color = DarkGray, elevation = 4.dp, shape = CircleShape) {
CircularProgressIndicator(
modifier = Modifier.preferredSize(50.dp).padding(3.dp, 3.dp, 4.dp, 4.dp),
modifier = Modifier.size(50.dp).padding(3.dp, 3.dp, 4.dp, 4.dp),
color = DarkGreen
)
}
@ -108,7 +108,7 @@ fun setTitleBar(text: String, content: ContentState) {
TopAppBar(
backgroundColor = DarkGreen,
title = {
Row(Modifier.preferredHeight(50.dp)) {
Row(Modifier.height(50.dp)) {
Text(
text,
color = Foreground,
@ -140,7 +140,7 @@ fun setTitleBar(text: String, content: ContentState) {
Image(
icRefresh(),
contentDescription = null,
modifier = Modifier.preferredSize(35.dp)
modifier = Modifier.size(35.dp)
)
}
}
@ -158,7 +158,7 @@ fun setPreviewImageUI(content: ContentState) {
) {
Card(
backgroundColor = Transparent,
modifier = Modifier.preferredHeight(250.dp),
modifier = Modifier.height(250.dp),
shape = RectangleShape,
elevation = 1.dp
) {
@ -186,7 +186,7 @@ fun setMiniatureUI(
val infoButtonHover = remember { mutableStateOf(false) }
Card(
backgroundColor = if (cardHover.value) MiniatureHoverColor else MiniatureColor,
modifier = Modifier.padding(start = 10.dp, end = 18.dp).preferredHeight(70.dp)
modifier = Modifier.padding(start = 10.dp, end = 18.dp).height(70.dp)
.fillMaxWidth()
.hover(onEnter = {
cardHover.value = true
@ -212,8 +212,8 @@ fun setMiniatureUI(
toByteArray(picture.image)
).asImageBitmap(),
contentDescription = null,
modifier = Modifier.preferredHeight(70.dp)
.preferredWidth(90.dp)
modifier = Modifier.height(70.dp)
.width(90.dp)
.padding(start = 1.dp, top = 1.dp, end = 1.dp, bottom = 1.dp),
contentScale = ContentScale.Crop
)
@ -229,8 +229,8 @@ fun setMiniatureUI(
)
Clickable(
modifier = Modifier.preferredHeight(70.dp)
.preferredWidth(30.dp)
modifier = Modifier.height(70.dp)
.width(30.dp)
.hover(
onEnter = {
infoButtonHover.value = true
@ -254,8 +254,8 @@ fun setMiniatureUI(
Image(
icDots(),
contentDescription = null,
modifier = Modifier.preferredHeight(70.dp)
.preferredWidth(30.dp)
modifier = Modifier.height(70.dp)
.width(30.dp)
.padding(start = 1.dp, top = 25.dp, end = 1.dp, bottom = 25.dp),
contentScale = ContentScale.FillHeight
)
@ -270,7 +270,7 @@ fun setScrollableArea(content: ContentState) {
modifier = Modifier.fillMaxSize()
.padding(end = 8.dp)
) {
val stateVertical = rememberScrollState(0f)
val stateVertical = rememberScrollState(0)
Column(modifier = Modifier.verticalScroll(stateVertical)) {
var index = 1
Column {

4
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/Toast.kt

@ -3,7 +3,7 @@ package example.imageviewer.view
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.preferredSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Surface
import androidx.compose.material.Text
@ -43,7 +43,7 @@ fun Toast(
contentAlignment = Alignment.BottomCenter
) {
Surface(
modifier = Modifier.preferredSize(300.dp, 70.dp),
modifier = Modifier.size(300.dp, 70.dp),
color = ToastBackground,
shape = RoundedCornerShape(4.dp)
) {

18
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/Zoomable.kt

@ -1,7 +1,6 @@
package example.imageviewer.view
import androidx.compose.foundation.InteractionState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
@ -11,7 +10,9 @@ import androidx.compose.ui.focus.focusModifier
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.shortcuts
import androidx.compose.ui.input.pointer.pointerInput
import example.imageviewer.style.Transparent
import androidx.compose.runtime.DisposableEffect
@Composable
fun Zoomable(
@ -19,7 +20,7 @@ fun Zoomable(
modifier: Modifier = Modifier,
children: @Composable() () -> Unit
) {
val focusRequester = remember { FocusRequester() }
val focusRequester = FocusRequester()
Surface(
color = Transparent,
@ -36,8 +37,17 @@ fun Zoomable(
}
.focusRequester(focusRequester)
.focusModifier()
.clickable(interactionState = InteractionState(), indication = null) { focusRequester.requestFocus() }
.pointerInput(Unit) {
detectTapGestures(onDoubleTap = { onScale.resetFactor() }) {
focusRequester.requestFocus()
}
}
) {
children()
}
DisposableEffect(Unit) {
focusRequester.requestFocus()
onDispose { }
}
}

Loading…
Cancel
Save