optimize Fragment Animation

androidx
Ztiany 5 years ago
parent f98ce6f6e4
commit 2e89356efe
  1. 102
      lib_base/src/main/java/com/android/base/app/fragment/AnimatorHelper.java
  2. 8
      lib_base/src/main/java/com/android/base/app/fragment/BaseFragment.java
  3. 40
      lib_base/src/main/java/com/android/base/app/fragment/DefaultHorizontalAnimator.java
  4. 42
      lib_base/src/main/java/com/android/base/app/fragment/DefaultNoAnimator.java
  5. 56
      lib_base/src/main/java/com/android/base/app/fragment/DefaultScaleAnimator.java
  6. 40
      lib_base/src/main/java/com/android/base/app/fragment/DefaultVerticalAnimator.java
  7. 102
      lib_base/src/main/java/com/android/base/app/fragment/FragmentAnimator.java
  8. 103
      lib_base/src/main/java/com/android/base/app/fragment/FragmentAnimatorHelper.java
  9. 4
      lib_base/src/main/java/com/android/base/app/fragment/Fragments.kt
  10. 17
      lib_base/src/main/java/com/android/base/utils/android/views/ResourceEx.kt
  11. 0
      lib_base/src/main/res/anim/base_no_anim.xml
  12. 0
      lib_base/src/main/res/anim/h_fragment_close_enter.xml
  13. 20
      lib_base/src/main/res/anim/h_fragment_close_exit.xml
  14. 10
      lib_base/src/main/res/anim/h_fragment_exit.xml
  15. 0
      lib_base/src/main/res/anim/h_fragment_open_enter.xml
  16. 19
      lib_base/src/main/res/anim/h_fragment_open_exit.xml
  17. 9
      lib_base/src/main/res/anim/h_fragment_pop_exit.xml
  18. 9
      lib_base/src/main/res/anim/pop_exit_no_anim.xml
  19. 0
      lib_base/src/main/res/anim/v_fragment_close_enter.xml
  20. 0
      lib_base/src/main/res/anim/v_fragment_close_exit.xml
  21. 0
      lib_base/src/main/res/anim/v_fragment_open_enter.xml
  22. 0
      lib_base/src/main/res/anim/v_fragment_open_exit.xml

@ -1,102 +0,0 @@
package com.android.base.app.fragment;
import android.content.Context;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import com.android.base.R;
import androidx.fragment.app.FragmentTransaction;
public final class AnimatorHelper {
private Animation noneAnim, noneAnimFixed;
private Animation enterAnim, exitAnim, popEnterAnim, popExitAnim;
private Context context;
private FragmentAnimator fragmentAnimator;
AnimatorHelper(Context context, FragmentAnimator fragmentAnimator) {
this.context = context;
notifyChanged(fragmentAnimator);
}
void notifyChanged(FragmentAnimator fragmentAnimator) {
this.fragmentAnimator = fragmentAnimator;
if (fragmentAnimator != null) {
initEnterAnim();
initExitAnim();
initPopEnterAnim();
initPopExitAnim();
}
}
public Animation getNoneAnim() {
if (noneAnim == null) {
noneAnim = AnimationUtils.loadAnimation(context, R.anim.no_anim);
}
return noneAnim;
}
public Animation getNoneAnimFixed() {
if (noneAnimFixed == null) {
noneAnimFixed = new Animation() {
};
}
return noneAnimFixed;
}
private Animation initEnterAnim() {
if (fragmentAnimator.getEnter() == 0) {
enterAnim = AnimationUtils.loadAnimation(context, R.anim.no_anim);
} else {
enterAnim = AnimationUtils.loadAnimation(context, fragmentAnimator.getEnter());
}
return enterAnim;
}
private Animation initExitAnim() {
if (fragmentAnimator.getExit() == 0) {
exitAnim = AnimationUtils.loadAnimation(context, R.anim.no_anim);
} else {
exitAnim = AnimationUtils.loadAnimation(context, fragmentAnimator.getExit());
}
return exitAnim;
}
private Animation initPopEnterAnim() {
if (fragmentAnimator.getPopEnter() == 0) {
popEnterAnim = AnimationUtils.loadAnimation(context, R.anim.no_anim);
} else {
popEnterAnim = AnimationUtils.loadAnimation(context, fragmentAnimator.getPopEnter());
}
return popEnterAnim;
}
private Animation initPopExitAnim() {
if (fragmentAnimator.getPopExit() == 0) {
popExitAnim = AnimationUtils.loadAnimation(context, R.anim.no_anim);
} else {
popExitAnim = AnimationUtils.loadAnimation(context, fragmentAnimator.getPopExit());
}
return popExitAnim;
}
Animation onCreateAnimation(BaseFragment baseFragment, int transit, boolean enter, int nextAnim) {
if (transit == FragmentTransaction.TRANSIT_FRAGMENT_OPEN) {
if (enter) {
return enterAnim;
} else {
return popExitAnim;
}
} else if (transit == FragmentTransaction.TRANSIT_FRAGMENT_CLOSE) {
if (enter) {
return popEnterAnim;
} else {
return exitAnim;
}
}
return null;
}
}

