Android - TabActivity with Transition animation

2019-01-14 09:45发布

问题:

I'm trying to add an animation to my TabActivty. For example, when the user select the 2nd tab, I want the new activity comes from the right. When the user select the first tab, I want the activity comes from the left.

I've found how to add one animation, but I want to add one again. Here is the code I'm using:

public Animation inFromRightAnimation()
{
    Animation inFromRight = new TranslateAnimation(
            Animation.RELATIVE_TO_PARENT, +1.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f);
    inFromRight.setDuration(240);
    inFromRight.setInterpolator(new AccelerateInterpolator());
    return inFromRight;
}

And

getTabHost().setOnTabChangedListener(new OnTabChangeListener() {
       public void onTabChanged(String tabId)
       {
           View currentView = getTabHost().getCurrentView();
           currentView.setAnimation( inFromRightAnimation() );
       }
});

How can I do that?

Thanks.

Regards.

V.

回答1:

This works correctly:

getTabHost().setOnTabChangedListener(new OnTabChangeListener() {
     public void onTabChanged(String tabId)
     {
            View currentView = getTabHost().getCurrentView();
            if (getTabHost().getCurrentTab() > currentTab)
            {
                currentView.setAnimation( inFromRightAnimation() );
            }
            else
            {
                currentView.setAnimation( outToRightAnimation() );
            }

            currentTab = getTabHost().getCurrentTab();
     }
});

And the animations:

public Animation inFromRightAnimation()
{
    Animation inFromRight = new TranslateAnimation(
            Animation.RELATIVE_TO_PARENT, +1.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f);
    inFromRight.setDuration(240);
    inFromRight.setInterpolator(new AccelerateInterpolator());
    return inFromRight;
}

public Animation outToRightAnimation()
{
    Animation outtoLeft = new TranslateAnimation(
            Animation.RELATIVE_TO_PARENT, -1.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f);
    outtoLeft.setDuration(240);
    outtoLeft.setInterpolator(new AccelerateInterpolator());
    return outtoLeft;
}


回答2:

I wrote a custom OnTabChangeListener based on this code that I wanted to share. Hopefully someone can use it :). Credit goes to Vomenki for original code.

package net.danielkvist.receipttracker.listener;

import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;

/**
 * A custom OnTabChangeListener that uses the TabHost its related to to fetch information about the current and previous
 * tabs. It uses this information to perform some custom animations that slide the tabs in and out from left and right.
 * 
 * @author Daniel Kvist
 * 
 */
public class AnimatedTabHostListener implements OnTabChangeListener
{

    private static final int ANIMATION_TIME = 240;
    private TabHost tabHost;
    private View previousView;
    private View currentView;
    private int currentTab;

    /**
     * Constructor that takes the TabHost as a parameter and sets previousView to the currentView at instantiation
     * 
     * @param tabHost
     */
    public AnimatedTabHostListener(TabHost tabHost)
    {
        this.tabHost = tabHost;
        this.previousView = tabHost.getCurrentView();
    }

    /**
     * When tabs change we fetch the current view that we are animating to and animate it and the previous view in the
     * appropriate directions.
     */
    @Override
    public void onTabChanged(String tabId)
    {

        currentView = tabHost.getCurrentView();
        if (tabHost.getCurrentTab() > currentTab)
        {
            previousView.setAnimation(outToLeftAnimation());
            currentView.setAnimation(inFromRightAnimation());
        }
        else
        {
            previousView.setAnimation(outToRightAnimation());
            currentView.setAnimation(inFromLeftAnimation());
        }
        previousView = currentView;
        currentTab = tabHost.getCurrentTab();

    }

    /**
     * Custom animation that animates in from right
     * 
     * @return Animation the Animation object
     */
    private Animation inFromRightAnimation()
    {
        Animation inFromRight = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 1.0f, Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f);
        return setProperties(inFromRight);
    }

    /**
     * Custom animation that animates out to the right
     * 
     * @return Animation the Animation object
     */
    private Animation outToRightAnimation()
    {
        Animation outToRight = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 1.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f);
        return setProperties(outToRight);
    }

    /**
     * Custom animation that animates in from left
     * 
     * @return Animation the Animation object
     */
    private Animation inFromLeftAnimation()
    {
        Animation inFromLeft = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, -1.0f, Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f);
        return setProperties(inFromLeft);
    }

    /**
     * Custom animation that animates out to the left
     * 
     * @return Animation the Animation object
     */
    private Animation outToLeftAnimation()
    {
        Animation outtoLeft = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, -1.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f);
        return setProperties(outtoLeft);
    }

    /**
     * Helper method that sets some common properties
     * @param animation the animation to give common properties
     * @return the animation with common properties
     */
    private Animation setProperties(Animation animation)
    {
        animation.setDuration(ANIMATION_TIME);
        animation.setInterpolator(new AccelerateInterpolator());
        return animation;
    }
}


回答3:

