TranslateAnimation - 动画仅在第二次之后起作用

时间:2011-11-21 16:47:41

标签: android animation

我使用了一些我在滑动面板上找到的代码,基本上它可以工作,但问题很小。

动画在第一次打开面板时不起作用。

这是动画的代码:

    TranslateAnimation anim = null;


    m_isOpen = !m_isOpen;

    if (m_isOpen) {
        setVisibility(View.VISIBLE);
        anim = new TranslateAnimation(0.0f, 0.0f, getHeight(), 0.0f);
    } else {
        anim = new TranslateAnimation(0.0f, 0.0f, 0.0f, getHeight());
        anim.setAnimationListener(new Animation.AnimationListener() {
              public void onAnimationEnd(Animation animation) {
                   setVisibility(View.GONE);
              }

              public void onAnimationRepeat(Animation animation) {
                   // not needed
              }

              public void onAnimationStart(Animation animation) {
                   // not needed
              }
        });

    }

    anim.setDuration(300);
    anim.setInterpolator(new AccelerateInterpolator(1.0f));
    startAnimation(anim);

为什么第一次打开面板时没有动画,但其他所有动画都有?

4 个答案:

答案 0 :(得分:6)

你什么时候打电话给这个?它可能只是“在第一次之后”执行它,因为当您第一次调用它时面板尚未呈现,getHeight()正在返回0.尝试等待getHeight()有一个值并启动动画然后。您也可以尝试将值硬编码为某种东西,以测试我的理论是否正确。

答案 1 :(得分:0)

我使代码工作的方式:


final ViewGroup viewGroup = (ViewGroup) findViewById(R.id.panel);
viewGroup.setVisibility(View.VISIBLE);
final ViewTreeObserver treeObserver = viewGroup.getViewTreeObserver();

if (treeObserver.isAlive()) {
    final OnPreDrawListener l = new OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            treeObserver.removeOnPreDrawListener(this);
            TranslateAnimation anim = new TranslateAnimation(0.0f, 0.0f, viewGroup.getHeight(), 0.0f);
            anim.setDuration(1000);
            anim.setInterpolator(new AccelerateInterpolator(1.0f));
            viewGroup.startAnimation(anim);

            return false;
            }
        };
    treeObserver.addOnPreDrawListener(l);
}

这就是它的本质。希望它有所帮助。

答案 2 :(得分:0)

如果您只是想要制作动画的一个视图,那么您可以像这样用XML编写动画:

<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator"
android:fromYDelta="-100%"
        (or)    
android:toYDelta="-100%"  
android:duration="300"/>

这样,您无需使用getHeight()。然后Java部分如下所示:

    final View flashTitle = findViewById(R.id.flash_title);
    Animation slideDownOnscreen = AnimationUtils.loadAnimation
            (this,  R.anim.slide_down_onscreen);
    flashTitle.setAnimation(slideDownOnscreen);
    flashTitle.setVisibility(View.VISIBLE);

或者,如果您需要同时为多个视图设置动画,请使用第一个视图执行上述操作,并在post runnable中设置后续视图的动画,以便getHeight()返回第一个视图的正确高度,像这样:

    flashTitle.post(new Runnable() {
        @Override
        public void run() {
            System.out.println("NOTE    flashTitle height: "+flashTitle.getHeight());
            Animation slideDown = new TranslateAnimation(0, 0,
                    -flashTitle.getHeight(),0);
            slideDown.setDuration(300);
            flashLine.setVisibility(View.VISIBLE);
            flashLine.startAnimation(slideDown);
            //(or)flashLine.animate().translationYBy(flashTitle.getHeight()).setDuration(300);
        }
    });

您还需要添加accelerate_interpolator,因为Android的默认设置为accelerate_decelerate_interpolator

答案 3 :(得分:0)

你可以使用延迟来工作

 TranslateAnimation animate1 = new TranslateAnimation(
                    0,                 // fromXDelta
                    0,                 // toXDelta
                    0,  // fromYDelta
                    binding.saveCardview.getMeasuredHeight());                // toYDelta
                animate1.setDuration(500);
                animate1.setFillAfter(true);
                binding.saveCardview.startAnimation(animate1);

                final Handler handler = new Handler(Looper.getMainLooper());
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //Do something after 100ms
                        binding.saveCardview.setVisibility(View.GONE);
                        TranslateAnimation animate2 = new TranslateAnimation(
                                0,                 // fromXDelta
                                0,                 // toXDelta
                                binding.carCardview.getHeight(),  // fromYDelta
                                0);                // toYDelta
                        animate2.setDuration(1000);
                        animate2.setFillAfter(true);
                        binding.carCardview.startAnimation(animate2);
                    }
                }, 500);