@ -46,7 +46,7 @@ public class BaseFragment extends Fragment implements LoadingView, OnBackPressLi
/* just for cache*/ /* just for cache*/
private View mCachedView; private View mCachedView;
private AnimatorHelper mAnimatorHelper; private FragmentAnimatorHelper mFragmentAnimatorHelper;
private final FragmentDelegates mFragmentDelegates = new FragmentDelegates(this); private final FragmentDelegates mFragmentDelegates = new FragmentDelegates(this);
@ -301,10 +301,10 @@ public class BaseFragment extends Fragment implements LoadingView, OnBackPressLi
@Nullable @Nullable
@Override @Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
if (mAnimatorHelper == null) { if (mFragmentAnimatorHelper == null) {
mAnimatorHelper = new AnimatorHelper(getContext(), FragmentConfig.defaultFragmentAnimator()); mFragmentAnimatorHelper = new FragmentAnimatorHelper(getContext(), FragmentConfig.defaultFragmentAnimator());
} }
return mAnimatorHelper.onCreateAnimation(this, transit, enter, nextAnim); return mFragmentAnimatorHelper.onCreateAnimation(transit, enter);
} }
} }

@ -1,44 +1,32 @@
package com.android.base.app.fragment; package com.android.base.app.fragment;
import android.os.Parcel; import android.view.animation.Animation;
import android.os.Parcelable; import android.view.animation.AnimationUtils;
import com.android.base.R; import com.android.base.R;
import com.android.base.utils.BaseUtils;
public class DefaultHorizontalAnimator extends FragmentAnimator implements Parcelable { public class DefaultHorizontalAnimator implements FragmentAnimator {
public DefaultHorizontalAnimator() { @Override
enter = R.anim.h_fragment_enter; public Animation makeOpenEnter() {
exit = R.anim.h_fragment_exit; return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_open_enter);
popEnter = R.anim.h_fragment_pop_enter;
popExit = R.anim.h_fragment_pop_exit;
} }
protected DefaultHorizontalAnimator(Parcel in) { @Override
super(in); public Animation makeOpenExit() {
return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_open_exit);
} }
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public Animation makeCloseEnter() {
super.writeToParcel(dest, flags); return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_close_enter);
} }
@Override @Override
public int describeContents() { public Animation makeCloseExit() {
return 0; return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_close_exit);
} }
public static final Creator<DefaultHorizontalAnimator> CREATOR = new Creator<DefaultHorizontalAnimator>() {
@Override
public DefaultHorizontalAnimator createFromParcel(Parcel in) {
return new DefaultHorizontalAnimator(in);
}
@Override
public DefaultHorizontalAnimator[] newArray(int size) {
return new DefaultHorizontalAnimator[size];
}
};
} }

