FragmentTransaction动画:onAnimationEnd在它真正结束之前被调用

时间:2014-11-17 07:42:54

标签: android android-fragments

我的问题与this question非常相似,只是我需要它来处理片段而不是视图。

正如该线程中所解释的,当AnimationListener附加到Animation时,Android中似乎存在一个错误(?),这导致在动画真正完全结束之前调用onAnimationEnd()回调。

我使用在FragmentTransaction(v4支持库)中设置动画的全屏片段来进行横向播放"滚动播放"影响。除了在我启动相机预览的片段中,这种方法在任何地方都能顺利运行因此,我想只在动画结束后启动相机预览。

我尝试在片段中使用此方法:

@Override
public Animation onCreateAnimation(final int transit,final boolean enter,final int nextAnim)
{
  Animation anim=super.onCreateAnimation(transit, enter, nextAnim);

  if (anim==null && nextAnim!=0)
    anim=AnimationUtils.loadAnimation(getActivity(), nextAnim);

  if(anim!=null)
  {
    anim.setAnimationListener(new AnimationListener() {

    @Override
    public void onAnimationStart(Animation animation)
    {
    }

    @Override
    public void onAnimationRepeat(Animation animation)
    {
    }

    @Override
    public void onAnimationEnd(Animation animation)
    {
      scannerView.startCameraInHandlerThread();
    }
  });
}

不幸的是,启动相机是一项非常昂贵的操作,因此我的动画在动画结束之前每次都会滞后。它看起来很难看,我的客户抱怨它。

我还想过一个便宜的解决方案,比如在相机线程上等待/休眠,但是主线程实际上需要等待相机启动线程进行同步,否则它会在某些情况下死锁,所以睡眠实际上会使问题变得更糟(滞后变得更长了。)

有谁知道如何解决这个问题?


编辑:有人要求提供更多代码...

public void startCameraInHandlerThread()
{
  if (mThread == null)
    mThread = new CameraHandlerThread();

  synchronized (mThread) {
    mThread.openCamera();
  }
}

private class CameraHandlerThread extends HandlerThread
{
  Handler mHandler = null;

  CameraHandlerThread()
  {
    super("CameraHandlerThread");
    start();
    mHandler = new Handler(getLooper());
  }

  synchronized void notifyCameraActionCompleted() {
    notify();
  }

  void openCamera()
  {
    mHandler.post(new Runnable() {
      @Override
      public void run() {
        startCamera();
        notifyCameraActionCompleted();
      }
    });

    try
    {
      wait();
    }
    catch (InterruptedException e)
    {
      Thread.currentThread().interrupt();
      LOG.warn("Waiting for camera opening was interrupted");
    }
  }
}

1 个答案:

答案 0 :(得分:0)

我能够提出一个解决方法:只需延迟我的方法的启动很短的时间,让动画时间运行完成。在我的客户将使用的设备上,这工作正常,但我不觉得它是一般的解决方案,因此我不会将此标记为已接受的答案。

@Override
public void onAnimationEnd(Animation animation)
{
  new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
      scannerView.startCameraInHandlerThread();
    }
  }, 10); // will start after 10ms
}