I mainly worked with iOS and got used to very smooth and smooth screen change animations. I am currently working on an Android application and cannot get a fragment transaction for the whole life to smoothly add / replace a fragment.
My setup is this: MainActivity has a FrameLayout for my xml, which I immediately load FragmentA into MainActivity OnCreate . Then my application replaces MainActivity FrameLayout with FragmentB , FragmentC , ect. Thus, my entire application has 1 activity.
In the button clicks, I call the following to add / replace the current fragment:
getFragmentManager() .beginTransaction() .setCustomAnimations(R.animator.slide_in, android.R.animator.fade_out, android.R.animator.fade_in, R.animator.slide_out) .addToBackStack(null) .add(R.id.fragment_1, fragment) .commit();
slide_in.xml looks like (slide_out.xml is clearly the opposite):
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:interpolator="@android:interpolator/linear" android:propertyName="xFraction" android:valueType="floatType" android:valueFrom="1.0" android:valueTo="0" android:duration="@android:integer/config_shortAnimTime" /> </set>
Insertion and shutdown I am an xFraction animation that I have subclassed LinearLayout to do this:
public class SlidingLinearLayout extends LinearLayout { private float yFraction = 0; private float xFraction = 0; public SlidingLinearLayout(Context context) { super(context); } public SlidingLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } public SlidingLinearLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } private ViewTreeObserver.OnPreDrawListener preDrawListener = null; public void setYFraction(float fraction) { this.yFraction = fraction; if (getHeight() == 0) { if (preDrawListener == null) { preDrawListener = new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { getViewTreeObserver().removeOnPreDrawListener(preDrawListener); setYFraction(yFraction); return true; } }; getViewTreeObserver().addOnPreDrawListener(preDrawListener); } return; } float translationY = getHeight() * fraction; setTranslationY(translationY); } public float getYFraction() { return this.yFraction; } public void setXFraction(float fraction) { this.xFraction = fraction; if (getWidth() == 0) { if (preDrawListener == null) { preDrawListener = new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { getViewTreeObserver().removeOnPreDrawListener(preDrawListener); setXFraction(xFraction); return true; } }; getViewTreeObserver().addOnPreDrawListener(preDrawListener); } return; } float translationX = getWidth() * fraction; setTranslationX(translationX); } public float getxFraction() { return xFraction; } }
So, my problem in most cases, when I initially clicked a button to add / replace a fragment, I do not get the animation, these are just pop-ups. However, more times than when I click the "Back" button, and a fragment appears from the back of the screen, the animation runs as expected. I feel this is an initialization issue when trying to revive. When a fragment is in memory and animated from the screen, it does it much better than when a new fragment is created, and then animated on the screen. I am curious if others have experienced this, and if so, how did they resolve it.
This is the annoyance that haunted my Android development experience, which I really would like to relax! Any help would be greatly appreciated. Thanks!