@ -1,42 +1,32 @@
package com.android.base.app.fragment; package com.android.base.app.fragment;
import android.os.Parcel; import android.view.animation.Animation;
import android.os.Parcelable; import android.view.animation.AnimationUtils;
public class DefaultNoAnimator extends FragmentAnimator implements Parcelable { import com.android.base.R;
import com.android.base.utils.BaseUtils;
public DefaultNoAnimator() { public class DefaultNoAnimator implements FragmentAnimator {
enter = 0;
exit = 0;
popEnter = 0;
popExit = 0;
}
protected DefaultNoAnimator(Parcel in) { @Override
super(in); public Animation makeOpenEnter() {
return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim);
} }
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public Animation makeOpenExit() {
super.writeToParcel(dest, flags); return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim);
} }
@Override @Override
public int describeContents() { public Animation makeCloseEnter() {
return 0; return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim);
} }
public static final Creator<DefaultNoAnimator> CREATOR = new Creator<DefaultNoAnimator>() { @Override
@Override public Animation makeCloseExit() {
public DefaultNoAnimator createFromParcel(Parcel in) { return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim);
return new DefaultNoAnimator(in); }
}
@Override
public DefaultNoAnimator[] newArray(int size) {
return new DefaultNoAnimator[size];
}
};
} }

@ -0,0 +1,56 @@
package com.android.base.app.fragment;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.ScaleAnimation;
public class DefaultScaleAnimator implements FragmentAnimator {
private static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f);
private static final Interpolator DECELERATE_CUBIC = new DecelerateInterpolator(1.5f);
private static final int ANIM_DUR = 220;
@Override
public Animation makeOpenEnter() {
return makeOpenCloseAnimation(1.125f, 1.0f, 0, 1);
}
@Override
public Animation makeOpenExit() {
return makeOpenCloseAnimation(1.0f, .975f, 1, 0);
}
@Override
public Animation makeCloseEnter() {
return makeOpenCloseAnimation(.975f, 1.0f, 0, 1);
}
@Override
public Animation makeCloseExit() {
return makeOpenCloseAnimation(1.0f, 1.075f, 1, 0);
}
private static Animation makeOpenCloseAnimation(float startScale, float endScale, float startAlpha, float endAlpha) {
AnimationSet set = new AnimationSet(false);
ScaleAnimation scale = new ScaleAnimation(startScale, endScale, startScale, endScale,
Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f);
scale.setInterpolator(DECELERATE_QUINT);
scale.setDuration(ANIM_DUR);
set.addAnimation(scale);
AlphaAnimation alpha = new AlphaAnimation(startAlpha, endAlpha);
alpha.setInterpolator(DECELERATE_CUBIC);
alpha.setDuration(ANIM_DUR);
set.addAnimation(alpha);
return set;
}
}

@ -1,43 +1,31 @@
package com.android.base.app.fragment; package com.android.base.app.fragment;
import android.os.Parcel; import android.view.animation.Animation;
import android.os.Parcelable; import android.view.animation.AnimationUtils;
import com.android.base.R; import com.android.base.R;
import com.android.base.utils.BaseUtils;
public class DefaultVerticalAnimator extends FragmentAnimator implements Parcelable { public class DefaultVerticalAnimator implements FragmentAnimator {
public DefaultVerticalAnimator() { @Override
enter = R.anim.v_fragment_enter; public Animation makeOpenEnter() {
exit = R.anim.v_fragment_exit; return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_open_enter);
popEnter = R.anim.v_fragment_pop_enter;
popExit = R.anim.v_fragment_pop_exit;
} }
protected DefaultVerticalAnimator(Parcel in) { @Override
super(in); public Animation makeOpenExit() {
return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_open_exit);
} }
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public Animation makeCloseEnter() {
super.writeToParcel(dest, flags); return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_close_enter);
} }
@Override @Override
public int describeContents() { public Animation makeCloseExit() {
return 0; return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_close_exit);
} }
public static final Creator<DefaultVerticalAnimator> CREATOR = new Creator<DefaultVerticalAnimator>() {
@Override
public DefaultVerticalAnimator createFromParcel(Parcel in) {
return new DefaultVerticalAnimator(in);
}
@Override
public DefaultVerticalAnimator[] newArray(int size) {
return new DefaultVerticalAnimator[size];
}
};
} }

