Sunday 29 January 2012

Android animation.Part-II


In this part we will focus on solving advance animation problems in Android. We have done simple animation in our previous tutorial now we will try create a more complex animation in a simpler way. We will create a simple animation that moves a Button from the top left corner of the screen to the center when it is clicked, then remains there, and when clicked again it moves back to its original position.

After you read the documentation http://developer.android.com/guide/topics/resources/animation-resource.h... it may seem easy to solve. We can define the animation relative to the parents size in percent (50%p), and the fillAfter attribute makes the button remain there, instead of jumping back to its original position. We can even define all of this in XML below.

      <?xml version="1.0" encoding="utf-8"?>
2       <translate xmlns:android="http://schemas.android.com/apk/res/android"
3          android:fromXDelta="0%p" android:fromYDelta="0%p"
4          android:toXDelta="50%p" android:toYDelta="50%p"
5          android:duration="1000"
6          android:fillAfter="true" />
But when you try this out, you will face two problems. First, the button will not be properly centered, the buttons top left corner will be in the center. Second, after it moved to the center it won’t be clickable any more. The clickable area of the button does not move with the animation, if you try to click at the original position of the button you will be able to trigger the onclick again. Unfortunately such a simple code, like the xml above will not be enough to fix these simple problem.
To properly center the button we must compute where the buttons top left corner should be. When the button is clicked get the buttons size, and its parent views size, compute where it should move, and create the proper animation by code. Somehow we have to track where the button is, if it is already in the middle, we have to reverse the animation. This can be done like this:
      public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
      final Button button = (Button) findViewById(R.id.button);
        final RelativeLayout mainContainer = (RelativeLayout)findViewById(R.id.mainContainer);
              button.setOnClickListener(new OnClickListener() {
           @Override
            public void onClick(View v) {
          //have to get the sizes here instead of onCreate, in onCreate size is not         //computed yet
          int buttonHeight = button.getHeight();
          int parentHeight = mainContainer.getHeight();
         int buttonWidth = button.getWidth ();
          int parentWidth  = mainContainer.getWidth();
       
        //detect if have to move to center, or already there and have to move back
         boolean isInCenter = button.getLeft()>0;
        final int fromX = isInCenter?(parentWidth/2)-(buttonWidth/2):0;
        final int fromY = isInCenter?(parentHeight/2)-(buttonHeight/2):0;
        final int toX = isInCenter?0:(parentWidth/2)-(buttonWidth/2);
        final int toY = isInCenter?0:(parentHeight/2)-(buttonHeight/2);
       
        //create the animation
            TranslateAnimation moveAnim = new TranslateAnimation(
            TranslateAnimation.ABSOLUTE, fromX, TranslateAnimation.ABSOLUTE, toX,
            TranslateAnimation.ABSOLUTE, fromY, TranslateAnimation.ABSOLUTE, toY);
                    moveAnim.setDuration(1000);
                    moveAnim.setFillAfter(true);

To solve the clickinkig problem we have to really move the button when the animation ended. This can be done by setting up an animation listener to detect the end of the animation. In the listener we set up margins to do the move. Because of this we have to remove this margins the next time we animate button or, the margins will mess it up. So we also add a listener to detect the start of the animation, and remove the margins there.


      moveAnim.setAnimationListener(new AnimationListener() {
        @Override
      public void onAnimationEnd(Animation animation) {
      //when the animation ended the button is really moved, to remain clickable
     LayoutParam params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
     params.leftMargin = toX;
     params.topMargin = toY;
     button.setLayoutParams(params);
          //remove the animation, its no longer needed, since button is really there
     button.clearAnimation();
    }
  
    @Override
    public void onAnimationStart(Animation animation) {
      //remove the margins used to really move the button, or it messes up the animation
    LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    params.leftMargin = 0;
    params.topMargin = 0;
    button.setLayoutParams(params);
    }
    @Override
    public void onAnimationRepeat(Animation animation) {
      //do nothing
    }
  });


Enjoy.... 
Do post your doubts, queries or suggestions in this blog.

No comments:

Post a Comment