mirror of
https://github.com/Tencent/QMUI_Android.git
synced 2026-10-17 04:31:16 +08:00
bugfix: do not change the container width and height.
This commit is contained in:
@@ -276,6 +276,9 @@ open class QMUICoilPhotoProvider(
|
||||
override fun meta(): Bundle? {
|
||||
return Bundle().apply {
|
||||
putParcelable(META_URI_KEY, uri)
|
||||
if(thumbUri != uri){
|
||||
putParcelable(META_THUMB_URI_KEY, thumbUri)
|
||||
}
|
||||
putParcelable(META_THUMB_URI_KEY, thumbUri)
|
||||
putFloat(META_RATIO_KEY, ratio)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -49,6 +50,7 @@ private fun GlideImage(
|
||||
mutableStateOf<Pair<Long, Drawable?>?>(null)
|
||||
}
|
||||
val context = LocalContext.current
|
||||
Log.i("cginetest", "1. $constraints")
|
||||
DisposableEffect(uri, isContainerDimenExactly, constraints.isZero,isLongImage, isThumbImage, contentScale) {
|
||||
val key = SystemClock.elapsedRealtime()
|
||||
val request = when {
|
||||
@@ -251,7 +253,9 @@ open class QMUIGlidePhotoProvider(val uri: Uri, val thumbUrl: Uri, val ratio: Fl
|
||||
override fun meta(): Bundle? {
|
||||
return Bundle().apply {
|
||||
putParcelable(META_URI_KEY, uri)
|
||||
putParcelable(META_THUMB_URI_KEY, thumbUrl)
|
||||
if(thumbUrl != uri){
|
||||
putParcelable(META_THUMB_URI_KEY, thumbUrl)
|
||||
}
|
||||
putFloat(META_RATIO_KEY, ratio)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
@@ -46,6 +47,7 @@ import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.pager.HorizontalPager
|
||||
import com.google.accompanist.pager.PagerScope
|
||||
import com.google.accompanist.pager.rememberPagerState
|
||||
import com.qmuiteam.compose.core.helper.QMUILog
|
||||
import com.qmuiteam.photo.R
|
||||
import com.qmuiteam.photo.compose.QMUIDefaultPhotoConfigProvider
|
||||
import com.qmuiteam.photo.compose.QMUIGesturePhoto
|
||||
@@ -75,17 +77,22 @@ open class QMUIPhotoViewerActivity : AppCompatActivity() {
|
||||
intent.putExtra(PHOTO_TRANSITION_DELIVERY_KEY, QMUIPhotoTransitionDelivery.put(data))
|
||||
intent.putExtra(PHOTO_CURRENT_INDEX, index)
|
||||
intent.putExtra(PHOTO_COUNT, list.size)
|
||||
list.forEachIndexed { i, transition ->
|
||||
val meta = transition.photoProvider.meta()
|
||||
val recoverCls = transition.photoProvider.recoverCls()
|
||||
if (meta != null && recoverCls != null) {
|
||||
intent.putExtra("${PHOTO_META_KEY_PREFIX}${i}", meta)
|
||||
intent.putExtra(
|
||||
"${PHOTO_PROVIDER_RECOVER_CLASS_KEY_PREFIX}${i}",
|
||||
recoverCls.name
|
||||
)
|
||||
if(list.size < 250){
|
||||
list.forEachIndexed { i, transition ->
|
||||
val meta = transition.photoProvider.meta()
|
||||
val recoverCls = transition.photoProvider.recoverCls()
|
||||
if (meta != null && recoverCls != null) {
|
||||
intent.putExtra("${PHOTO_META_KEY_PREFIX}${i}", meta)
|
||||
intent.putExtra(
|
||||
"${PHOTO_PROVIDER_RECOVER_CLASS_KEY_PREFIX}${i}",
|
||||
recoverCls.name
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QMUILog.w("QMUIPhotoViewerActivity", "once delivered too many photos, so only use memory data for delivery, there may be some recover issue.")
|
||||
}
|
||||
|
||||
return intent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.qmuiteam.photo.compose
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.*
|
||||
@@ -10,11 +11,12 @@ import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.TransformOrigin
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.geometry.toRect
|
||||
import androidx.compose.ui.graphics.*
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
@@ -23,7 +25,9 @@ import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.input.pointer.positionChangeConsumed
|
||||
import androidx.compose.ui.input.pointer.positionChanged
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -192,7 +196,6 @@ fun QMUIGesturePhoto(
|
||||
detectTapGestures(
|
||||
onTap = {
|
||||
if (shouldTransitionExit) {
|
||||
reset()
|
||||
transitionTargetState = false
|
||||
} else {
|
||||
onTapExit(false)
|
||||
@@ -375,15 +378,16 @@ fun QMUIGesturePhoto(
|
||||
imageWidthPx,
|
||||
imageHeightPx,
|
||||
scale,
|
||||
scale,
|
||||
translateX,
|
||||
translateY
|
||||
) {
|
||||
val imageLeft = translateX + imagePaddingFix.first * scale
|
||||
val imageTop = translateY + imagePaddingFix.second * scale
|
||||
val imageLeft = translateX + imagePaddingFix.first * it
|
||||
val imageTop = translateY + imagePaddingFix.second * it
|
||||
content(
|
||||
transition,
|
||||
scale,
|
||||
Rect(imageLeft, imageTop, imageLeft + imageWidthPx * scale, imageTop + imageHeightPx * scale),
|
||||
it,
|
||||
Rect(imageLeft, imageTop, imageLeft + imageWidthPx * it, imageTop + imageHeightPx * it),
|
||||
usedImageRatioUpdater
|
||||
)
|
||||
}
|
||||
@@ -398,14 +402,14 @@ fun QMUIGesturePhoto(
|
||||
translateY = photoTargetTranslateY,
|
||||
transition = transition,
|
||||
transitionDurationMs = transitionDurationMs
|
||||
) { w, h, scale, translateX, translateY ->
|
||||
PhotoTransformContent(1f, w, h, scale, translateX, translateY) {
|
||||
val imageLeft = translateX + imagePaddingFix.first * scale
|
||||
val imageTop = translateY + imagePaddingFix.second * scale
|
||||
) { scaleX, scaleY, translateX, translateY ->
|
||||
PhotoTransformContent(1f, imageWidthPx, imageHeightPx, scaleX, scaleY, translateX, translateY) {
|
||||
val imageLeft = translateX + imagePaddingFix.first * it
|
||||
val imageTop = translateY + imagePaddingFix.second * it
|
||||
content(
|
||||
transition,
|
||||
scale,
|
||||
Rect(imageLeft, imageTop, imageLeft + imageWidthPx * scale, imageTop + imageHeightPx * scale),
|
||||
it,
|
||||
Rect(imageLeft, imageTop, imageLeft + imageWidthPx * it, imageTop + imageHeightPx * it),
|
||||
usedImageRatioUpdater
|
||||
)
|
||||
}
|
||||
@@ -478,7 +482,7 @@ fun PhotoContentWithRectTransition(
|
||||
translateY: Float,
|
||||
transition: Transition<Boolean>,
|
||||
transitionDurationMs: Int,
|
||||
content: @Composable (w: Float, h: Float, scale: Float, translateX: Float, translateY: Float) -> Unit
|
||||
content: @Composable (scaleX: Float, scaleY: Float, translateX: Float, translateY: Float) -> Unit
|
||||
) {
|
||||
val rect = transition.animateRect(
|
||||
transitionSpec = { tween(durationMillis = transitionDurationMs) },
|
||||
@@ -486,13 +490,12 @@ fun PhotoContentWithRectTransition(
|
||||
) {
|
||||
if (it) Rect(translateX, translateY, translateX + imageWidth * scale, translateY + imageHeight * scale) else initRect
|
||||
}
|
||||
val isTransitionEnd = transition.currentState && transition.targetState
|
||||
val usedWidth = if (isTransitionEnd) imageWidth else rect.value.width.coerceAtMost(imageWidth)
|
||||
val usedHeight = if (isTransitionEnd) imageHeight else rect.value.height.coerceAtMost(imageHeight)
|
||||
val usedScale = if (isTransitionEnd || rect.value.width > imageWidth) {
|
||||
rect.value.width / imageWidth
|
||||
} else 1f
|
||||
content(usedWidth, usedHeight, usedScale, rect.value.left, rect.value.top)
|
||||
content(
|
||||
(rect.value.width / imageWidth).coerceAtLeast(0f),
|
||||
(rect.value.height / imageHeight).coerceAtLeast(0f),
|
||||
rect.value.left,
|
||||
rect.value.top
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -513,27 +516,49 @@ fun PhotoTransformContent(
|
||||
alpha: Float,
|
||||
width: Float,
|
||||
height: Float,
|
||||
scale: Float,
|
||||
scaleX: Float,
|
||||
scaleY: Float,
|
||||
translateX: Float,
|
||||
translateY: Float,
|
||||
content: @Composable () -> Unit
|
||||
content: @Composable (scale: Float) -> Unit
|
||||
) {
|
||||
val widthDp = with(LocalDensity.current) { width.toDp() }
|
||||
val heightDp = with(LocalDensity.current) { height.toDp() }
|
||||
val scale = scaleX.coerceAtLeast(scaleY)
|
||||
val clipSize = remember(scaleX, scaleY, width, height) {
|
||||
if(scale == 0f){
|
||||
Size(0f, 0f)
|
||||
}else{
|
||||
val expectedW = width * scaleX / scale
|
||||
val expectedH = height * scaleY / scale
|
||||
val clipW = (width - expectedW) / 2
|
||||
val clipH = (height - expectedH) / 2
|
||||
Size(clipW, clipH)
|
||||
}
|
||||
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(widthDp)
|
||||
.height(heightDp)
|
||||
.graphicsLayer {
|
||||
this.transformOrigin = TransformOrigin(0f, 0f)
|
||||
this.translationX = translateX
|
||||
this.translationY = translateY
|
||||
this.alpha = alpha
|
||||
this.scaleX = scale
|
||||
this.scaleY = scale
|
||||
this.clip = true
|
||||
this.shape = object : Shape {
|
||||
override fun createOutline(size: Size, layoutDirection: LayoutDirection, density: Density) =
|
||||
Outline.Rectangle(Rect(clipSize.width, clipSize.height, size.width - clipSize.width, size.height - clipSize.height))
|
||||
|
||||
override fun toString(): String = "PhotoTransformShape"
|
||||
}
|
||||
this.translationX = translateX - clipSize.width * scale
|
||||
this.translationY = translateY - clipSize.height * scale
|
||||
|
||||
}
|
||||
) {
|
||||
content()
|
||||
content(scale)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import androidx.compose.foundation.interaction.collectIsPressedAsState
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
@@ -18,11 +19,9 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.IntSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.qmuiteam.photo.activity.QMUIPhotoViewerActivity
|
||||
import com.qmuiteam.photo.data.PhotoResult
|
||||
import com.qmuiteam.photo.data.QMUIPhoto
|
||||
import com.qmuiteam.photo.data.QMUIPhotoProvider
|
||||
import com.qmuiteam.photo.data.QMUIPhotoTransitionInfo
|
||||
import com.qmuiteam.photo.data.*
|
||||
import com.qmuiteam.photo.util.getWindowSize
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
const val SINGLE_HIGH_IMAGE_MINI_SCREEN_HEIGHT_RATIO = -1F
|
||||
|
||||
|
||||
@@ -262,9 +262,6 @@ internal class TextEditLayer(
|
||||
scaleY = currentScale
|
||||
rotationZ = currentRotation
|
||||
}
|
||||
.onPlaced {
|
||||
Log.i("cginetest", "22.3 ${it.positionInWindow()}; ${it.size}")
|
||||
}
|
||||
.pointerInput("") {
|
||||
coroutineScope {
|
||||
|
||||
@@ -330,8 +327,6 @@ internal class TextEditLayer(
|
||||
offsetFlow.value = offsetFlow.value + panChange
|
||||
scaleFlow.value = scaleFlow.value * zoomChange
|
||||
rotationFlow.value = rotationFlow.value + rotationChange
|
||||
Log.i("cginetest", "10: ${panChange}; $zoomChange;" +
|
||||
" $rotationChange; ${event.calculateCentroid(true)}")
|
||||
if (isDragging) {
|
||||
isInDeleteArea = dragInfo.isInDeleteArea(offsetFlow.value)
|
||||
}
|
||||
@@ -391,7 +386,6 @@ internal class TextEditLayer(
|
||||
.padding(bottom = insets.bottom + 16.dp)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.onGloballyPositioned {
|
||||
Log.i("cginetest", "1: ${it.positionInWindow()}; ${it.size}")
|
||||
onPlaced(it.positionInWindow(), it.size)
|
||||
}
|
||||
.background(if (isFocusing) config.editLayerDeleteAreaNormalFocusColor else config.editLayerDeleteAreaNormalBgColor)
|
||||
@@ -424,7 +418,6 @@ private class MutableDragInfo(
|
||||
) {
|
||||
fun isInDeleteArea(offset: Offset): Boolean {
|
||||
val windowOffset = editLayerCenter + offset
|
||||
Log.i("cginetest", "3: $windowOffset; $deleteAreaOffset; $deleteAreaSize")
|
||||
return windowOffset.x > deleteAreaOffset.x &&
|
||||
windowOffset.x < deleteAreaOffset.x + deleteAreaSize.width &&
|
||||
windowOffset.y > deleteAreaOffset.y &&
|
||||
|
||||
@@ -13,12 +13,12 @@ object Dep {
|
||||
|
||||
object QMUI {
|
||||
const val group = "com.qmuiteam"
|
||||
const val qmuiVer = "2.1.0.2"
|
||||
const val archVer = "2.1.0.2"
|
||||
const val qmuiVer = "2.1.0.3"
|
||||
const val archVer = "2.1.0.3"
|
||||
const val typeVer = "0.1.0.4"
|
||||
const val composeCoreVer = "0.0.1"
|
||||
const val composeVer = "0.0.1.2"
|
||||
const val photoVer = "0.0.1.7"
|
||||
const val composeVer = "0.0.1.3"
|
||||
const val photoVer = "0.0.1.8"
|
||||
const val editorVer = "0.0.1"
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@ package com.qmuiteam.qmuidemo.fragment.lab
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.util.Log
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.result.registerForActivityResult
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
@@ -45,8 +43,8 @@ class QDPhotoFragment : ComposeBaseFragment() {
|
||||
|
||||
val pickerFlow = MutableStateFlow<QMUIPhotoPickResult?>(null)
|
||||
|
||||
private val pickLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
|
||||
if(it.resultCode == RESULT_OK){
|
||||
private val pickLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == RESULT_OK) {
|
||||
val pickerResult = it.data?.getQMUIPhotoPickResult() ?: return@registerForActivityResult
|
||||
pickerFlow.value = pickerResult
|
||||
}
|
||||
@@ -67,11 +65,13 @@ class QDPhotoFragment : ComposeBaseFragment() {
|
||||
rightItems = arrayListOf(
|
||||
QMUITopBarTextItem("Pick a Picture") {
|
||||
val activity = activity ?: return@QMUITopBarTextItem
|
||||
pickLauncher.launch(QMUIPhotoPickerActivity.intentOf(
|
||||
activity,
|
||||
QMUIPhotoPickerActivity::class.java,
|
||||
QMUIMediaCoilPhotoProviderFactory::class.java
|
||||
))
|
||||
pickLauncher.launch(
|
||||
QMUIPhotoPickerActivity.intentOf(
|
||||
activity,
|
||||
QMUIPhotoPickerActivity::class.java,
|
||||
QMUIMediaCoilPhotoProviderFactory::class.java
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
)
|
||||
@@ -303,10 +303,10 @@ class QDPhotoFragment : ComposeBaseFragment() {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PickerResult(){
|
||||
fun PickerResult() {
|
||||
val pickResultState = pickerFlow.collectAsState()
|
||||
val pickResult = pickResultState.value
|
||||
if(pickResult == null){
|
||||
if (pickResult == null) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -324,7 +324,7 @@ class QDPhotoFragment : ComposeBaseFragment() {
|
||||
) {
|
||||
Text("No Picked Images, click to pick")
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
val images = remember(pickResult) {
|
||||
pickResult.list.map {
|
||||
QMUICoilPhotoProvider(
|
||||
@@ -333,9 +333,11 @@ class QDPhotoFragment : ComposeBaseFragment() {
|
||||
)
|
||||
}
|
||||
}
|
||||
Column(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp, vertical = 20.dp)){
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp, vertical = 20.dp)
|
||||
) {
|
||||
Text(text = "原图:${pickResult.isOriginOpen}")
|
||||
QMUIPhotoThumbnailWithViewer(
|
||||
activity = requireActivity(),
|
||||
@@ -348,13 +350,13 @@ class QDPhotoFragment : ComposeBaseFragment() {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TestImageCompress(){
|
||||
fun TestImageCompress() {
|
||||
var bitmap by remember {
|
||||
mutableStateOf<Bitmap?>(null)
|
||||
}
|
||||
LaunchedEffect(""){
|
||||
LaunchedEffect("") {
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO){
|
||||
withContext(Dispatchers.IO) {
|
||||
QMUIPhotoHelper.compressByShortEdgeWidthAndByteSize(
|
||||
requireContext(),
|
||||
{
|
||||
@@ -362,7 +364,7 @@ class QDPhotoFragment : ComposeBaseFragment() {
|
||||
},
|
||||
500
|
||||
)?.inputStream().use {
|
||||
if(it != null){
|
||||
if (it != null) {
|
||||
bitmap = BitmapFactory.decodeStream(it)
|
||||
}
|
||||
}
|
||||
@@ -370,7 +372,7 @@ class QDPhotoFragment : ComposeBaseFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
if(bitmap != null){
|
||||
if (bitmap != null) {
|
||||
Image(painter = BitmapPainter(bitmap!!.asImageBitmap()), contentDescription = "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,10 +151,6 @@ open class EmojiEditText(
|
||||
|
||||
fixSelection()
|
||||
isPendingRemoving = false
|
||||
Log.i(
|
||||
"cginetest",
|
||||
"afterTextChanged end: $s, $isPendingRemoving, $isPendingRemoving"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user