在不违反布局约束的情况下实现动画效果

时间:2018-08-09 13:00:19

标签: android animation kotlin

我需要构建自己的动画库/助手,仅通过更新动画的进度百分比就可以将视图从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 animationafter animation的捕获。
使用View.layout()View.invalidate()不会更改任何内容,并且如果有一种方法可以重绘并恢复整个布局,则我不确定该应用程序将不再具有性能……。< / p>

编辑 我更正了一段代码(在for循环中),该代码可以使流畅的操作更加流畅。

问题
是否可以在不破坏视图约束的情况下更改视图的位置?

我敢肯定我在android ui定位/绘图中误解了一些东西,所以即使您无法回答我的问题,也请发表您对此的理解。谢谢你。

0 个答案:

没有答案