Android 撰写、缩放图像而不裁剪?

问题描述 投票:0回答:3
我希望该图像能够“缩小”到应用程序,但不会被裁剪为原始图像大小。

这效果很好,就像我想要的那样,直到我将图像放在行、列、框等内。下面的动画是我的目标。如果布局中只有图像,则此方法有效。

上面是用下面的代码绘制的:

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // A surface container using the 'background' color from the theme Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.surfaceVariant ) { Display() } } } @Preview @Composable fun Display() { ScaleImage() } @Composable fun ScaleImage() { val vector = ImageVector.vectorResource(id = R.drawable.smarter_garage_svg) val painter = rememberVectorPainter(image = vector) var visible by remember { mutableStateOf(false) } // a best effort 'hack' to avoid jumpiness of having no image in place when the garage image is temporarily hidden, uses this empty background to keep spacing AnimatedVisibility( visible = visible, enter = scaleIn(initialScale = 5f, animationSpec = tween(durationMillis = 2000)) + fadeIn( // Fade in with the initial alpha of 0.3f. initialAlpha = 0.01f, animationSpec = tween(durationMillis = 1000) ) ) { Image( painter = painter, contentDescription = "garage", modifier = Modifier .wrapContentSize(), contentScale = ContentScale.Crop ) } LaunchedEffect(Unit) { delay(1.milliseconds) visible = true } }
但是,如果我尝试使用任何布局,我的动画缩放图像将被裁剪到原始图像边界。

我正在使用类似下面的东西

@Preview @Composable fun Display() { Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxWidth() .padding(20.dp), verticalArrangement = Arrangement.spacedBy(20.dp) ) { ScaleImage() } }
我的SVG如下

<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="200dp" android:height="200dp" android:background="@android:color/transparent" android:viewportWidth="150" android:viewportHeight="150"> <path android:name="front" android:fillColor="#fb0101" android:pathData="M15.002,42.815V137.24H30.739V54.92h89.583v82.319h15.737V42.815l-60.529,-26.196 -1.211,0.034c-59.318,26.162 0,0 -59.318,26.162z" android:strokeWidth="1.21061" android:strokeColor="#00000000" /> <path android:name="door" android:fillColor="#fdfdfd" android:pathData="M45.266,68.237V137.24H105.795V68.237Z" android:strokeWidth="1.21061" android:strokeColor="#00000000" /> <path android:name="handle" android:fillColor="#000000" android:pathData="M68.712,122.423a7.387,6.945 0,1 0,14.774 0a7.387,6.945 0,1 0,-14.774 0z" android:strokeWidth="1.21061" /> <path android:fillColor="#000000" android:pathData="M1.046,137.248h147.95v10.091h-147.95z" android:strokeWidth="1.2144" /> <path android:name="house_frame" android:fillColor="#000000" android:pathData="M74.147,1.105C50.028,12.041 25.909,22.976 1.79,33.911c-1.14,0.677 -0.577,2.167 -0.712,3.248 -0.021,33.178 -0.042,66.356 -0.062,99.534 0.038,1.084 1.218,1.343 2.101,1.206 3.806,-0.044 7.625,0.003 11.424,-0.095 1.206,-0.126 1.13,-1.533 1.083,-2.439 0.021,-30.719 0.042,-61.439 0.062,-92.158 18.706,-8.222 37.37,-16.543 56.107,-24.686 1.087,-0.396 2.134,-1.031 3.278,-1.206 3.935,1.404 7.72,3.204 11.576,4.809 16.248,7.013 32.485,14.053 48.728,21.078 0.019,31.142 0.04,62.283 0.061,93.425 0.038,1.077 1.208,1.34 2.087,1.215 3.47,-0.002 6.951,0.084 10.414,0.026 1.154,-0.098 1.165,-1.434 1.095,-2.315 -0.018,-33.602 -0.041,-67.203 -0.062,-100.805 -0.147,-1.324 -1.745,-1.415 -2.679,-1.978C122.575,22.216 98.857,11.658 75.139,1.101c-0.338,-0.046 -0.666,-0.165 -0.992,0.003z" android:strokeWidth="0.126265" /> <path android:name="garage_frame_wrapper" android:fillColor="#00000000" android:pathData="M45.266,137.24V68.237h60.529v69.003h14.527V54.92H30.739v82.319h14.527" android:strokeWidth="1.21061" android:strokeColor="#000000" android:strokeLineCap="butt" android:strokeLineJoin="miter" /> <path android:name="garage_frame" android:fillColor="#000000" android:pathData="m30.713,54.916c-0.657,1.202 -0.137,2.713 -0.303,4.042 0,25.895 0,51.789 0,77.683 0.333,1.417 2.134,0.657 3.169,0.848 3.743,-0.041 7.515,0.083 11.24,-0.06 1.213,-0.459 0.479,-2.112 0.68,-3.108 0,-21.921 0,-43.843 0,-65.764 20.031,0 40.063,0 60.094,0 0,22.695 0,45.39 0,68.085 0.333,1.417 2.134,0.657 3.169,0.848 3.743,-0.041 7.515,0.083 11.24,-0.06 1.213,-0.459 0.48,-2.112 0.68,-3.108 0,-26.252 0,-52.503 0,-78.755 -0.332,-1.417 -2.133,-0.657 -3.169,-0.848 -28.752,0 -57.504,0 -86.255,0 -0.182,0.066 -0.363,0.132 -0.545,0.198z" android:strokeWidth="0.178596" android:strokeColor="#000000" /> </vector>
    
