android - 在不破坏布局约束的情况下实现动画
问题描述
我需要构建自己的动画库/助手,只需通过更新动画的进度百分比就可以将视图从 A 点移动到 B 点。这必须用 Kotlin 编写,但如果需要,我可以用 java 翻译它。
我做了什么
class Animator(
private val animations: List<Animation>
) {
constructor(view: View,
startPoint: Point2D = Point2D(view.x, view.y),
endPoint: Point2D) : this(listOf(Animation(view, startPoint, endPoint)))
private val transitionState: TransitionState = TransitionState(0)
private val animationQueue: Handler = Handler()
/**
* Apply a progression in the animation from [startPoint] to [endPoint] or conversely depending
* on the transition state.
* When the [TransitionState.progress] reach 0 the position of the [view] to animate is at [startPoint]. When it
* reach 100 the view will be at the [endPoint]
*
* @param percent an Integer that must be between 0 and 100 because it's percentage. If the
* given percent is below 0 it
* will override it to 0. Same process when it's over 100.
*/
fun progressTo(percent: Int) {
for (anim in animations) {
val finalPercent = if (percent > 100) 100 else if (percent < 0) 0 else percent
if (Math.abs(transitionState.progress - finalPercent) < 10) {
animationQueue.post {
anim.view.x = (Vector2D(anim.startPoint, anim.endPoint) % finalPercent).endPoint.x
anim.view.y = (Vector2D(anim.startPoint, anim.endPoint) % finalPercent).endPoint.y
}
} else {
anim.view.animate().x((Vector2D(anim.startPoint, anim.endPoint) % finalPercent).endPoint.x)
anim.view.animate().y((Vector2D(anim.startPoint, anim.endPoint) % finalPercent).endPoint.y)
}
transitionState.progress = finalPercent
}
}
/**
* Finish the animation to the endPoint or startPoint depending on the [TransitionState.progress]
*/
fun finishAnimation() {
if (transitionState.progress < 50) {
progressTo(0)
} else if (transitionState.progress >= 50) {
progressTo(100)
}
}
}
data class TransitionState(
var progress: Int,
var isOnTransaction: Boolean = progress != 0 && progress != 100
)
data class Vector2D(
val startPoint: Point2D,
val endPoint: Point2D
) {
operator fun rem(percent: Int): Vector2D {
val finalPercent = if (percent > 100) 100 else if (percent < 0) 0 else percent
return Vector2D(startPoint, Point2D(
startPoint.x + ((endPoint.x - startPoint.x) * finalPercent / 100),
startPoint.y + ((endPoint.y - startPoint.y) * finalPercent / 100)
))
}
}
data class Animation(
val view: View,
val startPoint: Point2D = Point2D(view.x, view.y),
val endPoint: Point2D
)
data class Point2D(
val x: Float,
val y: Float
)
如您所见,我正在使用属性 View.setX 和 View.setY 来移动视图。它很好地使用正确的动画和运动正确移动视图。
问题
当我使用 X 和 Y 值时,视图的布局父级的约束(LinearLayout、RelativeLayout 或 ConstraintLayout)没有更新或遵守。例如,约束布局中有一个视图(第一个捕获中的红色视图),它被约束到父级的左、右和下,如此布局编辑器捕获中所示。
当我更改视图的 y 值时,底部约束不会更新(它不再适合父底部)。这是动画之前和动画之后的真实应用程序的捕获。
使用View.layout()
或View.invalidate()
不会改变任何东西,如果有一种方法可以重绘和恢复整个布局,我不确定应用程序是否会继续运行......
编辑 我更正了一段代码(在 for 循环中),使动画更加流畅。
问题
是否可以在不破坏其约束的情况下更改视图的位置?
我很确定我误解了 android ui 定位/绘图中的某些内容,因此即使您无法回答我的问题,也请随时发表您对此的理解。提前谢谢你。
解决方案
推荐阅读
- selenium - 如何返回动态下载链接的值?
- c - 为什么getchar()的返回类型是int?
- r - 无法在 R Studio 中安装包
- javascript - javascript中的字符串比较特殊字符
- node.js - 我想用 signalR 提出简单的请求,但这对我来说似乎很复杂
- java - 在 SpringBootTest 中排除少数 @Component 注解的类
- java - 在本地部署和工作后,AWS s3 不采用 MultipartFile 并且无法正常工作 文件上传到 tomcat 服务器
- android - 如何使进度条进度从边缘四舍五入?
- swagger - 如何使用 302 重定向为相同的响应代码定义两个不同的响应?
- numpy -
当我从终端运行文件时出现以下错误:
我正在使用 python 3.7 并在 Windows 10 系统上工作。
运行