改包名com.aiosman.ravenow
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package com.aiosman.ravenow.ui.imageviewer
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.aiosman.ravenow.entity.MomentImageEntity
|
||||
|
||||
object ImageViewerViewModel:ViewModel() {
|
||||
var imageList = mutableListOf<MomentImageEntity>()
|
||||
var initialIndex = 0
|
||||
fun asNew(images: List<MomentImageEntity>, index: Int = 0) {
|
||||
imageList.clear()
|
||||
imageList.addAll(images)
|
||||
initialIndex = index
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.aiosman.ravenow.LocalNavController
|
||||
import com.aiosman.ravenow.R
|
||||
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
||||
import com.aiosman.ravenow.ui.composables.StatusBarMaskLayout
|
||||
import com.aiosman.ravenow.ui.imageviewer.ImageViewerViewModel
|
||||
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||
import com.aiosman.ravenow.utils.FileUtil.saveImageToGallery
|
||||
import kotlinx.coroutines.launch
|
||||
import net.engawapg.lib.zoomable.rememberZoomState
|
||||
import net.engawapg.lib.zoomable.zoomable
|
||||
|
||||
|
||||
@OptIn(
|
||||
ExperimentalFoundationApi::class,
|
||||
)
|
||||
@Composable
|
||||
fun ImageViewer() {
|
||||
val model = ImageViewerViewModel
|
||||
val images = model.imageList
|
||||
val pagerState =
|
||||
rememberPagerState(pageCount = { images.size }, initialPage = model.initialIndex)
|
||||
val navController = LocalNavController.current
|
||||
val context = LocalContext.current
|
||||
val navigationBarPaddings =
|
||||
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 16.dp
|
||||
val scope = rememberCoroutineScope()
|
||||
val showRawImageStates = remember { mutableStateListOf(*Array(images.size) { false }) }
|
||||
var isDownloading by remember { mutableStateOf(false) }
|
||||
var currentPage by remember { mutableStateOf(model.initialIndex) }
|
||||
LaunchedEffect(pagerState) {
|
||||
currentPage = pagerState.currentPage
|
||||
}
|
||||
StatusBarMaskLayout(
|
||||
modifier = Modifier.background(Color.Black),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Black),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
HorizontalPager(
|
||||
state = pagerState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(0.8f),
|
||||
) { page ->
|
||||
val zoomState = rememberZoomState()
|
||||
CustomAsyncImage(
|
||||
context,
|
||||
if (showRawImageStates[page]) images[page].url else images[page].thumbnail,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.zoomable(
|
||||
zoomState = zoomState,
|
||||
onTap = {
|
||||
navController.navigateUp()
|
||||
}
|
||||
)
|
||||
,
|
||||
contentScale = ContentScale.Fit,
|
||||
)
|
||||
}
|
||||
Box(modifier = Modifier.padding(top = 10.dp, bottom = 10.dp)){
|
||||
if (images.size > 1) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(Color(0xff333333).copy(alpha = 0.6f))
|
||||
.padding(vertical = 4.dp, horizontal = 24.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "${pagerState.currentPage + 1}/${images.size}",
|
||||
color = Color.White,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(0.2f)
|
||||
.background(
|
||||
Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
Color.Transparent,
|
||||
Color.Black
|
||||
),
|
||||
)
|
||||
)
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = navigationBarPaddings),
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 72.dp, end = 72.dp)
|
||||
.padding(top = 16.dp),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.noRippleClickable {
|
||||
if (isDownloading) {
|
||||
return@noRippleClickable
|
||||
}
|
||||
isDownloading = true
|
||||
scope.launch {
|
||||
saveImageToGallery(context, images[pagerState.currentPage].url)
|
||||
isDownloading = false
|
||||
}
|
||||
}
|
||||
) {
|
||||
if (isDownloading) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(32.dp),
|
||||
color = Color.White
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.rider_pro_download_icon),
|
||||
contentDescription = "",
|
||||
modifier = Modifier.size(32.dp),
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
stringResource(R.string.download),
|
||||
color = Color.White
|
||||
)
|
||||
}
|
||||
if (!showRawImageStates[pagerState.currentPage]) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
if (!showRawImageStates[pagerState.currentPage]) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.noRippleClickable {
|
||||
showRawImageStates[pagerState.currentPage] = true
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.rider_pro_original_raw),
|
||||
contentDescription = "",
|
||||
modifier = Modifier.size(32.dp),
|
||||
tint = Color.White
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
stringResource(R.string.original),
|
||||
color = Color.White
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user