You have to use String tabId and check if this tabId==firstTab then put animation from left else animation from right.



回答4:

If you like, you can use Android Support Package - http://developer.android.com/sdk/compatibility-library.html

With little effort you can modify your activity to use fragments so your tabs can have transition animations just like the YouTube app. Here is a sample code of how to implement it - http://developer.android.com/sdk/compatibility-library.html

Edit: If you don't want to use support package, maybe this implementation will help

private class MyGestureDetector extends SimpleOnGestureListener {

      private static final int SWIPE_MIN_DISTANCE = 120;
      private static final int SWIPE_MAX_OFF_PATH = 250;
      private static final int SWIPE_THRESHOLD_VELOCITY = 200;

      public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        //get density   
          final DisplayMetrics metrics = getResources().getDisplayMetrics();
          final float density = metrics.density;
       //System.out.println(" in onFling() :: ");
          //off path
          if (Math.abs(e1.getY() - e2.getY()) > density*SWIPE_MAX_OFF_PATH)
              return false;
          //fling from right to left
          if (e1.getX() - e2.getX() > density*SWIPE_MIN_DISTANCE && Math.abs(velocityX) > density*SWIPE_THRESHOLD_VELOCITY) {
              //if the first tab is selected
              if(currentSelection.equalsIgnoreCase(getString(R.string.tab_details_info))) {
                  //switch to second tab and save current selection
                  tabs.setCurrentTab(1);
                  currentSelection = tabs.getCurrentTabTag();
              }
              //if the second tab is selected
              else if(currentSelection.equalsIgnoreCase(getString(R.string.tab_details_details))) {
                  //switch to second tab and save current selection
                  tabs.setCurrentTab(2);
                  currentSelection = tabs.getCurrentTabTag();
              }
          }
          //fling from left to right
          else if (e2.getX() - e1.getX() > density*SWIPE_MIN_DISTANCE && Math.abs(velocityX) > density*SWIPE_THRESHOLD_VELOCITY) {

              //if the second tab is selected
              if(currentSelection.equalsIgnoreCase(getString(R.string.tab_details_details))) {
                  //switch to second tab and save current selection
                  tabs.setCurrentTab(0);
                  currentSelection = tabs.getCurrentTabTag();
              }
              //if the third tab is selected
              else if(currentSelection.equalsIgnoreCase(getString(R.string.tab_details_company))) {
                  //switch to second tab and save current selection
                  tabs.setCurrentTab(1);
                  currentSelection = tabs.getCurrentTabTag();
              }
          }
          return super.onFling(e1, e2, velocityX, velocityY);
      }
}

and then on your tab changed listener just load the appropriate animation since you know which one was selected before the gesture, and the one that we are switching to after.

        @Override
        public void onTabChanged(String tabId) {



            //if the first tab is selected
            if(currentSelection.equalsIgnoreCase(getResources().getString(R.string.tab_details_info))) {
                //if we switch to second
                if(tabId.equalsIgnoreCase(getResources().getString(R.string.tab_details_details))) {
                    linearInfo.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_left_out));
                    linearDetails.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_left_in));
                    linearCompany.setAnimation(null);
                }
                //if switch to third
                else if(tabId.equalsIgnoreCase(getResources().getString(R.string.tab_details_company))) {
                    linearInfo.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_left_out));
                    linearDetails.setAnimation(null);
                    linearCompany.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_left_in));
                }
            }
            //if the second tab is selected
            else if(currentSelection.equalsIgnoreCase(getResources().getString(R.string.tab_details_details))) {
                //if we switch to first
                if(tabId.equalsIgnoreCase(getResources().getString(R.string.tab_details_info))) {
                    linearInfo.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_right_in));
                    linearDetails.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_right_out));
                    linearCompany.setAnimation(null);
                }
                //if switch to third
                else if(tabId.equalsIgnoreCase(getResources().getString(R.string.tab_details_company))) {
                    linearInfo.setAnimation(null);
                    linearDetails.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_left_out));
                    linearCompany.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_left_in));
                }
            }
            //if the third tab is selected
            else if(currentSelection.equalsIgnoreCase(getResources().getString(R.string.tab_details_company))) {
                //if we switch to first
                if(tabId.equalsIgnoreCase(getResources().getString(R.string.tab_details_info))) {
                    linearInfo.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_right_in));
                    linearDetails.setAnimation(null);
                    linearCompany.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_right_out));
                }
                //if switch to second
                else if(tabId.equalsIgnoreCase(getResources().getString(R.string.tab_details_details))) {
                    linearInfo.setAnimation(null);
                    linearDetails.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_right_in));
                    linearCompany.setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_right_out));
                }
            }

            currentSelection = tabId;
        }
    };

Also you need to catch the gesture by overriding the onTouchListener with you custom gesture detector (and maybe account for different screen density when determining if a gesture is a swipe action)

Sorry for the long answer, but I hope it helps :)