@ -1,105 +1,15 @@
package com.android.base.app.fragment; package com.android.base.app.fragment;
import android.os.Parcel; import android.view.animation.Animation;
import android.os.Parcelable;
import androidx.annotation.AnimRes; public interface FragmentAnimator {
public class FragmentAnimator implements Parcelable { Animation makeOpenEnter();
@AnimRes protected int enter; Animation makeOpenExit();
@AnimRes protected int exit;
@AnimRes protected int popEnter;
@AnimRes protected int popExit;
public FragmentAnimator() { Animation makeCloseEnter();
}
public FragmentAnimator(int enter, int exit) { Animation makeCloseExit();
this.enter = enter;
this.exit = exit;
}
public FragmentAnimator(int enter, int exit, int popEnter, int popExit) {
this.enter = enter;
this.exit = exit;
this.popEnter = popEnter;
this.popExit = popExit;
}
public FragmentAnimator copy() {
return new FragmentAnimator(getEnter(), getExit(), getPopEnter(), getPopExit());
}
protected FragmentAnimator(Parcel in) {
enter = in.readInt();
exit = in.readInt();
popEnter = in.readInt();
popExit = in.readInt();
}
public static final Creator<FragmentAnimator> CREATOR = new Creator<FragmentAnimator>() {
@Override
public FragmentAnimator createFromParcel(Parcel in) {
return new FragmentAnimator(in);
}
@Override
public FragmentAnimator[] newArray(int size) {
return new FragmentAnimator[size];
}
};
public int getEnter() {
return enter;
}
public FragmentAnimator setEnter(int enter) {
this.enter = enter;
return this;
}
public int getExit() {
return exit;
}
/**
* enter animation
*/
public FragmentAnimator setExit(int exit) {
this.exit = exit;
return this;
}
public int getPopEnter() {
return popEnter;
}
public FragmentAnimator setPopEnter(int popEnter) {
this.popEnter = popEnter;
return this;
}
public int getPopExit() {
return popExit;
}
public FragmentAnimator setPopExit(int popExit) {
this.popExit = popExit;
return this;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(enter);
dest.writeInt(exit);
dest.writeInt(popEnter);
dest.writeInt(popExit);
}
} }

@ -0,0 +1,103 @@
package com.android.base.app.fragment;
import android.content.Context;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import com.android.base.R;
import androidx.fragment.app.FragmentTransaction;
public final class FragmentAnimatorHelper {
private Context context;
private FragmentAnimator fragmentAnimator;
FragmentAnimatorHelper(Context context, FragmentAnimator fragmentAnimator) {
this.context = context;
this.fragmentAnimator = fragmentAnimator;
}
public void changeAnimation(FragmentAnimator fragmentAnimator) {
this.fragmentAnimator = fragmentAnimator;
}
public Animation getNoneAnim() {
return AnimationUtils.loadAnimation(context, R.anim.base_no_anim);
}
public Animation getNoneAnimFixed() {
return new Animation() {
};
}
private Animation initEnterAnim() {
if (fragmentAnimator == null) {
return AnimationUtils.loadAnimation(context, R.anim.base_no_anim);
} else {
Animation animation = fragmentAnimator.makeOpenEnter();
if (animation == null) {
return AnimationUtils.loadAnimation(context, R.anim.base_no_anim);
} else {
return animation;
}
}
}
private Animation initExitAnim() {
if (fragmentAnimator == null) {
return AnimationUtils.loadAnimation(context, R.anim.base_no_anim);
} else {
Animation animation = fragmentAnimator.makeOpenExit();
if (animation == null) {
return AnimationUtils.loadAnimation(context, R.anim.base_no_anim);
} else {
return animation;
}
}
}
private Animation initPopEnterAnim() {
if (fragmentAnimator == null) {
return AnimationUtils.loadAnimation(context, R.anim.base_no_anim);
} else {
Animation animation = fragmentAnimator.makeCloseEnter();
if (animation == null) {
return AnimationUtils.loadAnimation(context, R.anim.base_no_anim);
} else {
return animation;
}
}
}
private Animation initPopExitAnim() {
if (fragmentAnimator == null) {
return AnimationUtils.loadAnimation(context, R.anim.base_no_anim);
} else {
Animation animation = fragmentAnimator.makeCloseExit();
if (animation == null) {
return AnimationUtils.loadAnimation(context, R.anim.base_no_anim);
} else {
return animation;
}
}
}
Animation onCreateAnimation(int transit, boolean enter) {
if (transit == FragmentTransaction.TRANSIT_FRAGMENT_OPEN) {
if (enter) {
return initEnterAnim();
} else {
return initExitAnim();
}
} else if (transit == FragmentTransaction.TRANSIT_FRAGMENT_CLOSE) {
if (enter) {
return initPopEnterAnim();
} else {
return initPopExitAnim();
}
}
return null;
}
}

