pref: 看图优化

This commit is contained in:
HuanCheng65 2023-09-21 16:10:27 +08:00
parent c112cf79eb
commit cbf1fe64c4
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
4 changed files with 81 additions and 89 deletions

View File

@ -157,7 +157,6 @@ dependencies {
implementation "io.github.panpf.sketch3:sketch-compose:$sketch_version"
implementation "io.github.panpf.sketch3:sketch-extensions:$sketch_version"
implementation "io.github.panpf.sketch3:sketch-gif-movie:$sketch_version"
implementation "io.github.panpf.sketch3:sketch-zoom:$sketch_version"
implementation "io.github.panpf.sketch3:sketch-okhttp:$sketch_version"
def zoomimage_version = "1.0.0-alpha03"

View File

@ -29,22 +29,22 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
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.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import com.github.panpf.sketch.displayImage
import com.github.panpf.sketch.zoom.Edge
import com.github.panpf.sketch.zoom.ReadModeDecider
import com.github.panpf.sketch.zoom.SketchZoomImageView
import com.github.panpf.sketch.request.DisplayRequest
import com.github.panpf.zoomimage.SketchZoomAsyncImage
import com.google.accompanist.systemuicontroller.SystemUiController
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.arch.BaseComposeActivityWithParcelable
import com.huanchengfly.tieba.post.arch.collectPartialAsState
@ -56,65 +56,40 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad
import com.huanchengfly.tieba.post.ui.widgets.compose.ProvideContentColor
import com.huanchengfly.tieba.post.utils.ImageUtil
import com.huanchengfly.tieba.post.utils.download
import kotlinx.coroutines.launch
import kotlin.math.abs
import kotlinx.collections.immutable.persistentListOf
import kotlin.math.roundToInt
object MyReadModeDecider : ReadModeDecider {
override fun should(
imageWidth: Int,
imageHeight: Int,
viewWidth: Int,
viewHeight: Int
): Boolean {
val imageAspectRatio = imageHeight.toFloat() / imageWidth
val viewAspectRatio = viewHeight.toFloat() / viewWidth
return if (viewAspectRatio > 1f) {
imageAspectRatio >= viewAspectRatio * 1.25f
} else {
imageAspectRatio >= (1f / viewAspectRatio) * 3f
}
}
}
@Composable
private fun ViewPhoto(
imageUri: String,
modifier: Modifier = Modifier,
onDrag: ((dx: Float, dy: Float, isAtEdge: Boolean) -> Unit)? = null
onTap: (offset: Offset) -> Unit = {},
) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center
) {
var progress by remember { mutableStateOf(0f) }
val context = LocalContext.current
var progress by remember { mutableFloatStateOf(0f) }
var showProgress by remember { mutableStateOf(true) }
AndroidView(
factory = {
SketchZoomImageView(it).apply {
readModeEnabled = true
readModeDecider = MyReadModeDecider
allowParentInterceptOnEdge = true
addOnViewDragListener { dx, dy ->
val isAtEdge = horScrollEdge != Edge.NONE
onDrag?.invoke(dx, dy, isAtEdge)
}
}
},
modifier = Modifier.fillMaxSize(),
update = {
it.displayImage(imageUri) {
listener(
val request = remember(imageUri) {
DisplayRequest.Builder(context, imageUri)
.listener(
onStart = { showProgress = true },
onSuccess = { _, _ -> showProgress = false },
onError = { _, _ -> showProgress = false },
onCancel = { showProgress = false }
)
progressListener { _, totalLength: Long, completedLength: Long ->
progress = (completedLength.toDouble() / totalLength).toFloat()
}
.progressListener { _, totalLength, completedLength ->
progress = completedLength.toFloat() / totalLength
}
.build()
}
SketchZoomAsyncImage(
request = request,
contentDescription = null,
modifier = Modifier.fillMaxSize(),
onTap = onTap,
)
if (showProgress) {
Box(
@ -150,7 +125,7 @@ class PhotoViewActivity : BaseComposeActivityWithParcelable<PhotoViewData>() {
}
val items by viewModel.uiState.collectPartialAsState(
prop1 = PhotoViewUiState::data,
initial = emptyList()
initial = persistentListOf()
)
val initialIndex by viewModel.uiState.collectPartialAsState(
prop1 = PhotoViewUiState::initialIndex,
@ -172,14 +147,17 @@ class PhotoViewActivity : BaseComposeActivityWithParcelable<PhotoViewData>() {
prop1 = PhotoViewUiState::loadPicPageData,
initial = LoadPicPageData()
)
val pageCount by remember { derivedStateOf { items.size } }
Surface(color = Color.Black) {
if (items.isNotEmpty()) {
val coroutineScope = rememberCoroutineScope()
val pagerState = rememberPagerState(initialPage = initialIndex) { pageCount }
LaunchedEffect(initialIndex) {
if (pagerState.currentPage != initialIndex) pagerState.scrollToPage(initialIndex)
}
Surface(color = Color.Black) {
if (items.isNotEmpty()) {
LaunchedEffect(pagerState.currentPage, pageCount, loadPicPageData) {
loadPicPageData?.let {
val item = items[pagerState.currentPage]
@ -205,30 +183,15 @@ class PhotoViewActivity : BaseComposeActivityWithParcelable<PhotoViewData>() {
Box(modifier = Modifier.fillMaxSize()) {
HorizontalPager(
state = pagerState,
key = {
"${items[it].overallIndex}"
}
key = { items[it].picId }
) {
val item = items[it]
ViewPhoto(
imageUri = item.originUrl,
modifier = Modifier.fillMaxSize(),
onDrag = { dx, dy, isAtEdge ->
val currentPage = pagerState.currentPage
if (abs(dy) < 15 && abs(dx) > 30 && isAtEdge) {
val prevPage = currentPage - 1
val nextPage = currentPage + 1
if (dx > 0 && prevPage >= 0) {
coroutineScope.launch {
pagerState.animateScrollToPage(prevPage)
}
} else if (dx < 0 && nextPage < items.size) {
coroutineScope.launch {
pagerState.animateScrollToPage(nextPage)
}
}
}
}
onTap = {
finish()
},
)
}
Box(
@ -313,6 +276,10 @@ class PhotoViewActivity : BaseComposeActivityWithParcelable<PhotoViewData>() {
}
}
override fun onCreateContent(systemUiController: SystemUiController) {
systemUiController.isSystemBarsVisible = false
}
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
return try {
super.dispatchTouchEvent(ev)

View File

@ -10,6 +10,9 @@ import com.huanchengfly.tieba.post.arch.UiIntent
import com.huanchengfly.tieba.post.arch.UiState
import com.huanchengfly.tieba.post.models.protos.LoadPicPageData
import com.huanchengfly.tieba.post.models.protos.PhotoViewData
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
@ -62,6 +65,7 @@ class PhotoViewViewModel :
val hasPrev = items.first().overallIndex > 1
PhotoViewPartialChange.LoadPrev.Success(
hasPrev = hasPrev,
currentPicId = picId,
items = items
)
}
@ -159,12 +163,15 @@ class PhotoViewViewModel :
val items = localItems + fetchedItems
val hasNext = items.last().overallIndex < picAmount
val hasPrev = items.first().overallIndex > 1
val initialIndex =
items.indexOfFirst { it.picId == data.data_.picId }.takeIf { it != -1 }
?: (data.data_.picIndex - 1)
PhotoViewPartialChange.Init.Success(
hasPrev = hasPrev,
hasNext = hasNext,
totalAmount = picAmount,
items = items,
initialIndex = data.data_.picIndex - 1,
initialIndex = initialIndex,
loadPicPageData = data.data_
)
}
@ -198,7 +205,7 @@ sealed interface PhotoViewPartialChange : PartialChange<PhotoViewUiState> {
override fun reduce(oldState: PhotoViewUiState): PhotoViewUiState =
when (this) {
is Success -> oldState.copy(
data = items,
data = items.toImmutableList(),
hasNext = hasNext,
hasPrev = hasPrev,
totalAmount = totalAmount,
@ -216,7 +223,7 @@ sealed interface PhotoViewPartialChange : PartialChange<PhotoViewUiState> {
url = if (item.showOriginBtn) item.url else null,
overallIndex = index + 1
)
},
}.toImmutableList(),
hasNext = false,
hasPrev = false,
totalAmount = data.picItems.size,
@ -246,19 +253,26 @@ sealed interface PhotoViewPartialChange : PartialChange<PhotoViewUiState> {
when (this) {
Start -> oldState.copy(isLoading = true)
is Success -> oldState.copy(
data = items.filterNot { item -> oldState.data.any { item.picId == it.picId } } + oldState.data,
is Success -> {
val items =
(items.filterNot { item -> oldState.data.any { item.picId == it.picId } } + oldState.data).toImmutableList()
val newIndex = items.indexOfFirst { it.picId == currentPicId }
oldState.copy(
data = items,
hasPrev = hasPrev,
isLoading = false
isLoading = false,
initialIndex = newIndex
)
}
is Failure -> oldState.copy(isLoading = false)
}
object Start : LoadPrev()
data object Start : LoadPrev()
data class Success(
val items: List<PhotoViewItem>,
val currentPicId: String,
val hasPrev: Boolean,
) : LoadPrev()
@ -273,7 +287,7 @@ sealed interface PhotoViewPartialChange : PartialChange<PhotoViewUiState> {
Start -> oldState.copy(isLoading = true)
is Success -> oldState.copy(
data = oldState.data + items.filterNot { item -> oldState.data.any { item.picId == it.picId } },
data = (oldState.data + items.filterNot { item -> oldState.data.any { item.picId == it.picId } }).toImmutableList(),
hasNext = hasNext,
isLoading = false
)
@ -281,7 +295,7 @@ sealed interface PhotoViewPartialChange : PartialChange<PhotoViewUiState> {
is Failure -> oldState.copy(isLoading = false)
}
object Start : LoadMore()
data object Start : LoadMore()
data class Success(
val items: List<PhotoViewItem>,
@ -296,7 +310,7 @@ sealed interface PhotoViewPartialChange : PartialChange<PhotoViewUiState> {
data class PhotoViewUiState(
val isLoading: Boolean = false,
val data: List<PhotoViewItem> = emptyList(),
val data: ImmutableList<PhotoViewItem> = persistentListOf(),
val totalAmount: Int = 0,
val hasNext: Boolean = false,
val hasPrev: Boolean = false,

View File

@ -24,4 +24,16 @@
<item name="android:navigationBarColor">?colorNavBar</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
<style name="AppTheme.PhotoView" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="android:windowAnimationStyle">@style/Animation.Fade</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowBackground">@color/transparent</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item><!--控制刘海处显示信息-->
</style>
</resources>