android android-jetpack-compose android-animation
3个回答
1
投票
图像中没有任何异常

@Preview @Composable fun Display() { ScaleImage() }

@Preview @Composable fun Display() { Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxWidth() .padding(20.dp), verticalArrangement = Arrangement.spacedBy(20.dp) ) { ScaleImage() } }
样品。在第一个中,您没有设置预览尺寸,而矢量资源的固有大小为 200.dp。在第二个中,您设置了全宽度,但图像仍然占据 200.dp。观察这一点的最简单方法是在图像、AnimatedVisibility 周围添加边框。

@Preview @Composable fun ScaleImage() { val vector = ImageVector.vectorResource(id = R.drawable.ic_garrage) val painter = rememberVectorPainter(image = vector) var visible by remember { mutableStateOf(false) } // a best effort 'hack' to avoid jumpiness of having no image in place // when the garage image is temporarily hidden, uses this empty background to keep spacing AnimatedVisibility( modifier = Modifier.border(3.dp, Color.Red), visible = visible, enter = scaleIn(initialScale = 5f, animationSpec = tween(durationMillis = 2000)) + fadeIn( // Fade in with the initial alpha of 0.3f. initialAlpha = 0.01f, animationSpec = tween(durationMillis = 1000) ) ) { Image( painter = painter, contentDescription = "garage", modifier = Modifier .border(6.dp, Color.Blue) .wrapContentSize(), contentScale = ContentScale.Crop ) } LaunchedEffect(Unit) { delay(1.milliseconds) visible = true } }
对于第一列,如果您添加一个 200.dp 的参考框,您将看到两者都按预期工作

@Preview @Composable fun Display() { Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxWidth() .padding(20.dp) .border(2.dp, Color.Green), verticalArrangement = Arrangement.spacedBy(20.dp) ) { ScaleImage() Box(Modifier.size(200.dp).background(Color.Yellow)) } }
要使其正确缩放全屏,您可以在 

Modifier.fillMaxSize

 之前指定 
wrapContentSize

@Preview @Composable fun ScaleImage() { val vector = ImageVector.vectorResource(id = R.drawable.ic_garrage) val painter = rememberVectorPainter(image = vector) var visible by remember { mutableStateOf(false) } // a best effort 'hack' to avoid jumpiness of having no image in place // when the garage image is temporarily hidden, uses this empty background to keep spacing AnimatedVisibility( modifier = Modifier.border(3.dp, Color.Red), visible = visible, enter = scaleIn(initialScale = 5f, animationSpec = tween(durationMillis = 2000)) + fadeIn( // Fade in with the initial alpha of 0.3f. initialAlpha = 0.01f, animationSpec = tween(durationMillis = 1000) ) ) { Image( painter = painter, contentDescription = "garage", modifier = Modifier .border(6.dp, Color.Blue) .fillMaxSize() .wrapContentSize(), contentScale = ContentScale.Crop ) } LaunchedEffect(Unit) { delay(1.milliseconds) visible = true } }
无论是否有 Column 或任何其他可组合项都将像这样显示。


0
投票
我认为

AnimatedVisibility

 可组合项只能在其范围内绘制动画。因此,当您将其包装到另一个 Composable 中时,您可能必须在父 Composable 上设置 fillMaxSize
,以便 
AnimatedVisibility
 可以在整个屏幕上绘制动画。

@Composable fun Display() { Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxSize() .padding(20.dp), verticalArrangement = Arrangement.spacedBy(20.dp) ) { ScaleImage() } }
但这意味着,如果您想将图像放置在列中,同时在动画中包含全屏,则必须使用一些技巧。


0
投票
谢谢你,@thracian,这似乎是窍门。我的较大项目具有更多的复杂性和覆盖范围,但这使我的动画能够使用全部可用空间并停止以原始尺寸进行裁剪

.fillMaxSize() .wrapContentSize(),
    
© www.soinside.com 2019 - 2024. All rights reserved.