Skip to content

Commit

Permalink
feat: add selected view in the preview screens
Browse files Browse the repository at this point in the history
  • Loading branch information
huhx committed Feb 20, 2024
1 parent 80f03d8 commit 5ab5fcc
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 45 deletions.
2 changes: 1 addition & 1 deletion app/src/main/java/com/huhx/picker/AppRoute.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fun AppRoute(
) {
NavHost(
navController = navController,
startDestination = "moment_list",
startDestination = "asset_picker",
) {
composable("moment_list") {
MomentListScreen(viewModel) { navController.navigate("moment_add") }
Expand Down
24 changes: 24 additions & 0 deletions app/src/main/java/com/huhx/picker/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import com.huhx.picker.model.AssetInfo
import com.huhx.picker.model.AssetResourceType
import com.huhx.picker.ui.theme.Compose_image_pickerTheme
import com.huhx.picker.view.AssetImageIndicator
import com.huhx.picker.view.SelectorBottomBar

class MainActivity : ComponentActivity() {

Expand Down Expand Up @@ -165,6 +166,29 @@ fun AssetImageIndicatorPreview() {
assetSelected = list
)
}
}

@Preview
@Composable
fun AssetPreviewScreenPreview() {
val assetInfo = AssetInfo(
id = 8L,
filepath = "https://huhx-family.oss-cn-beijing.aliyuncs.com/20220116082003904824.jpg",
uriString = "https://huhx-family.oss-cn-beijing.aliyuncs.com/20220116082003904824.jpg",
filename = "test.jpeg",
directory = "Picture",
mediaType = 1,
size = 1150260,
mimeType = "img/jpeg",
duration = 16000,
date = 23423434433
)
val list = listOf(assetInfo, assetInfo)
val selectedList = SnapshotStateList<AssetInfo>()
selectedList.add(assetInfo)
selectedList.add(assetInfo)

Compose_image_pickerTheme {
SelectorBottomBar(assetInfo = assetInfo, selectedList = selectedList, onClick = {}, onSelectedClick = {})
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.huhx.picker.component

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -31,6 +34,7 @@ import coil.compose.AsyncImagePainter
import coil.decode.VideoFrameDecoder
import coil.request.ImageRequest
import com.huhx.picker.R
import com.huhx.picker.model.AssetInfo
import com.huhx.picker.model.AssetResourceType

@OptIn(ExperimentalFoundationApi::class)
Expand Down Expand Up @@ -110,6 +114,75 @@ fun AssetImageItem(
}
}

if (resourceType == AssetResourceType.GIF) {
Box(
modifier = Modifier
.padding(bottom = 4.dp, end = 6.dp)
.background(
color = Color(0F, 0F, 0F, 0.4F),
shape = RoundedCornerShape(8.dp)
)
) {
Text(
modifier = Modifier.padding(horizontal = 6.dp, vertical = 1.dp),
text = stringResource(R.string.text_gif),
color = Color.White,
fontSize = 10.sp
)
}
}
}
}

@Composable
fun SelectedAssetImageItem(
assetInfo: AssetInfo,
isSelected: Boolean,
modifier: Modifier = Modifier,
resourceType: AssetResourceType = AssetResourceType.IMAGE,
durationString: String? = null,
filterQuality: FilterQuality = FilterQuality.None,
onClick: (AssetInfo) -> Unit,
) {
val (backgroundColor, alpha) = if (isSelected) {
Pair(Color.Black, 0.6F)
} else {
Pair(Color.Transparent, 1F)
}
val context = LocalContext.current

Box(
modifier = modifier
.background(backgroundColor)
.alpha(alpha),
) {
AsyncImage(
model = ImageRequest.Builder(context)
.data(assetInfo.uriString)
.decoderFactory(VideoFrameDecoder.Factory())
.crossfade(true)
.build(),
modifier = modifier
.aspectRatio(1.0F)
.then(if (isSelected) Modifier.border(BorderStroke(width = 1.dp, color = Color.Red)) else Modifier)
.padding(horizontal = 3.dp, vertical = 2.dp)
.clickable { onClick(assetInfo) },
filterQuality = filterQuality,
contentScale = ContentScale.Crop,
contentDescription = null
)

if (resourceType == AssetResourceType.VIDEO) {
Column(modifier = Modifier.align(Alignment.BottomEnd)) {
Text(
modifier = Modifier.padding(bottom = 3.dp, end = 3.dp),
text = durationString ?: "00:00",
color = Color.White,
fontSize = 10.sp
)
}
}

if (resourceType == AssetResourceType.GIF) {
Box(
modifier = Modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.provider.MediaStore
import com.huhx.picker.util.StringUtil
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter

data class AssetInfo(
Expand Down Expand Up @@ -35,6 +37,11 @@ data class AssetInfo(
return BitmapFactory.decodeFile(uriString)
}

val dateString: String get() {
val instant = Instant.ofEpochMilli(date)
return instant.atZone(ZoneId.systemDefault()).toLocalDate().toString()
}

val resourceType: AssetResourceType = AssetResourceType.fromFileName(filename)

// todo: 这种方式还是存在问题
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
@file:OptIn(ExperimentalMaterial3Api::class)

package com.huhx.picker.view

import android.os.Build
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.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState
Expand All @@ -24,12 +30,14 @@ import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -52,22 +60,64 @@ import coil.decode.GifDecoder
import coil.decode.ImageDecoderDecoder
import coil.request.ImageRequest
import com.huhx.picker.R
import com.huhx.picker.component.SelectedAssetImageItem
import com.huhx.picker.model.AssetInfo
import kotlinx.coroutines.launch

@UnstableApi
@Composable
internal fun AssetPreviewScreen(
fun AssetPreviewScreen(
index: Int,
assets: List<AssetInfo>,
navigateUp: () -> Unit,
selectedList: SnapshotStateList<AssetInfo>,
) {
val pageState = rememberPagerState(initialPage = index, pageCount = assets::size)
val scope = rememberCoroutineScope()
val titleString = if (assets[pageState.currentPage].isImage()) "图片" else "视频"

Scaffold(
topBar = { PreviewTopAppBar(navigateUp = navigateUp) },
topBar = {
CenterAlignedTopAppBar(
modifier = Modifier.statusBarsPadding(),
title = {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = titleString,
style = MaterialTheme.typography.bodyLarge.copy(fontSize = 18.sp, color = Color.White)
)
Text(
text = assets[pageState.currentPage].dateString,
style = MaterialTheme.typography.bodyMedium.copy(color = Color.Gray)
)
}
},
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(containerColor = Color.Black),
navigationIcon = {
IconButton(onClick = navigateUp) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, tint = Color.White, contentDescription = "")
}
},
actions = {
Text(
modifier = Modifier.padding(horizontal = 4.dp),
text = "${pageState.currentPage + 1}/${assets.size}",
style = MaterialTheme.typography.bodyLarge.copy(fontSize = 18.sp, color = Color.White)
)
},
)
},
bottomBar = {
SelectorBottomBar(selectedList = selectedList, assetInfo = assets[pageState.currentPage]) {
SelectorBottomBar(
selectedList = selectedList,
assetInfo = assets[pageState.currentPage],
onSelectedClick = { asset ->
val selectedIndex = assets.indexOfFirst { it.id == asset.id }
scope.launch {
pageState.animateScrollToPage(selectedIndex)
}
}
) {
navigateUp()
if (selectedList.isEmpty()) selectedList.add(it)
}
Expand All @@ -83,54 +133,62 @@ internal fun AssetPreviewScreen(
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun PreviewTopAppBar(navigateUp: () -> Unit) {
CenterAlignedTopAppBar(
modifier = Modifier.statusBarsPadding(),
title = {},
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(containerColor = Color.Black),
navigationIcon = {
IconButton(onClick = navigateUp) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, tint = Color.White, contentDescription = "")
}
}
)
}

@UnstableApi
@Composable
private fun SelectorBottomBar(
fun SelectorBottomBar(
assetInfo: AssetInfo,
selectedList: SnapshotStateList<AssetInfo>,
onSelectedClick: (AssetInfo) -> Unit,
onClick: (AssetInfo) -> Unit,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.background(color = Color.Black.copy(alpha = 0.9F))
.padding(horizontal = 10.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(verticalAlignment = Alignment.CenterVertically) {
AssetImageIndicator(
assetInfo = assetInfo,
selected = selectedList.any { it == assetInfo },
assetSelected = selectedList,
fontSize = 14.sp,
size = 22.dp
)
Spacer(modifier = Modifier.width(6.dp))
Text(text = stringResource(R.string.text_asset_select), color = Color.White, fontSize = 14.sp)
Column {
if (selectedList.isNotEmpty()) {
LazyRow(
modifier = Modifier
.fillMaxWidth()
.background(Color.Black.copy(alpha = 0.8F))
.padding(horizontal = 2.dp, vertical = 2.dp)
) {
itemsIndexed(selectedList) { _, resource ->
SelectedAssetImageItem(
assetInfo = resource,
isSelected = resource.id == assetInfo.id,
resourceType = resource.resourceType,
modifier = Modifier.size(64.dp),
onClick = onSelectedClick
)
}
}
}
Button(
modifier = Modifier.defaultMinSize(minHeight = 1.dp, minWidth = 1.dp),
shape = RoundedCornerShape(5.dp),
enabled = true,
contentPadding = PaddingValues(horizontal = 20.dp, vertical = 6.dp),
onClick = { onClick(assetInfo) }

Row(
modifier = Modifier
.fillMaxWidth()
.background(color = Color.Black.copy(alpha = 0.9F))
.padding(horizontal = 10.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(stringResource(R.string.text_done), color = Color.White, fontSize = 15.sp)
Row(verticalAlignment = Alignment.CenterVertically) {
AssetImageIndicator(
assetInfo = assetInfo,
selected = selectedList.any { it == assetInfo },
assetSelected = selectedList,
fontSize = 14.sp,
size = 22.dp
)
Spacer(modifier = Modifier.width(6.dp))
Text(text = stringResource(R.string.text_asset_select), color = Color.White, fontSize = 14.sp)
}
Button(
modifier = Modifier.defaultMinSize(minHeight = 1.dp, minWidth = 1.dp),
shape = RoundedCornerShape(5.dp),
enabled = true,
contentPadding = PaddingValues(horizontal = 20.dp, vertical = 6.dp),
onClick = { onClick(assetInfo) }
) {
Text(stringResource(R.string.text_done), color = Color.White, fontSize = 15.sp)
}
}
}
}
Expand Down

0 comments on commit 5ab5fcc

Please sign in to comment.