0

Here is my problem. I have a LinearLayout that has clickable=true for an onTouch Event so that when the LinearLayout is touched, it slides up the screen. This works, but afterward when the onTouch Event is fired from the new location nothing happens.

Steps:

  1. I touch the LinearLayout and it moves up like it should.
  2. I touch it again and nothing happens
  3. I touch the part of the screen where the LinearLayout was originally the LinearLayout will toggle like it should.

It appears as if the view has moved to a new location but in reality it has not.

Below is my xml & code.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/julyContainer"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">


        <RelativeLayout android:id="@+id/rel01"/> 
        <ImageView />
        </RelativeLayout>

        <ImageView             
            android:id="@+id/shadow"
            android:paddingTop="6dip"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/header_barshadow"/>

<ScrollView 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="@drawable/bg_calendar" 
    android:id="@+id/calScroller">


<RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">        

        <LinearLayout android:id="@+id/circleLayout"
                android:orientation="horizontal"
                android:clickable="true"
                android:onClick="@string/circleAction"              
                android:paddingTop="10dip"
                android:paddingLeft="10dip"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <Button 
                android:id="@+id/circleCal"
                android:background="@drawable/cal_circle_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="@string/circleAction"/>

                <LinearLayout 
                android:id="@+id/circleLayout01"
                android:orientation="vertical"        
            android:paddingLeft="10dip"
            android:paddingRight="3dip"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView/>  
                <TextView/>  
                <TextView/>  

               <LinearLayout android:id="@+id/julylayout2"
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:orientation="vertical">

              <TextView/>

               </LinearLayout>

            </LinearLayout>
        </LinearLayout>

       <ImageView android:id="@+id/etch1"
                  android:src="@drawable/etch_calendar"
                  android:paddingTop="15dip"
                  android:paddingBottom="15dip"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_below="@id/circleLayout"/>                     

      <LinearLayout android:id="@+id/squareLayout"
                android:clickable="true"
                android:onClick="@string/squareAction"              
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="10dip"
                android:layout_below="@id/etch1">
        <Button 
                android:id="@+id/squareCal"
                android:background="@drawable/cal_square_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="@string/squareAction"/>

                <LinearLayout
            android:orientation="vertical"
            android:paddingLeft="10dip"
            android:paddingRight="3dip"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

                <TextView/>  
                <TextView/>  
                <TextView/> 

               <LinearLayout android:id="@+id/layout3"
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:orientation="vertical">

                    <TextView/>  

               </LinearLayout>
        </LinearLayout>        
    </LinearLayout>        

</RelativeLayout>
</ScrollView>      
</LinearLayout>  

CODE:

private void slideUp(View view) {
    Animation slide = new TranslateAnimation(
            Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
            0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -0.25f);
    slide.setDuration(1000);
    slide.setFillAfter(true);
    slide.setFillEnabled(true);

    view.startAnimation(slide);
}

private void slideDown(View view) {
    Animation slide = new TranslateAnimation(
            Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
            0.0f, Animation.RELATIVE_TO_SELF, -0.25f, Animation.RELATIVE_TO_SELF, 0.0f);
    slide.setDuration(1000);
    slide.setFillAfter(true);
    slide.setFillEnabled(true);
    view.startAnimation(slide);
}

NEW CHANGES: output of new positions

07-05 13:20:22.084: I/System.out(15187): onAnimationStart 0 , 120

07-05 13:20:23.053: I/System.out(15187): onAnimationEnd 0 , 120

private void slideUp(final View view) {

        Animation slide = new TranslateAnimation(
                Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
                0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -0.75f);
        slide.setDuration(1000);
        slide.setFillAfter(true);
        slide.setFillEnabled(true);
        view.startAnimation(slide);
        slide.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
                int[] startPosition = new int[2];
                view.getLocationOnScreen(startPosition);
                System.out.println("onAnimationStart " + startPosition[0] + " , " + startPosition[1]);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                final int left = view.getLeft();
                final int top = view.getTop();
                final int right = view.getRight();
                final int bottom = view.getBottom();

                int offset = (int) 0.75;
                view.layout(left, top + offset * top, right, bottom + offset * bottom);

                int[] endPosition = new int[2];
                view.getLocationOnScreen(endPosition);
                System.out.println("onAnimationEnd " + endPosition[0] + " , " + endPosition[1]);

            }

        });


    }
Byron
  • 3,833
  • 9
  • 34
  • 39

1 Answers1

2

This is normal behaviour for android animation. It is happening because animation does not really moves the layout so it's position on the display remains the same. If you want to relocate your layout to the place where your animation ends, you need to call yourLayout.layout() method and pass there 4 parameters, which describe layout's new position. Keep in mind that layout() gets params relative to it's parent.

See sample code below

private AnimationListener slideDownAnimationListener = new AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            final int left = view.getLeft();
            final int top = view.getTop();
            final int right = view.getRight();
            final int bottom = view.getBottom();
            view.layout(left, top - 0.25 * top, right, bottom - 0.25 * bottom);
        }
};

private Animation slideDownAnimation = new TranslateAnimation(
                                     Animation.RELATIVE_TO_SELF, 0.0f,
                                     Animation.RELATIVE_TO_SELF, 0.0f,
                                     Animation.RELATIVE_TO_SELF, -0.25f,
                                     Animation.RELATIVE_TO_SELF, 0.0f
                                     );

private void slideDown(final View view) {
    slide.setDuration(1000);
    slide.setFillAfter(true);
    slide.setFillEnabled(true);
    slide.setAnimationListener(slideDownAnimationListener);
    view.startAnimation(slideDownAnimation);
}
Rafael T
  • 15,401
  • 15
  • 83
  • 144
vasart
  • 6,692
  • 38
  • 39
  • Thank you @vasart, that makes sense. Can you provide a small example of how to calculate the new position from the top? – Byron Jul 05 '12 at 15:59
  • In my scenario I am animating the top level LinearLayout would this cause a problem for me in trying to get layout params? – Byron Jul 05 '12 at 18:05
  • I made the following change but had no effect. Please view my updated code. – Byron Jul 05 '12 at 20:21
  • Sorry, you have to change places of the `startAnimation` and `setAnimationListener` – vasart Jul 05 '12 at 20:30
  • BTW, Thanks for your patience on this. I did that change but had no effect. I did however make a small change to your layout calculation.Since we cannot use a double value in the view.layout parameters I did a cast to an int example: int tempVal = (int)0.75; this however comes out to a zero value. Is there another way to do the calculation so that It will work with the double values? – Byron Jul 05 '12 at 20:43
  • Use `Math.round(0.75f * top)` – vasart Jul 05 '12 at 21:06
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/13486/discussion-between-byron-and-vasart) – Byron Jul 05 '12 at 21:39
  • Can anyone explain the purpose of the default state being animating the "pixels" but not the view itself? Is this for performance reasons? – Alfie Hanssen Oct 02 '13 at 20:49