按顺序将动画应用到多个视图
Apply animation sequentially to multiple views
我有一个 activity,在垂直线性布局中有 3 个视图 (buttonViews
)。我正在动态生成(膨胀)这些视图。我想应用一个动画,这样,在 activity 开始时,第一个按钮滑入 -> 100 毫秒延迟 -> 第二个按钮滑入 -> 100 毫秒延迟 -> 第三个按钮滑入。
尝试
我尝试以这种方式实现它:
private void setMainButtons() {
ArrayList<String> dashboardTitles = DashboardUtils.getDashboardTitles();
ArrayList<Integer> dashboardIcons = DashboardUtils.getDashboardIcons();
final ViewGroup root = findViewById(R.id.button_container);
for (int i = 0; i < (dashboardTitles.size() < dashboardIcons.size() ? dashboardTitles.size() : dashboardIcons.size()); i++){
final View buttonView = DashboardButtonInflater.getDashboardButton(root, dashboardTitles.get(i), dashboardIcons.get(i), this);
if (buttonView == null) continue;
buttonView.setOnClickListener(this);
root.addView(buttonView);
animateBottomToTop(buttonView, (long) (i*50)); // Calling method to animate buttonView
}
}
//The function that adds animation to buttonView, with a delay.
private void animateBottomToTop(final View buttonView,long delay) {
AnimationSet animationSet = new AnimationSet(false);
animationSet.addAnimation(bottomToTop);
animationSet.addAnimation(fadeIn);
animationSet.setStartOffset(delay);
buttonView.setAnimation(animationSet);
}
结果:
上述方法等待所有视图的总延迟,最后将所有视图一起删除。我猜这里的罪魁祸首是线程。 dealy 实际上是在阻止 UI 线程执行任何动画。我可能是错的。
我也试了运行里面的动画代码
new Thread(new Runnable(){...}).run()
但这也没有用。
期望:
谁能帮我实现 buttonView
上的逐一动画?谢谢你。
使用 Transitions API 可能很容易解决问题。使用此 xml:
声明根布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
然后里面 activity:
class MainActivity : AppCompatActivity() {
lateinit var content: LinearLayout
private var counter = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
content = findViewById(R.id.content_frame)
// wait this view to be laid out and only then start adding and animating views
content.post { addNextChild() }
}
private fun addNextChild() {
// terminal condition
if (counter >= 3) return
++counter
val button = createButton()
val slide = Slide()
slide.duration = 500
slide.startDelay = 100
slide.addListener(object : TransitionListenerAdapter() {
override fun onTransitionEnd(transition: Transition) {
addNextChild()
}
})
TransitionManager.beginDelayedTransition(content, slide)
content.addView(button)
}
private fun createButton(): Button {
val button = Button(this)
button.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
button.text = "button"
return button
}
}
这段代码将产生以下输出:
您可以分别调整动画和延迟时间。
如果您想要以下行为:
然后你可以使用下面的代码:
class MainActivity : AppCompatActivity() {
lateinit var content: LinearLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
content = findViewById(R.id.content_frame)
content.post { addChildren() }
}
private fun addChildren() {
val button1 = createButton()
val button2 = createButton()
val button3 = createButton()
val slide1 = Slide()
slide1.duration = 500
slide1.addTarget(button1)
val slide2 = Slide()
slide2.duration = 500
slide2.startDelay = 150
slide2.addTarget(button2)
val slide3 = Slide()
slide3.duration = 500
slide3.startDelay = 300
slide3.addTarget(button3)
val set = TransitionSet()
set.addTransition(slide1)
set.addTransition(slide2)
set.addTransition(slide3)
TransitionManager.beginDelayedTransition(content, set)
content.addView(button1)
content.addView(button2)
content.addView(button3)
}
private fun createButton(): Button {
val button = Button(this)
button.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
button.text = "button"
return button
}
}
动画是有状态的对象,你不应该同时多次使用同一个实例。在您的情况下, bottomToTop
和 fadeIn
动画在动画集之间共享。当集合开始时(initialize()
被调用)它将设置其子项的起始偏移量。
例如,该方法可能如下所示:
//The function that adds animation to buttonView, with a delay.
private void animateBottomToTop(final View buttonView,long delay) {
AnimationSet animationSet = new AnimationSet(false);
// create new instances of the animations each time
animationSet.addAnimation(createBottomToTop());
animationSet.addAnimation(createFadeIn());
animationSet.setStartOffset(delay);
buttonView.setAnimation(animationSet);
}
创建方法,它将接受任意数量的 Animation
一个接一个地调用。举个例子。
private void playOneAfterAnother(@NonNull Queue<Animation> anims) {
final Animation next = anims.poll();
/* You can set any other paramters,
like delay, for each next Playing view, if any of course */
next.addListener(new AnimationListener() {
@Override
public void onAnimationEnd(Animator a) {
if (!anim.isEmpty()) {
playOneAfterAnother(anims);
}
}
@Override
public void onAnimationStart(Animator a) {
}
@Override
public void onAnimationCancel(Animator a) {
}
@Override
public void onAnimationRepeat(Animator a) {
}
});
next.play();
}
或者动画延迟,也很简单。
private void playOneAfterAnother(@NonNull Queue<Animation> anims,
long offsetBetween, int nextIndex) {
final Animation next = anims.poll();
/* You can set any other paramters,
like delay, for each next Playing view, if any of course */
next.setStartOffset(offsetBetween * nextIndex);
next.play();
if (!anim.isEmpty()) {
playOneAfterAnother(anims,
offsetBetween, nextIndex +1);
}
}
可能你需要用到的是AnimatorSet,而不是AnimationSet。 AnimatorSet API 允许您以两种方式编排动画:
1.顺序播放
2.一起玩
使用 API:
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(anim1, anim2, anim3, ...);
animatorSet.playTogether(anim1, anim2, anim3, ...);
您可以使用
进一步为动画添加延迟
animatorSet.setStartDelay();
在此处访问完整的 API 文档 https://developer.android.com/reference/android/animation/AnimatorSet
希望对您有所帮助!
我使用此代码并且其工作正常
希望能帮到你
// 首先将你的视图放在一个名为 arrayViews
的数组中
final int[] time = {0};
for (int i = 0; i < arrayViews.size(); i++) {
Animation zoom = AnimationUtils.loadAnimation(this, R.anim.fade_in);
zoom.setDuration(250);
zoom.setStartOffset(time[0] += 250);
arrayViews.get(i).startAnimation(zoom);
arrayViews.get(i).setVisibility(View.VISIBLE);
}
我有一个 activity,在垂直线性布局中有 3 个视图 (buttonViews
)。我正在动态生成(膨胀)这些视图。我想应用一个动画,这样,在 activity 开始时,第一个按钮滑入 -> 100 毫秒延迟 -> 第二个按钮滑入 -> 100 毫秒延迟 -> 第三个按钮滑入。
尝试
我尝试以这种方式实现它:
private void setMainButtons() {
ArrayList<String> dashboardTitles = DashboardUtils.getDashboardTitles();
ArrayList<Integer> dashboardIcons = DashboardUtils.getDashboardIcons();
final ViewGroup root = findViewById(R.id.button_container);
for (int i = 0; i < (dashboardTitles.size() < dashboardIcons.size() ? dashboardTitles.size() : dashboardIcons.size()); i++){
final View buttonView = DashboardButtonInflater.getDashboardButton(root, dashboardTitles.get(i), dashboardIcons.get(i), this);
if (buttonView == null) continue;
buttonView.setOnClickListener(this);
root.addView(buttonView);
animateBottomToTop(buttonView, (long) (i*50)); // Calling method to animate buttonView
}
}
//The function that adds animation to buttonView, with a delay.
private void animateBottomToTop(final View buttonView,long delay) {
AnimationSet animationSet = new AnimationSet(false);
animationSet.addAnimation(bottomToTop);
animationSet.addAnimation(fadeIn);
animationSet.setStartOffset(delay);
buttonView.setAnimation(animationSet);
}
结果:
上述方法等待所有视图的总延迟,最后将所有视图一起删除。我猜这里的罪魁祸首是线程。 dealy 实际上是在阻止 UI 线程执行任何动画。我可能是错的。
我也试了运行里面的动画代码
new Thread(new Runnable(){...}).run()
但这也没有用。
期望:
谁能帮我实现 buttonView
上的逐一动画?谢谢你。
使用 Transitions API 可能很容易解决问题。使用此 xml:
声明根布局<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
然后里面 activity:
class MainActivity : AppCompatActivity() {
lateinit var content: LinearLayout
private var counter = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
content = findViewById(R.id.content_frame)
// wait this view to be laid out and only then start adding and animating views
content.post { addNextChild() }
}
private fun addNextChild() {
// terminal condition
if (counter >= 3) return
++counter
val button = createButton()
val slide = Slide()
slide.duration = 500
slide.startDelay = 100
slide.addListener(object : TransitionListenerAdapter() {
override fun onTransitionEnd(transition: Transition) {
addNextChild()
}
})
TransitionManager.beginDelayedTransition(content, slide)
content.addView(button)
}
private fun createButton(): Button {
val button = Button(this)
button.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
button.text = "button"
return button
}
}
这段代码将产生以下输出:
您可以分别调整动画和延迟时间。
如果您想要以下行为:
然后你可以使用下面的代码:
class MainActivity : AppCompatActivity() {
lateinit var content: LinearLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
content = findViewById(R.id.content_frame)
content.post { addChildren() }
}
private fun addChildren() {
val button1 = createButton()
val button2 = createButton()
val button3 = createButton()
val slide1 = Slide()
slide1.duration = 500
slide1.addTarget(button1)
val slide2 = Slide()
slide2.duration = 500
slide2.startDelay = 150
slide2.addTarget(button2)
val slide3 = Slide()
slide3.duration = 500
slide3.startDelay = 300
slide3.addTarget(button3)
val set = TransitionSet()
set.addTransition(slide1)
set.addTransition(slide2)
set.addTransition(slide3)
TransitionManager.beginDelayedTransition(content, set)
content.addView(button1)
content.addView(button2)
content.addView(button3)
}
private fun createButton(): Button {
val button = Button(this)
button.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
button.text = "button"
return button
}
}
动画是有状态的对象,你不应该同时多次使用同一个实例。在您的情况下, bottomToTop
和 fadeIn
动画在动画集之间共享。当集合开始时(initialize()
被调用)它将设置其子项的起始偏移量。
例如,该方法可能如下所示:
//The function that adds animation to buttonView, with a delay.
private void animateBottomToTop(final View buttonView,long delay) {
AnimationSet animationSet = new AnimationSet(false);
// create new instances of the animations each time
animationSet.addAnimation(createBottomToTop());
animationSet.addAnimation(createFadeIn());
animationSet.setStartOffset(delay);
buttonView.setAnimation(animationSet);
}
创建方法,它将接受任意数量的 Animation
一个接一个地调用。举个例子。
private void playOneAfterAnother(@NonNull Queue<Animation> anims) {
final Animation next = anims.poll();
/* You can set any other paramters,
like delay, for each next Playing view, if any of course */
next.addListener(new AnimationListener() {
@Override
public void onAnimationEnd(Animator a) {
if (!anim.isEmpty()) {
playOneAfterAnother(anims);
}
}
@Override
public void onAnimationStart(Animator a) {
}
@Override
public void onAnimationCancel(Animator a) {
}
@Override
public void onAnimationRepeat(Animator a) {
}
});
next.play();
}
或者动画延迟,也很简单。
private void playOneAfterAnother(@NonNull Queue<Animation> anims,
long offsetBetween, int nextIndex) {
final Animation next = anims.poll();
/* You can set any other paramters,
like delay, for each next Playing view, if any of course */
next.setStartOffset(offsetBetween * nextIndex);
next.play();
if (!anim.isEmpty()) {
playOneAfterAnother(anims,
offsetBetween, nextIndex +1);
}
}
可能你需要用到的是AnimatorSet,而不是AnimationSet。 AnimatorSet API 允许您以两种方式编排动画: 1.顺序播放 2.一起玩 使用 API:
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(anim1, anim2, anim3, ...);
animatorSet.playTogether(anim1, anim2, anim3, ...);
您可以使用
进一步为动画添加延迟animatorSet.setStartDelay();
在此处访问完整的 API 文档 https://developer.android.com/reference/android/animation/AnimatorSet
希望对您有所帮助!
我使用此代码并且其工作正常 希望能帮到你
// 首先将你的视图放在一个名为 arrayViews
的数组中 final int[] time = {0};
for (int i = 0; i < arrayViews.size(); i++) {
Animation zoom = AnimationUtils.loadAnimation(this, R.anim.fade_in);
zoom.setDuration(250);
zoom.setStartOffset(time[0] += 250);
arrayViews.get(i).startAnimation(zoom);
arrayViews.get(i).setVisibility(View.VISIBLE);
}