mirror of
https://github.com/jlengrand/compose-multiplatform.git
synced 2026-03-10 08:11:20 +00:00
ImageViewer material3 -> material (#2943)
This commit is contained in:
@@ -35,7 +35,6 @@ kotlin {
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material)
|
||||
implementation(compose.material3)
|
||||
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
|
||||
implementation(compose.components.resources)
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
||||
|
||||
@@ -13,8 +13,8 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
@@ -2,11 +2,8 @@ package example.imageviewer
|
||||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import androidx.compose.ui.Modifier
|
||||
import example.imageviewer.model.*
|
||||
import example.imageviewer.view.*
|
||||
|
||||
@@ -16,7 +13,6 @@ enum class ExternalImageViewerEvent {
|
||||
Escape,
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
internal fun ImageViewerCommon(
|
||||
dependencies: Dependencies
|
||||
@@ -48,68 +44,66 @@ internal fun ImageViewerWithProvidedDependencies(
|
||||
}
|
||||
}
|
||||
|
||||
Surface(modifier = Modifier.fillMaxSize()) {
|
||||
AnimatedContent(targetState = navigationStack.lastWithIndex(), transitionSpec = {
|
||||
val previousIdx = initialState.index
|
||||
val currentIdx = targetState.index
|
||||
val multiplier = if (previousIdx < currentIdx) 1 else -1
|
||||
if (initialState.value is GalleryPage && targetState.value is MemoryPage) {
|
||||
fadeIn() with fadeOut(tween(durationMillis = 500, 500))
|
||||
} else if (initialState.value is MemoryPage && targetState.value is GalleryPage) {
|
||||
fadeIn() with fadeOut(tween(delayMillis = 150))
|
||||
} else {
|
||||
slideInHorizontally { w -> multiplier * w } with
|
||||
slideOutHorizontally { w -> multiplier * -1 * w }
|
||||
}
|
||||
}) { (index, page) ->
|
||||
when (page) {
|
||||
is GalleryPage -> {
|
||||
GalleryScreen(
|
||||
pictures = pictures,
|
||||
selectedPictureIndex = selectedPictureIndex,
|
||||
onClickPreviewPicture = { previewPictureId ->
|
||||
navigationStack.push(MemoryPage(previewPictureId))
|
||||
}
|
||||
) {
|
||||
navigationStack.push(CameraPage())
|
||||
AnimatedContent(targetState = navigationStack.lastWithIndex(), transitionSpec = {
|
||||
val previousIdx = initialState.index
|
||||
val currentIdx = targetState.index
|
||||
val multiplier = if (previousIdx < currentIdx) 1 else -1
|
||||
if (initialState.value is GalleryPage && targetState.value is MemoryPage) {
|
||||
fadeIn() with fadeOut(tween(durationMillis = 500, 500))
|
||||
} else if (initialState.value is MemoryPage && targetState.value is GalleryPage) {
|
||||
fadeIn() with fadeOut(tween(delayMillis = 150))
|
||||
} else {
|
||||
slideInHorizontally { w -> multiplier * w } with
|
||||
slideOutHorizontally { w -> multiplier * -1 * w }
|
||||
}
|
||||
}) { (index, page) ->
|
||||
when (page) {
|
||||
is GalleryPage -> {
|
||||
GalleryScreen(
|
||||
pictures = pictures,
|
||||
selectedPictureIndex = selectedPictureIndex,
|
||||
onClickPreviewPicture = { previewPictureId ->
|
||||
navigationStack.push(MemoryPage(previewPictureId))
|
||||
}
|
||||
) {
|
||||
navigationStack.push(CameraPage())
|
||||
}
|
||||
}
|
||||
|
||||
is FullScreenPage -> {
|
||||
FullscreenImageScreen(
|
||||
picture = page.picture,
|
||||
back = {
|
||||
navigationStack.back()
|
||||
is FullScreenPage -> {
|
||||
FullscreenImageScreen(
|
||||
picture = page.picture,
|
||||
back = {
|
||||
navigationStack.back()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
is MemoryPage -> {
|
||||
MemoryScreen(
|
||||
pictures = pictures,
|
||||
memoryPage = page,
|
||||
onSelectRelatedMemory = { galleryId ->
|
||||
navigationStack.push(MemoryPage(galleryId))
|
||||
},
|
||||
onBack = {
|
||||
navigationStack.back()
|
||||
},
|
||||
onHeaderClick = { galleryId ->
|
||||
navigationStack.push(FullScreenPage(galleryId))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
is CameraPage -> {
|
||||
CameraScreen(
|
||||
onBack = { resetSelectedPicture ->
|
||||
if (resetSelectedPicture) {
|
||||
selectedPictureIndex.value = 0
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
is MemoryPage -> {
|
||||
MemoryScreen(
|
||||
pictures = pictures,
|
||||
memoryPage = page,
|
||||
onSelectRelatedMemory = { galleryId ->
|
||||
navigationStack.push(MemoryPage(galleryId))
|
||||
},
|
||||
onBack = {
|
||||
navigationStack.back()
|
||||
},
|
||||
onHeaderClick = { galleryId ->
|
||||
navigationStack.push(FullScreenPage(galleryId))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
is CameraPage -> {
|
||||
CameraScreen(
|
||||
onBack = { resetSelectedPicture ->
|
||||
if (resetSelectedPicture) {
|
||||
selectedPictureIndex.value = 0
|
||||
}
|
||||
navigationStack.back()
|
||||
},
|
||||
)
|
||||
}
|
||||
navigationStack.back()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package example.imageviewer.style
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ProvideTextStyle
|
||||
import androidx.compose.material.LocalTextStyle
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.ProvideTextStyle
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -51,7 +51,7 @@ object ImageviewerColors {
|
||||
internal fun ImageViewerTheme(content: @Composable () -> Unit) {
|
||||
isSystemInDarkTheme() // todo check and change colors
|
||||
MaterialTheme(
|
||||
colorScheme = MaterialTheme.colorScheme.copy(
|
||||
colors = MaterialTheme.colors.copy(
|
||||
background = ImageviewerColors.background,
|
||||
onBackground = ImageviewerColors.onBackground
|
||||
)
|
||||
|
||||
@@ -84,8 +84,6 @@ internal fun FullscreenImageScreen(
|
||||
)
|
||||
ZoomControllerView(Modifier, scalableState)
|
||||
}
|
||||
} else {
|
||||
LoadingScreen()
|
||||
}
|
||||
|
||||
TopLayout(
|
||||
|
||||
@@ -2,30 +2,20 @@
|
||||
|
||||
package example.imageviewer.view
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedContentScope
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.with
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.itemsIndexed
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.unit.dp
|
||||
import example.imageviewer.*
|
||||
import example.imageviewer.model.*
|
||||
@@ -33,7 +23,6 @@ import example.imageviewer.style.ImageviewerColors
|
||||
import org.jetbrains.compose.resources.ExperimentalResourceApi
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
|
||||
|
||||
enum class GalleryStyle {
|
||||
SQUARES,
|
||||
LIST
|
||||
@@ -75,7 +64,7 @@ internal fun GalleryScreen(
|
||||
}
|
||||
}
|
||||
|
||||
Column(modifier = Modifier.background(MaterialTheme.colorScheme.background)) {
|
||||
Column(modifier = Modifier.background(MaterialTheme.colors.background)) {
|
||||
Box {
|
||||
picture?.let {
|
||||
PreviewImage(
|
||||
@@ -125,21 +114,19 @@ private fun SquaresGalleryView(
|
||||
selectedImage: PictureData?,
|
||||
onSelect: (PictureData) -> Unit,
|
||||
) {
|
||||
Column {
|
||||
Spacer(Modifier.height(4.dp))
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(minSize = 130.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(1.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(1.dp)
|
||||
) {
|
||||
itemsIndexed(images) { idx, picture ->
|
||||
val isSelected = picture == selectedImage
|
||||
SquareThumbnail(
|
||||
picture = picture,
|
||||
onClick = { onSelect(picture) },
|
||||
isHighlighted = isSelected
|
||||
)
|
||||
}
|
||||
LazyVerticalGrid(
|
||||
modifier = Modifier.padding(top = 4.dp),
|
||||
columns = GridCells.Adaptive(minSize = 130.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(1.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(1.dp)
|
||||
) {
|
||||
itemsIndexed(images) { idx, picture ->
|
||||
val isSelected = picture == selectedImage
|
||||
SquareThumbnail(
|
||||
picture = picture,
|
||||
onClick = { onSelect(picture) },
|
||||
isHighlighted = isSelected
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package example.imageviewer.view
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
internal fun LoadingScreen(text: String = "") {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize().background(color = MaterialTheme.colorScheme.background)
|
||||
) {
|
||||
Box(modifier = Modifier.align(Alignment.Center)) {
|
||||
Surface(/*elevation = 4.dp, */shape = CircleShape) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(50.dp).padding(3.dp, 3.dp, 4.dp, 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = text,
|
||||
modifier = Modifier.align(Alignment.Center).offset(0.dp, 70.dp),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -25,14 +25,13 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import example.imageviewer.ImageProvider
|
||||
import example.imageviewer.LocalImageProvider
|
||||
import example.imageviewer.model.*
|
||||
import example.imageviewer.style.ImageviewerColors
|
||||
import org.jetbrains.compose.resources.ExperimentalResourceApi
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
|
||||
@OptIn(ExperimentalResourceApi::class, ExperimentalMaterial3Api::class)
|
||||
@OptIn(ExperimentalResourceApi::class)
|
||||
@Composable
|
||||
internal fun MemoryScreen(
|
||||
pictures: SnapshotStateList<PictureData>,
|
||||
@@ -71,12 +70,12 @@ internal fun MemoryScreen(
|
||||
)
|
||||
}
|
||||
}
|
||||
Box(modifier = Modifier.background(MaterialTheme.colorScheme.background)) {
|
||||
Box(modifier = Modifier.background(MaterialTheme.colors.background)) {
|
||||
Column {
|
||||
Headliner("Note")
|
||||
Collapsible(memoryPage.picture.description)
|
||||
Headliner("Related memories")
|
||||
RelatedMemoriesVisualizer(pictures, imageProvider, onSelectRelatedMemory)
|
||||
RelatedMemoriesVisualizer(pictures, onSelectRelatedMemory)
|
||||
Headliner("Place")
|
||||
val locationShape = RoundedCornerShape(10.dp)
|
||||
LocationVisualizer(
|
||||
@@ -224,7 +223,6 @@ internal fun Headliner(s: String) {
|
||||
@Composable
|
||||
internal fun RelatedMemoriesVisualizer(
|
||||
ps: List<PictureData>,
|
||||
imageProvider: ImageProvider,
|
||||
onSelectRelatedMemory: (PictureData) -> Unit
|
||||
) {
|
||||
Box(
|
||||
@@ -235,7 +233,7 @@ internal fun RelatedMemoriesVisualizer(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
itemsIndexed(ps) { idx, item ->
|
||||
RelatedMemory(idx, item, imageProvider, onSelectRelatedMemory)
|
||||
RelatedMemory(item, onSelectRelatedMemory)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,9 +241,7 @@ internal fun RelatedMemoriesVisualizer(
|
||||
|
||||
@Composable
|
||||
internal fun RelatedMemory(
|
||||
index: Int,
|
||||
galleryEntry: PictureData,
|
||||
imageProvider: ImageProvider,
|
||||
onSelectRelatedMemory: (PictureData) -> Unit
|
||||
) {
|
||||
Box(Modifier.size(130.dp).clip(RoundedCornerShape(8.dp))) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -19,7 +19,7 @@ import example.imageviewer.model.PictureData
|
||||
import org.jetbrains.compose.resources.ExperimentalResourceApi
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
|
||||
@OptIn(ExperimentalResourceApi::class, ExperimentalMaterial3Api::class)
|
||||
@OptIn(ExperimentalResourceApi::class)
|
||||
@Composable
|
||||
internal fun Thumbnail(
|
||||
picture: PictureData,
|
||||
@@ -30,41 +30,39 @@ internal fun Thumbnail(
|
||||
Card(
|
||||
modifier = Modifier.padding(start = 10.dp, end = 10.dp).height(70.dp)
|
||||
.fillMaxWidth(),
|
||||
onClick = { onClickSelect() },
|
||||
shape = RoundedCornerShape(200.dp),
|
||||
border = BorderStroke(1.dp, Color.White),
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = MaterialTheme.colorScheme.background,
|
||||
contentColor = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
|
||||
backgroundColor = MaterialTheme.colors.background,
|
||||
contentColor = MaterialTheme.colors.onBackground
|
||||
) {
|
||||
Row(modifier = Modifier.padding(end = 30.dp)) {
|
||||
Tooltip(picture.name) {
|
||||
ThumbnailImage(
|
||||
modifier = Modifier.size(70.dp)
|
||||
.clip(CircleShape)
|
||||
.border(BorderStroke(1.dp, Color.White), CircleShape)
|
||||
.clickable { onClickFullScreen() },
|
||||
picture = picture,
|
||||
Box(Modifier.clickable { onClickSelect() }) {
|
||||
Row(modifier = Modifier.padding(end = 30.dp)) {
|
||||
Tooltip(picture.name) {
|
||||
ThumbnailImage(
|
||||
modifier = Modifier.size(70.dp)
|
||||
.clip(CircleShape)
|
||||
.border(BorderStroke(1.dp, Color.White), CircleShape)
|
||||
.clickable { onClickFullScreen() },
|
||||
picture = picture,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = picture.name,
|
||||
modifier = Modifier.weight(1f).align(Alignment.CenterVertically)
|
||||
.padding(start = 16.dp),
|
||||
style = MaterialTheme.typography.subtitle1
|
||||
)
|
||||
|
||||
Image(
|
||||
painterResource("dots.png"),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.height(70.dp)
|
||||
.width(30.dp)
|
||||
.padding(start = 1.dp, top = 25.dp, end = 1.dp, bottom = 25.dp)
|
||||
.clickable { onClickInfo() },
|
||||
contentScale = ContentScale.FillHeight
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = picture.name,
|
||||
modifier = Modifier.weight(1f).align(Alignment.CenterVertically)
|
||||
.padding(start = 16.dp),
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
)
|
||||
|
||||
Image(
|
||||
painterResource("dots.png"),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.height(70.dp)
|
||||
.width(30.dp)
|
||||
.padding(start = 1.dp, top = 25.dp, end = 1.dp, bottom = 25.dp)
|
||||
.clickable { onClickInfo() },
|
||||
contentScale = ContentScale.FillHeight
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ 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.material3.*
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
|
||||
@@ -6,8 +6,8 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -15,8 +15,6 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import example.imageviewer.*
|
||||
import example.imageviewer.LocalLocalization
|
||||
import example.imageviewer.createNewPhotoNameAndDescription
|
||||
import example.imageviewer.model.PictureData
|
||||
import example.imageviewer.model.createCameraPictureData
|
||||
import org.jetbrains.compose.resources.ExperimentalResourceApi
|
||||
|
||||
@@ -2,9 +2,9 @@ package example.imageviewer.view
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
Reference in New Issue
Block a user