我需要构建自己的动画库/助手,仅通过更新动画的进度百分比就可以将视图从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)不会被更新或遵守。例如,在约束布局中有一个视图(第一个捕获中的红色视图),该视图被约束到父项as shown in this layout editor capture的左,右和下。
当我更改视图的y值时,底部约束未更新(它不再适合父底部)。这是真实应用程序before animation和after animation的捕获。
使用View.layout()
或View.invalidate()
不会更改任何内容,并且如果有一种方法可以重绘并恢复整个布局,则我不确定该应用程序将不再具有性能……。< / p>
编辑 我更正了一段代码(在for循环中),该代码可以使流畅的操作更加流畅。
问题
是否可以在不破坏视图约束的情况下更改视图的位置?
我敢肯定我在android ui定位/绘图中误解了一些东西,所以即使您无法回答我的问题,也请发表您对此的理解。谢谢你。