0

我有两个 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();

  }
}

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

4

1 回答 1

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();
  }

}
于 2012-04-29T14:25:40.553 回答