Android ObjectAnimator 更改视图位置

举报
AnRFDev 发表于 2021/08/14 21:39:45 2021/08/14
【摘要】 用动画移动View。使用ObjectAnimator 更改View的位置。走直线,走曲线,走自定义路径。

如果要改变某个View的位置,直接修改坐标会有一种刷的一下突然改变位置的感觉。
为了让它看起来更自然一些,我们可以加入动画,位置移动看起来更顺滑。

我们可以用ObjectAnimator来实现动画效果。配合上时间插值器,能控制动画的加减速。

接下来用一些例子来说明ObjectAnimator的用法。本文使用Kotlin来演示。

动画移动示例

mTv是被我们操作的View。同时它显示了当前它的x,ytranslationX/Y

private val mUpdateListener = ValueAnimator.AnimatorUpdateListener {
    mTv.text = "RustFisher\n(${mTv.x.toInt()},${mTv.y.toInt()}); (${mTv.translationX.toInt()},${mTv.translationY.toInt()})"
}

这个mUpdateListener不用也行。这里只是为了显示坐标。

TRANSLATION_X

这个小例子是为了演示TRANSLATION_X修改的动画。水平方向的动画,时常1秒。

val ani = ObjectAnimator.ofFloat(mTv, View.TRANSLATION_X, 0f, 200f, 640f).apply {
    duration = 1000
}
ani.addUpdateListener(mUpdateListener)
ani.start()

使用静态方法ObjectAnimator.ofFloat获得ObjectAnimator对象。

ofFloat(T target, Property<T, Float> property, float... values)

  • target 是要移动的对象,我们传入一个View
  • property 是要更改的属性
  • float… values 是目的数值

注意这里都是用float。values里我们传入了3个数字。开始到结束时从0变化到640。
动画将会分成2个部分,前500毫秒是0到200;后500毫秒是200到640。

apply里,动画时间duration设置为1000毫秒。

动画效果

tx.gif

可以看到,最后停止的位置并不是我们指定的640,而是差那么1像素。

实际上,如果不用监听器,可以写成这样

ObjectAnimator.ofFloat(mTv, View.TRANSLATION_X, 0f, 200f, 640f).apply {
    duration = 1000
    start()
}

TRANSLATION_Y

同理,我们也可以改变View.TRANSLATION_Y

val ani = ObjectAnimator.ofFloat(mTv, View.TRANSLATION_Y, 100f).apply {
    duration = 1000
}
ani.addUpdateListener(mUpdateListener)
ani.start()

values里只传入了100f。表示从当前值变化到100f。这个是目标值。

X,Y

我们也可以直接改变View的X和Y

val ani = ObjectAnimator.ofFloat(mTv, View.X, 500f).apply {
    duration = 800
}
ani.addUpdateListener(mUpdateListener)
ani.start()
// 或者
val ani = ObjectAnimator.ofFloat(mTv, View.Y, 700f).apply {
    duration = 700
}
ani.addUpdateListener(mUpdateListener)
ani.start()

xy.gif

上下左右

可以以View当前位置为出发点,计算出目标点。实现一个控制上下左右移动的效果。

例如控制向上,让Y减少100。

val ani = ObjectAnimator.ofFloat(mTv, View.Y, mTv.y - 100).apply {
    duration = 200
}
ani.addUpdateListener(mUpdateListener)
ani.start()

move.gif

沿指定路径移动

除了水平/垂直移动,我们还可以指定一个路径给动画。
要用到Path类。

圆弧

指定一个圆弧路径。Path().apply{ }里指定圆弧的参数。

val path = Path().apply {
    arcTo(0f, 0f, 960f, 1200f, 270f, -180f, true)
}
val ani = ObjectAnimator.ofFloat(mTv, View.X, View.Y, path).apply {
    duration = 2000
}
ani.addUpdateListener(mUpdateListener)
ani.start()

arc.gif

折线

同样是利用Path,我们自己绘制一个折线路线。

val path = Path().apply {
    moveTo(0f, 0f)
    lineTo(800f, 400f)
    lineTo(0f, 600f)
    lineTo(800f, 800f)
    lineTo(0f, 1000f)
}
val ani = ObjectAnimator.ofFloat(mTv, View.X, View.Y, path).apply {
    duration = 3000
}
ani.addUpdateListener(mUpdateListener)
ani.start()

这是个长达3秒的动画。从(0,0)出发,最后抵达(0,1000)。视觉上就是走了一个折线。
创建Path时,先moveTo(0f, 0f)回到(0,0),然后用lineTo把路径绘制出来。

line.gif

参考

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。