Browse Source

Adopt ImageViewer to Compose 1.5.0-dev1114 and Kotlin 1.9.0 (#3400)

* ImageViewer. Add WindowsInsets.ime and update resources

* Update gradle properties

* Fix HorizontalPager usage

* Add ExperimentalForeignApi annotation

---------

Co-authored-by: dima.avdeev <dima.avdeev@jetbrains.com>
support/1.5.0-replace-warnings-with-errors
Ivan Matkov 11 months ago committed by GitHub
parent
commit
c09b344c03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      examples/imageviewer/README.md
  2. 4
      examples/imageviewer/gradle.properties
  3. 2
      examples/imageviewer/shared/src/androidMain/kotlin/example/imageviewer/platform.android.kt
  4. 2
      examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/platform.common.kt
  5. 8
      examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/GalleryScreen.kt
  6. 6
      examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/TopLayout.kt
  7. 2
      examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/platform.desktop.kt
  8. 28
      examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/platform.ios.kt
  9. 2
      examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/FileExtensions.kt
  10. 3
      examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/IosImageStorage.ios.kt
  11. 3
      examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/CameraView.ios.kt
  12. 2
      examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/LocationVisualizer.ios.kt

3
examples/imageviewer/README.md

@ -9,6 +9,9 @@ To setup the environment, please consult these [instructions](https://github.com
## How to run
If you already runned this sample before, then you need to execute command at least once:
`/gradlew podInstall`
Choose a run configuration for an appropriate target in IDE and run it.
![run-configurations.png](screenshots/run-configurations.png)

4
examples/imageviewer/gradle.properties

@ -11,6 +11,6 @@ kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.native.useEmbeddableCompilerJar=true
# Enable kotlin/native experimental memory model
kotlin.native.binary.memoryModel=experimental
kotlin.version=1.8.20
kotlin.version=1.9.0
agp.version=7.1.3
compose.version=1.4.1
compose.version=1.5.0-dev1114

2
examples/imageviewer/shared/src/androidMain/kotlin/example/imageviewer/platform.android.kt

@ -10,8 +10,6 @@ import androidx.compose.ui.graphics.vector.ImageVector
import kotlinx.coroutines.Dispatchers
import java.util.UUID
actual fun Modifier.notchPadding(): Modifier = this.displayCutoutPadding().statusBarsPadding()
class AndroidStorableImage(
val imageBitmap: ImageBitmap
)

2
examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/platform.common.kt

@ -4,8 +4,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import kotlinx.coroutines.CoroutineDispatcher
expect fun Modifier.notchPadding(): Modifier
expect class PlatformStorableImage
expect fun createUUID(): String

8
examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/GalleryScreen.kt

@ -56,7 +56,11 @@ fun GalleryScreen(
val imageProvider = LocalImageProvider.current
val viewScope = rememberCoroutineScope()
val pagerState = rememberPagerState(initialPage = selectedPictureIndex.value)
val pagerState = rememberPagerState(
initialPage = selectedPictureIndex.value,
initialPageOffsetFraction = 0f,
pageCount = { pictures.size },
)
LaunchedEffect(pagerState) {
// Subscribe to page changes
snapshotFlow { pagerState.currentPage }.collect { page ->
@ -116,7 +120,7 @@ fun GalleryScreen(
onClickPreviewPicture(pagerState.currentPage)
}
) {
HorizontalPager(pictures.size, state = pagerState) { index ->
HorizontalPager(state = pagerState) { index ->
val picture = pictures[index]
var image: ImageBitmap? by remember(picture) { mutableStateOf(null) }
LaunchedEffect(picture) {

6
examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/TopLayout.kt

@ -2,13 +2,15 @@ package example.imageviewer.view
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import example.imageviewer.notchPadding
@Composable
fun TopLayout(
@ -18,7 +20,7 @@ fun TopLayout(
Box(
Modifier
.fillMaxWidth()
.notchPadding()
.windowInsetsPadding(WindowInsets.systemBars)
.padding(12.dp)
) {
Row(Modifier.align(Alignment.CenterStart)) {

2
examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/platform.desktop.kt

@ -10,8 +10,6 @@ import androidx.compose.ui.unit.dp
import kotlinx.coroutines.Dispatchers
import java.util.UUID
actual fun Modifier.notchPadding(): Modifier = Modifier.padding(top = 12.dp)
class DesktopStorableImage(
val imageBitmap: ImageBitmap
)

28
examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/platform.ios.kt

@ -1,46 +1,22 @@
package example.imageviewer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import example.imageviewer.icon.IconIosShare
import kotlinx.cinterop.useContents
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import platform.CoreFoundation.CFUUIDCreate
import platform.CoreFoundation.CFUUIDCreateString
import platform.Foundation.CFBridgingRelease
import platform.UIKit.UIApplication
import platform.UIKit.UIImage
private val iosNotchInset = object : WindowInsets {
override fun getTop(density: Density): Int {
val safeAreaInsets = UIApplication.sharedApplication.keyWindow?.safeAreaInsets
return if (safeAreaInsets != null) {
val topInset = safeAreaInsets.useContents { this.top }
(topInset * density.density).toInt()
} else {
0
}
}
override fun getLeft(density: Density, layoutDirection: LayoutDirection): Int = 0
override fun getRight(density: Density, layoutDirection: LayoutDirection): Int = 0
override fun getBottom(density: Density): Int = 0
}
actual fun Modifier.notchPadding(): Modifier =
this.windowInsetsPadding(iosNotchInset)
class IosStorableImage(
val rawValue: UIImage
)
actual typealias PlatformStorableImage = IosStorableImage
@OptIn(ExperimentalForeignApi::class)
actual fun createUUID(): String =
CFBridgingRelease(CFUUIDCreateString(null, CFUUIDCreate(null))) as String

2
examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/FileExtensions.kt

@ -1,3 +1,5 @@
@file:OptIn(ExperimentalForeignApi::class)
package example.imageviewer.storage
import kotlinx.cinterop.*

3
examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/IosImageStorage.ios.kt

@ -7,6 +7,7 @@ import example.imageviewer.PlatformStorableImage
import example.imageviewer.model.PictureData
import example.imageviewer.toImageBitmap
import kotlinx.cinterop.CValue
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.useContents
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -122,6 +123,7 @@ class IosImageStorage(
}
}
@OptIn(ExperimentalForeignApi::class)
private fun UIImage.fitInto(px: Int): UIImage {
val targetScale = maxOf(
px.toFloat() / size.useContents { width },
@ -131,6 +133,7 @@ private fun UIImage.fitInto(px: Int): UIImage {
return resize(newSize)
}
@OptIn(ExperimentalForeignApi::class)
private fun UIImage.resize(targetSize: CValue<CGSize>): UIImage {
val currentSize = this.size
val widthRatio = targetSize.useContents { width } / currentSize.useContents { width }

3
examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/CameraView.ios.kt

@ -18,6 +18,7 @@ import example.imageviewer.model.GpsPosition
import example.imageviewer.model.PictureData
import example.imageviewer.model.createCameraPictureData
import kotlinx.cinterop.CValue
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.ObjCAction
import kotlinx.cinterop.useContents
import platform.AVFoundation.*
@ -121,6 +122,7 @@ private fun BoxScope.AuthorizedCamera(
}
}
@OptIn(ExperimentalForeignApi::class)
@Composable
private fun BoxScope.RealDeviceCamera(
camera: AVCaptureDevice,
@ -272,6 +274,7 @@ private fun BoxScope.RealDeviceCamera(
}
}
@OptIn(ExperimentalForeignApi::class)
fun CLLocation.toGps() =
GpsPosition(
latitude = coordinate.useContents { latitude },

2
examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/LocationVisualizer.ios.kt

@ -6,11 +6,13 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.interop.UIKitView
import example.imageviewer.model.GpsPosition
import kotlinx.cinterop.ExperimentalForeignApi
import platform.CoreLocation.CLLocationCoordinate2DMake
import platform.MapKit.MKCoordinateRegionMakeWithDistance
import platform.MapKit.MKMapView
import platform.MapKit.MKPointAnnotation
@OptIn(ExperimentalForeignApi::class)
@Composable
actual fun LocationVisualizer(
modifier: Modifier,

Loading…
Cancel
Save