Search code examples
androidandroid-fragmentsfragmenttransactionobjectanimator

Fragment Transition Animation using Object Animator not working


I just want to say this isn't a duplicate, this question hasn't been addressed on stack overflow

I have multiple fragments in the application that the user navigates through. I had the support library in my code but I have since removed it, when I was using it was I was animating the fragments with <translate> . I have now changed that to this works fine if I hard code in the values to and from. As my app will be used on different screen densities I can't do this. So after research and tutorials I created my custom FrameLayout as follows:

public class CustomFrameLayout extends FrameLayout{

    public CustomFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


   public float getXFraction() {
        return getX() / getWidth(); // TODO: guard divide-by-zero
    }

    public void setXFraction(float xFraction) {
        // TODO: cache width
        final int width = getWidth();
        setX((width > 0) ? (xFraction * width) : -9999);
    }
}

my animation xml is:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/linear_interpolator"
        android:valueFrom="1.0"
        android:valueTo="0"
        android:propertyName="xFraction"
        android:duration="@android:integer/config_mediumAnimTime" />
</set>

and my main activity layout is:

<com.axn.test.app.custom.CustomFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:gravity="top"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

I then have the code to set the custom animations:

FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
        ft.setCustomAnimations(R.animator.fragment_slide_in_right, R.animator.fragment_slide_in_right, R.animator.fragment_slide_in_right, R.animator.fragment_slide_out_right);

The problem is when I change fragments there is no animation and I get the following in the console:

W/PropertyValuesHolder﹕ Method setXFraction() with type float not found on target class class android.widget.RelativeLayout

So if anyone has come across this in the past or knows how to fix this issue I'd appreciate it. in my customFrameLayout setXFraction(float xFraction) and getXFraction() are never called so I'm not sure where to go from here...all input greatly appreciated

**EDIT ==== FRAGMENT LAYOUT ===== **

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background"
    >

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:layout_marginTop="20dp"
            android:layout_marginLeft="20dp"
            android:id="@+id/show1"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="true">

            <ImageView
                android:id="@+id/poster1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/poster1"/>
            <RelativeLayout
                android:id="@+id/poster1Details"
                android:background="@drawable/reflection1"
                android:layout_below="@+id/poster1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <TextView
                    android:id="@+id/poster1text"
                    android:layout_centerHorizontal="true"
                    android:textColor="@color/white"
                    android:textAppearance="?android:attr/textAppearanceMedium"
                    android:text="@string/poster1Title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/poster1text"
                    android:layout_centerHorizontal="true"
                    android:textColor="@color/white"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:text="@string/episode1"/>
            </RelativeLayout>
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/show2"
            android:layout_weight="1"
            android:layout_marginRight="10dp"
            android:layout_marginTop="20dp"
            android:layout_marginLeft="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="true">

            <ImageView
                android:id="@+id/poster2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/poster2"/>
            <RelativeLayout
                android:id="@+id/poster2Details"
                android:background="@drawable/reflection2"
                android:layout_below="@+id/poster2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <TextView
                    android:id="@+id/poster2text"
                    android:layout_centerHorizontal="true"
                    android:textColor="@color/white"
                    android:textAppearance="?android:attr/textAppearanceMedium"
                    android:text="@string/poster2Title"
                    android:gravity="center"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/poster2text"
                    android:layout_centerHorizontal="true"
                    android:textColor="@color/white"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:text="@string/episode1"/>

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

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/logos_backgrounds"
      />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/presents"
            android:textColor="@color/white"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="10dp"
            />
    </RelativeLayout>
</RelativeLayout>

Solution

  • The problem is that you are trying to animate a fragment. Not an activity. So you have to add the CustomFrameLayout on the fragment you are setting the animations to. Once your transaction takes place the transaction will animate the values on your fragment's parent and not your activity's. That's why you're getting Method setXFraction() with type float not found on target class class android.widget.RelativeLayout. Because the parent of your fragment is a RelativeLayout and it doesn't have the setXFraction method.

    Still I will left the rest of the anwser bellow because it might help others.

    in_from_left.xml

    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:propertyName="x"
        android:valueFrom="1000"
        android:valueTo="0"
        android:valueType="floatType" />
    

    in_from_right.xml

    <?xml version="1.0" encoding="utf-8"?>
    
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:propertyName="x"
        android:valueFrom="0"
        android:valueTo="1000"
        android:valueType="floatType" />
    

    And my transaction looks like this:

    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.setCustomAnimations(R.anim.in_from_left, R.anim.in_from_right, R.anim.in_from_left, R.anim.in_from_right);
    transaction.add(R.id.container,myFragment,"tag");
    transaction.commit();