代码之家  ›  专栏  ›  技术社区  ›  Srujan Barai

将动画顺序应用于多个视图

  •  3
  • Srujan Barai  · 技术社区  · 7 年前

    我有一个有三种观点的活动( buttonViews )在垂直线性布局中。我正在动态地生成(膨胀)这些视图。我想应用一个动画,这样,在活动开始时,第一个按钮在-≫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);
    }
    

    结果:

    上述方法等待所有视图的总延迟,并在结束时将所有视图重新组合在一起。我猜罪魁祸首就是线索。交易实际上是阻止ui线程执行任何动画。但我可能错了。

    我还试着在里面运行动画代码

    new Thread(new Runnable(){...}).run()
    

    但那也没用。

    期望:

    有人能帮我一个接一个地完成动画吗 buttonView ?谢谢您。

    4 回复  |  直到 7 年前
        1
  •  3
  •   bwt    7 年前

    动画是状态完整的对象,不应该同时使用同一个实例多次。在你的情况下 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);
    }
    
        2
  •  3
  •   azizbekian    7 年前

    这个问题很容易用 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"/>
    

    那么内部活动:

    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
        }
    }
    
        3
  •  0
  •   GensaGames    7 年前

    create方法,它将接受任意数量的 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);
         }
    
    }
    
        4
  •  0
  •   Rahul Shukla    7 年前

    可能,您需要使用的是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

    希望这有帮助!

    推荐文章