Android Translate Animation like Swapping Two View

2019-02-11 01:44发布

问题:

I'm trying to simulate swapping two views (one goes up and ones go down) with Translate animation.

Basically, it swaps and re-swap again.

This is my activity.

  LinearLayout topView, belowView;
  TextView foo, bar;
  int viewHeight;
  boolean noSwap = true;
  private static int ANIMATION_DURATION = 3000;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_slide);

    topView = (LinearLayout) findViewById(R.id.top_view);
    belowView = (LinearLayout) findViewById(R.id.below_view);

    foo = (TextView) findViewById(R.id.foo);
    bar = (TextView) findViewById(R.id.bar);

    ImageButton btnSwitch = (ImageButton) findViewById(R.id.switch_btn);

    ViewTreeObserver viewTreeObserver = foo.getViewTreeObserver();
    if (viewTreeObserver.isAlive()) {
      viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
          foo.getViewTreeObserver().addOnGlobalLayoutListener(this);
          viewHeight = foo.getHeight();
          foo.getLayoutParams();
        }
      });
    }

    btnSwitch.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
        if (noSwap) {
          //Log.d("Swap Status", "Not Swapping yet ? " + true);

          TranslateAnimation ta1 = new TranslateAnimation(0, 0, 0, viewHeight);
          ta1.setDuration(ANIMATION_DURATION);
          ta1.setFillAfter(true);
          topView.startAnimation(ta1);
          topView.bringToFront();

          belowView.setY(0);
          TranslateAnimation ta2 = new TranslateAnimation(0, 0, 0, -viewHeight);
          ta2.setDuration(ANIMATION_DURATION);
          ta2.setFillAfter(true);
          belowView.startAnimation(ta2);
          belowView.bringToFront();

          noSwap = false;
        } else {
          //Log.d("Swap Status", "Swapped already ? " + true);

          TranslateAnimation ta1 = new TranslateAnimation(0, 0, viewHeight, 0);
          ta1.setDuration(ANIMATION_DURATION);
          ta1.setFillAfter(true);
          topView.startAnimation(ta1);
          topView.bringToFront();

          belowView.setY(0);

          TranslateAnimation ta2 = new TranslateAnimation(0, 0, 0, viewHeight);
          ta2.setDuration(ANIMATION_DURATION);
          ta2.setFillAfter(true);
          belowView.startAnimation(ta2);
          belowView.bringToFront();

          noSwap = true;
        }
      }
    });
  } 

This is the layout.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${packageName}.${activityClass}">

  <LinearLayout
      android:id="@+id/top_view"
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="wrap_content">
    <TextView
        android:id="@+id/foo"
        android:text="@string/foo"
        android:textSize="30sp"
        android:textColor="@android:color/holo_purple"
        android:padding="10dp"
        android:fontFamily="sans-serif-condensed"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
  </LinearLayout>

  <LinearLayout
      android:id="@+id/below_view"
      android:layout_below="@+id/top_view"
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="wrap_content">
    <TextView
        android:id="@+id/bar"
        android:text="@string/bar"
        android:textSize="30sp"
        android:textColor="@android:color/holo_red_light"
        android:padding="10dp"
        android:fontFamily="sans-serif-condensed"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
  </LinearLayout>

  <ImageButton android:id="@+id/switch_btn"
      style="?android:borderlessButtonStyle"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:src="@drawable/ic_action_import_export"
      android:contentDescription="@string/swap"
      android:layout_alignParentBottom="true"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"/>

</RelativeLayout>

Everything seems fine until I click the Switch button for third times when the top view is supposed to go down and below view is to go up. But the starting position of the below view is not correct. I've tried setting several positions to below view but still can't get it right.

I've made a screencast about it here.

回答1:

I think I get it right. Here's the working class.

LinearLayout topView, belowView;
  TextView foo, bar;
  int viewHeight;
  boolean noSwap = true;
  private static int ANIMATION_DURATION = 300;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_slide);

    topView = (LinearLayout) findViewById(R.id.top_view);
    belowView = (LinearLayout) findViewById(R.id.below_view);

    foo = (TextView) findViewById(R.id.foo);
    bar = (TextView) findViewById(R.id.bar);

    ImageButton btnSwitch = (ImageButton) findViewById(R.id.switch_btn);

    ViewTreeObserver viewTreeObserver = foo.getViewTreeObserver();
    if (viewTreeObserver.isAlive()) {
      viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
          foo.getViewTreeObserver().addOnGlobalLayoutListener(this);
          viewHeight = foo.getHeight();
          foo.getLayoutParams();
        }
      });
    }

    btnSwitch.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
        if (noSwap) {
          TranslateAnimation ta1 = new TranslateAnimation(0, 0, 0, viewHeight);
          ta1.setDuration(ANIMATION_DURATION);
          ta1.setFillAfter(true);
          topView.startAnimation(ta1);
          topView.bringToFront();

          TranslateAnimation ta2 = new TranslateAnimation(0, 0, 0, -viewHeight);
          ta2.setDuration(ANIMATION_DURATION);
          ta2.setFillAfter(true);
          belowView.startAnimation(ta2);
          belowView.bringToFront();

          noSwap = false;
        } else {
          TranslateAnimation ta1 = new TranslateAnimation(0, 0, viewHeight, 0);
          ta1.setDuration(ANIMATION_DURATION);
          ta1.setFillAfter(true);
          topView.startAnimation(ta1);
          topView.bringToFront();

          TranslateAnimation ta2 = new TranslateAnimation(0, 0, -viewHeight, 0);
          ta2.setDuration(ANIMATION_DURATION);
          ta2.setFillAfter(true);
          belowView.startAnimation(ta2);
          belowView.bringToFront();

          noSwap = true;
        }
      }
    });
  }