@ -277,13 +277,13 @@ class EnhanceFragmentTransaction constructor(
* 如果 [tag] ==null 则使用 fragment 对应 class 的全限定类名 * 如果 [tag] ==null 则使用 fragment 对应 class 的全限定类名
*/ */
fun addWithStack(containerId: Int = 0, fragment: Fragment, tag: String? = null, transition: Boolean = true): EnhanceFragmentTransaction { fun addWithStack(containerId: Int = 0, fragment: Fragment, tag: String? = null, transition: Boolean = true): EnhanceFragmentTransaction {
//hide top
hideTopFragment()
//set add to stack //set add to stack
val nonnullTag = (tag ?: fragment.javaClassName()) val nonnullTag = (tag ?: fragment.javaClassName())
addToBackStack(nonnullTag) addToBackStack(nonnullTag)
//add //add
fragmentTransaction.add(confirmLayoutId(containerId), fragment, nonnullTag) fragmentTransaction.add(confirmLayoutId(containerId), fragment, nonnullTag)
//hide top
hideTopFragment()
if (transition) { if (transition) {
//set a transition //set a transition
setOpeningTransition() setOpeningTransition()

@ -6,6 +6,7 @@ import android.content.Context
import android.content.res.TypedArray import android.content.res.TypedArray
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.util.TypedValue
import android.view.View import android.view.View
import androidx.annotation.* import androidx.annotation.*
@ -66,10 +67,24 @@ fun Context.drawableFromId(@DrawableRes id: Int): Drawable? {
* *
* 返回资源 id * 返回资源 id
*/ */
fun getResource(name: String, defType: String, defPackage: String): Int { fun getResourceId(name: String, defType: String, defPackage: String): Int {
return BaseUtils.getResources().getIdentifier(name, defType, defPackage) return BaseUtils.getResources().getIdentifier(name, defType, defPackage)
} }
/**
* - attr, like [android.R.attr.selectableItemBackground] or other attr id.
*/
fun getResourceId(context: Context, attr: Int): Int {
return try {
val outValue = TypedValue()
context.theme.resolveAttribute(attr, outValue, true)
outValue.resourceId
} catch (e: Exception) {
e.printStackTrace()
0
}
}
fun getText(@StringRes id: Int): CharSequence { fun getText(@StringRes id: Int): CharSequence {
return BaseUtils.getResources().getText(id) return BaseUtils.getResources().getText(id)
} }

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="100%p" />
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.9"
android:fillEnabled="true"
android:fillBefore="false"
android:fillAfter="true"
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="300" />
</set>

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="100%p" />
</set>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300">
<translate
android:fromXDelta="0%p"
android:toXDelta="-26%p" />
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.3"
android:fillEnabled="true"
android:fillBefore="false"
android:fillAfter="true"
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="300" />
</set>

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300">
<translate
android:fromXDelta="0%p"
android:toXDelta="-26%p" />
</set>

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300">
<alpha
android:fromAlpha="1.0"
android:toAlpha="1.0" />
</set>
Loading…
Cancel
Save