对象动画师动画后视图切换器的奇怪问题

时间:2012-04-11 11:26:49

标签: android android-animation viewswitcher

我有两个LinearLayout视图,其中包含许多编辑文本和复选框,用于输入用户信息(名称,电子邮件地址等)。当其中一个字段的验证失败时,会显示一条消失的文本视图,显示验证错误。

我在ViewSwitcher中包含了两个布局,并使用ObjectAnimator类在两个视图之间进行动画处理。 (由于代码需要支持旧版本的Android,我实际上使用的是nineoldandroids向后兼容库。)

大部分工作都是在我的switchToChild方法中执行的。

如果我将视图翻转两次以上,那么我就会遇到奇怪的错误。

首先,虽然显示了视图动画师的正确子视图,但似乎另一个视图具有焦点,我可以单击当前视图下方的视图。我通过在第一个动画结束时添加一个viewSwitcher.bringChildToFront解决了这个问题。

当我这样做并在第二个视图上执行验证时,我现在设置为可见的“已消失”视图不会显示(就好像线性布局永远不会被重新测量一样)。以下是XML文件的子集:

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/TitleBar"
    android:scrollbarAlwaysDrawVerticalTrack="true"
    android:scrollbarStyle="outsideOverlay"
    android:scrollbars="vertical" >

    <ViewSwitcher
        android:id="@+id/switcher"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:id="@+id/page_1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

        <!-- Lots of subviews here -->

        <LinearLayout
            android:id="@+id/page_2"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

这是在视图之间翻转的主要方法:

private void switchToChild(final int child) {
  final ViewSwitcher viewSwitcher = (ViewSwitcher) findViewById(R.id.switcher);
  if (viewSwitcher.getDisplayedChild() != child) {
    final Interpolator accelerator = new AccelerateInterpolator();
    final Interpolator decelerator = new DecelerateInterpolator();
    final View visibleView;
    final View invisibleView;
    switch (child) {
      case 0:
        visibleView = findViewById(R.id.page_2);
        invisibleView = findViewById(R.id.page_1);
        findViewById(R.id.next).setVisibility(View.VISIBLE);
        findViewById(R.id.back).setVisibility(View.GONE);
        break;
      case 1:
      default:
        visibleView = findViewById(R.id.page_1);
        invisibleView = findViewById(R.id.page_2);
        findViewById(R.id.back).setVisibility(View.VISIBLE);
        findViewById(R.id.next).setVisibility(View.GONE);
        break;
    }
    final ObjectAnimator visToInvis = ObjectAnimator.ofFloat(visibleView, "rotationY", 0f, 90f).setDuration(250);
    visToInvis.setInterpolator(accelerator);

    final ObjectAnimator invisToVis = ObjectAnimator.ofFloat(invisibleView, "rotationY", -90f, 0f).setDuration(250);
    invisToVis.setInterpolator(decelerator);

    visToInvis.addListener(new AnimatorListenerAdapter() {

      @Override
      public void onAnimationEnd(Animator anim) {
        viewSwitcher.showNext();
        invisToVis.start();
        viewSwitcher.bringChildToFront(invisibleView); // If I don't do this the old view can have focus

      }
    });
    visToInvis.start();

  }
}

有没有人有任何想法?这让我很困惑!

1 个答案:

答案 0 :(得分:0)

看起来最好的解决方案是不使用视图切换器,而是通过在两个页面周围声明FrameLayout并将第二页的可见性设置为消失来有效地创建我自己的视频切换器。

switchToChild方法(我应该重命名以切换到页面并实际传入1或2值)只是将相应的视图设置为在动画期间可见:

private void switchToChild(final int child) {
  final Interpolator accelerator = new AccelerateInterpolator();
  final Interpolator decelerator = new DecelerateInterpolator();
  final View visibleView;
  final View invisibleView;
  switch (child) {
  case 0:
    visibleView = findViewById(R.id.page_2);
    invisibleView = findViewById(R.id.page_1);
    findViewById(R.id.next).setVisibility(View.VISIBLE);
    findViewById(R.id.back).setVisibility(View.GONE);
    break;
  case 1:
  default:
    visibleView = findViewById(R.id.page_1);
    invisibleView = findViewById(R.id.page_2);
    findViewById(R.id.back).setVisibility(View.VISIBLE);
    findViewById(R.id.next).setVisibility(View.GONE);
    break;
  }
  if (invisibleView.getVisibility() != View.VISIBLE) {
    final ObjectAnimator visToInvis = ObjectAnimator.ofFloat(visibleView, "rotationY", 0f, 90f).setDuration(250);
    visToInvis.setInterpolator(accelerator);

    final ObjectAnimator invisToVis = ObjectAnimator.ofFloat(invisibleView, "rotationY", -90f, 0f).setDuration(250);
    invisToVis.setInterpolator(decelerator);

    visToInvis.addListener(new AnimatorListenerAdapter() {
      @Override
      public void onAnimationEnd(Animator anim) {
        visibleView.setVisibility(View.GONE);
        invisibleView.setVisibility(View.VISIBLE);

        invisToVis.start();

      }
    });
    visToInvis.start();
  }

}