### Basic ImagePreviewer Usage in Kotlin Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/image_previewer.md Demonstrates the fundamental setup and usage of the ImagePreviewer component. It involves preparing a list of image URLs, creating a PreviewerState, and configuring the ImagePreviewer with an image loader. Basic open and close operations are also shown. ```kotlin import androidx.compose.runtime.* import androidx.compose.ui.unit.dp import coil.compose.rememberAsyncImagePainter import com.github.panpf.sketch.compose.AsyncImage import com.github.panpf.sketch.images.Image import com.github.panpf.sketch.request.ImageRequest import com.github.panpf.zoomapk.ImagePreviewer import com.github.panpf.zoomapk.rememberPreviewerState // Prepare a list of image URLs val images = remember { mutableStateListOf( "https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF", "https://t7.baidu.com/it/u=4198287529,2774471735&fm=193&f=GIF" ) } // Declare a PreviewerState val state = rememberPreviewerState(pageCount = { images.size }) { images[it] } // Create an ImagePreviewer ImagePreviewer( state = state, imageLoader = { page -> val painter = rememberAsyncImagePainter(model = images[page]) Pair(painter, painter.intrinsicSize) } ) // Open state.open() // Close state.close() ``` -------------------------------- ### SamplingDecoder with Exif Rotation Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/sampling_decoder.md This example demonstrates how to read rotation information from Exif data in an image file and apply it when creating the SamplingDecoder. ```kotlin val file = // 图片文件 val inputStream = FileInputStream(file) val exifInterface = ExifInterface(file) val rotation = exifInterface.getDecoderRotation() val samplingDecoder = rememberSamplingDecoder(inputStream, rotation) ``` -------------------------------- ### Customizing ImagePreviewer Layers with Page Decorations Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/image_previewer.md Demonstrates how to customize the appearance of individual pages and the overall ImagePreviewer container. This involves using the `pageDecoration` lambda to add elements to each page and `previewerLayer` for container-level customization, such as setting background colors. ```kotlin import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.rememberAsyncImagePainter import com.github.panpf.zoomapk.ImagePreviewer import com.github.panpf.zoomapk.TransformLayerScope import com.github.panpf.zoomapk.rememberPreviewerState // Assuming 'state' and 'images' are already defined and properly initialized ImagePreviewer( state = state, imageLoader = { page -> val painter = rememberAsyncImagePainter(model = images[page]) Pair(painter, painter.intrinsicSize) }, pageDecoration = { _, innerPage -> var mounted = false // Set background color for each page Box(modifier = Modifier.background(Color.Cyan.copy(0.2F))) { // Call innerPage() to get the image loader state mounted = innerPage() // Set foreground layer Box( modifier = Modifier .padding(bottom = 48.dp) .size(56.dp) .shadow(4.dp, CircleShape) .background(Color.White) .align(Alignment.BottomCenter) ) { Text( modifier = Modifier.align(Alignment.Center), fontSize = 36.sp, text = "❤️" ) } } // Return the mounted status of the page mounted }, previewerLayer = TransformLayerScope( previewerDecoration = { innerPreviewer -> // Set the background color for the ImagePreviewer container Box( modifier = Modifier .background(Color.Black) ) { innerPreviewer.invoke() } } ) ) ``` -------------------------------- ### Kotlin Image Preview with Transform Animation Source: https://github.com/jvziyaoyao/scale/blob/main/README.md Demonstrates how to implement an image previewer with transition animations using Jetpack Compose. It includes setting up image data, managing the previewer state, and handling click events for entering and exiting the transformational view. ```kotlin val images = remember { listOf( // 依次声明图片的key、缩略图、原图(实际情况按实际情况来,这里只是示例) Triple("001", R.drawable.thumb_01, R.drawable.img_01), Triple("002", R.drawable.thumb_02, R.drawable.img_02), ) } // 为组件提供获取数据长度和获取key的方法 val previewerState = rememberPreviewerState( pageCount = { images.size }, getKey = { images[it].first } ) // 显示缩略图小图的示例代码 val index = 1 val scope = rememberCoroutineScope() TransformImageView( modifier = Modifier .size(120.dp) .clickable { scope.launch { // 点击事件触发动效 previewerState.enterTransform(index) } }, imageLoader = { val key = images[index].first val imageDrawableId = images[index].second val painter = painterResource(id = imageDrawableId) // 这里使用的是缩略图 // 必须依次返回key、图片数据、图片的尺寸 Triple(key, painter, painter.intrinsicSize) }, transformState = previewerState, ) // 这里声明图片预览组件 ImagePreviewer( state = previewerState, detectGesture = PagerGestureScope(onTap = { scope.launch { // 点击界面后关闭组件 previewerState.exitTransform() } }), imageLoader = { val painter = painterResource(id = images[it].third) // 这里使用的是原图 // 这里必须依次返回图片数据、图片的尺寸 return@ImagePreviewer Pair(painter, painter.intrinsicSize) } ) ``` -------------------------------- ### ImagePreviewer with TransformImageView for Transitions Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/image_previewer.md Shows how to use TransformImageView within ImagePreviewer to achieve smooth transition animations when opening the preview. This requires returning a Triple from the image loader, containing a key, painter, and intrinsic size. ```kotlin import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import coil.compose.rememberAsyncImagePainter import com.github.panpf.zoomapk.TransformImageView import com.github.panpf.zoomapk.rememberPreviewerState import kotlinx.coroutines.launch Box(modifier = Modifier.fillMaxSize()) { Row( modifier = Modifier.align(Alignment.Center), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { images.forEachIndexed { index, url -> TransformImageView( modifier = Modifier .size(120.dp) .clickable { scope.launch { state.enterTransform(index) } }, imageLoader = { val painter = rememberAsyncImagePainter(model = url) Triple(url, painter, painter.intrinsicSize) }, transformState = state ) } } } ``` -------------------------------- ### Manual SamplingDecoder Creation and Release Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/sampling_decoder.md Illustrates how to manually create a SamplingDecoder instance using a BitmapRegionDecoder. It also emphasizes the importance of releasing the decoder in `onDispose` to prevent memory leaks. ```kotlin val bitmapRegionDecoder = // 创建一个BitmapRegionDecoder val samplingDecoder = createSamplingDecoder(decoder, SamplingDecoder.Rotation.ROTATION_0) // 组件退出的时候release DisposableEffect(Unit) { onDispose { samplingDecoder.release() } } ``` -------------------------------- ### Simple SamplingDecoder Usage with ImageViewer Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/sampling_decoder.md Demonstrates the basic usage of SamplingDecoder within an ImageViewer component. It fetches an image input stream, creates a SamplingDecoder, and renders it using ZoomableState and ModelProcessor. ```kotlin val context = LocalContext.current val inputStream = remember { context.assets.open("a350.jpg") } val (samplingDecoder) = rememberSamplingDecoder(inputStream = inputStream) if (samplingDecoder != null) { val state = rememberZoomableState( contentSize = samplingDecoder.intrinsicSize ) ImageViewer( model = samplingDecoder, state = state, // 添加SamplingDecoder的支持 processor = ModelProcessor(samplingProcessorPair) ) } ``` -------------------------------- ### Basic Zoomable Image Component Source: https://github.com/jvziyaoyao/scale/blob/main/README.md Demonstrates how to use the ZoomableView component to display an image with zoom and pan gestures. It requires a Painter and a ZoomableState to manage the image's scale and offset. ```kotlin val painter = painterResource(id = R.drawable.light_02) val state = rememberZoomableState(contentSize = painter.intrinsicSize) ZoomableView(state = state) { Image( modifier = Modifier.fillMaxSize(), // 这里请务бя要充满整个图层 painter = painter, contentDescription = null, ) } ``` -------------------------------- ### ImagePreviewer with Key-Index Consistency for Transitions Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/image_previewer.md Illustrates how to ensure key-index consistency for animations when using TransformImageView, especially when images are represented by resource IDs. It involves providing a getKey function to PreviewerState and ensuring the Triple returned by imageLoader includes the key. ```kotlin import androidx.compose.runtime.* import androidx.compose.ui.res.painterResource import com.github.panpf.zoomapk.TransformImageView import com.github.panpf.zoomapk.rememberPreviewerState // Assuming R.drawable.img_01 and R.drawable.img_02 are valid drawable resources val images = remember { mutableStateListOf( // key to image "001" to R.drawable.img_01, "002" to R.drawable.img_02 ) } val state = rememberPreviewerState( pageCount = { images.size }, getKey = { index -> images[index].first } // Get the key ) images.forEachIndexed { index, image -> TransformImageView( imageLoader = { val painter = painterResource(id = image.second) // key model size Triple(image.first, painter, painter.intrinsicSize) } ) } // Index should be consistent with the key's position state.enterTransform(index) ``` -------------------------------- ### SamplingDecoder with Exception Handling Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/sampling_decoder.md This code shows how to use rememberSamplingDecoder and capture any exceptions that occur during the decoding process, such as unsupported image formats. ```kotlin // exception为报错信息 val (samplingDecoder,exception) = rememberSamplingDecoder(inputStream = inputStream) ``` -------------------------------- ### ImagePreviewer for Pop-up Previews Source: https://github.com/jvziyaoyao/scale/blob/main/README.md Shows how to use the ImagePreviewer component to display images in a pop-up preview. It manages preview state with rememberPreviewerState and includes gesture detection for actions like closing the preview. ```kotlin val images = remember { listOf( R.drawable.img_01, R.drawable.img_02, ) } val previewerState = rememberPreviewerState(pageCount = { images.size }) val scope = rememberCoroutineScope() ImagePreviewer( state = previewerState, detectGesture = PagerGestureScope(onTap = { scope.launch { // 关闭预览组件 previewerState.close() } }), imageLoader = { index -> val painter = painterResource(id = images[index]) Pair(painter, painter.intrinsicSize) } ) // 显示预览组件 previewerState.open() ``` -------------------------------- ### ImagePager for Image List Browsing Source: https://github.com/jvziyaoyao/scale/blob/main/README.md Demonstrates the ImagePager component for displaying a list of images. It uses a PagerState and an imageLoader lambda to provide Painter and intrinsicSize for each image in the list. ```kotlin val images = remember { mutableStateListOf( R.drawable.light_01, R.drawable.light_02, ) } ImagePager( modifier = Modifier.fillMaxSize(), pagerState = rememberZoomablePagerState { images.size }, imageLoader = { index -> val painter = painterResource(images[index]) return@ImagePager Pair(painter, painter.intrinsicSize) }, ) ``` -------------------------------- ### Add Scale Dependencies to Gradle Source: https://github.com/jvziyaoyao/scale/blob/main/README.md This snippet shows how to add the Scale image viewer and optional sampling decoder dependencies to your project's Gradle file. Ensure you have the mavenCentral() repository configured. ```kotlin repositories { mavenCentral() } val version = "1.1.1-beta.2" // 图片浏览库 implementation("com.jvziyaoyao.scale:image-viewer:$version") // 大型图片支持(可选) implementation("com.jvziyaoyao.scale:sampling-decoder:$version") ``` -------------------------------- ### Loading and Displaying Large Images Source: https://github.com/jvziyaoyao/scale/blob/main/README.md Illustrates how to load and display very large images using the SamplingDecoder. Ensure the 'sampling-decoder' dependency is included. The image data is provided as a ByteArray. ```kotlin implementation("com.jvziyaoyao.scale:sampling-decoder:$version") val bytes = remember { mutableStateOf(null) } LaunchedEffect(Unit) { bytes.value = Res.readBytes("files/a350.jpg") } val (samplingDecoder) = rememberSamplingDecoder(bytes.value) if (samplingDecoder != null) { val state = rememberZoomableState( contentSize = samplingDecoder.intrinsicSize ) ImageViewer( model = samplingDecoder, state = state, processor = ModelProcessor(samplingProcessorPair), ) } ``` -------------------------------- ### Add SamplingDecoder Dependency Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/sampling_decoder.md This snippet shows how to add the SamplingDecoder dependency to your project using Gradle. ```kotlin implementation("com.jvziyaoyao.scale:sampling-decoder:$version") ``` -------------------------------- ### ImageViewer Component for Image Display Source: https://github.com/jvziyaoyao/scale/blob/main/README.md Shows how to use the ImageViewer component for displaying images, including handling double-tap gestures for zooming. It utilizes a ZoomableState and can optionally take a ZoomableGestureScope for custom gesture handling. ```kotlin val scope = rememberCoroutineScope() val state = rememberZoomableState() ImageViewer( state = state, model = painterResource(id = R.drawable.light_02), modifier = Modifier.fillMaxSize(), detectGesture = ZoomableGestureScope(onDoubleTap = { // 双击放大缩小 scope.launch { state.toggleScale(it) } }) ) ``` -------------------------------- ### Direct SamplingCanvas Rendering with Gestures Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/sampling_decoder.md This snippet demonstrates direct rendering of a large image using SamplingCanvas. It includes custom gesture detection (pan and zoom) to control the image's offset and scale within a Box modifier. ```kotlin val context = LocalContext.current val inputStream = remember { context.assets.open("a350.jpg") } val (samplingDecoder) = rememberSamplingDecoder(inputStream = inputStream) if (samplingDecoder != null) { val offset = remember { mutableStateOf(Offset.Zero) } val scale = remember { mutableStateOf(1F) } Box( modifier = Modifier .fillMaxSize() .pointerInput(Unit) { detectTransformGestures { _, pan, zoom, _, _ -> offset.value += pan scale.value *= zoom true } } ) { val ratio = samplingDecoder.intrinsicSize.run { width.div(height) } Box( modifier = Modifier .graphicsLayer { translationX = offset.value.x translationY = offset.value.y scaleX = scale.value scaleY = scale.value } .fillMaxWidth() .aspectRatio(ratio) .align(Alignment.Center) ) { SamplingCanvas( samplingDecoder = samplingDecoder, viewPort = SamplingCanvasViewPort( scale = 8F, visualRect = Rect(0.4F, 0.4F, 0.6F, 0.8F) ) ) } } } ``` -------------------------------- ### Managing Multiple ImagePreviewers with ItemStateMap Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/image_previewer.md Explains how to handle scenarios where the same key might appear in different positions across multiple ImagePreviewer instances. This is achieved by using ItemStateMap to associate transform states with specific keys, preventing animation position conflicts. ```kotlin import androidx.compose.runtime.* import androidx.compose.ui.res.painterResource import com.github.panpf.zoomapk.ImagePreviewer import com.github.panpf.zoomapk.LocalTransformItemStateMap import com.github.panpf.zoomapk.TransformItemStateMap import com.github.panpf.zoomapk.rememberPreviewerState // Assuming R.drawable.img_03 and R.drawable.img_06 are valid drawable resources val imageIds = remember { listOf(R.drawable.img_03, R.drawable.img_06) } val itemStateMap01 = remember { mutableStateMapOf() } val previewerState01 = rememberPreviewerState( transformItemStateMap = itemStateMap01, pageCount = { imageIds.size }, getKey = { imageIds[it] }, ) val itemStateMap02 = remember { mutableStateMapOf() } val previewerState02 = rememberPreviewerState( transformItemStateMap = itemStateMap02, pageCount = { imageIds.size }, getKey = { imageIds[it] }, ) CompositionLocalProvider(LocalTransformItemStateMap provides itemStateMap01) { imageIds.forEach { ImagePreviewer( state = previewerState01, imageLoader = { /* ... */ } ) } } CompositionLocalProvider(LocalTransformItemStateMap provides itemStateMap02) { imageIds.forEach { ImagePreviewer( state = previewerState02, imageLoader = { /* ... */ } ) } } ``` -------------------------------- ### Using SamplingDecoder within ZoomableView Source: https://github.com/jvziyaoyao/scale/blob/main/doc/docs/sampling_decoder.md Shows how to integrate SamplingDecoder with ZoomableView for interactive zooming and panning of large images. It uses SamplingCanvas to render the decoded image within the ZoomableView. ```kotlin val state = rememberZoomableState(contentSize = samplingDecoder.intrinsicSize) ZoomableView(state = state) { SamplingCanvas( samplingDecoder = samplingDecoder, viewPort = state.getViewPort() ) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.