An interesting Android animation effect.
Let's take a look at the effect.
Analysis implementation principle:
The main knowledge point here is the use of animation. The principle page is very simple. layout two Fragment in an Activity does not require fragment, but the amount of code in the same xml will be relatively large; during initialization, move the second Fagment to the bottom to hide the interface when the application is started. Click Start and execute the corresponding animation. The X and y of the first Fragment are reduced at the same time, at the beginning, Let X rotate for 25 degrees and wait for a certain period of time to restore the angle of X rotation. This process is the animation process of Fragment moving backward, at the same time, there is a black background to set its transparency, from full to 0.5f; the second Fragment animation is very simple, simple to move down and up.
Here I will post some code. If you are interested, you can download the source code and study it.
Code pasting process:
Move the animation backward
MHoverView. setClickable (true);/* set the background transparency animation */ObjectAnimator animator = ObjectAnimator. ofFloat (mHoverView, "alpha", 0, 0.5f);/* place a small X animation */ObjectAnimator scaleXAnim = ObjectAnimator. ofFloat (mOriginalView, "scaleX", 1.0f ,. 8f);/* place a small Y animation */ObjectAnimator scaleYAnim = ObjectAnimator. ofFloat (mOriginalView, "scaleY", 1.0f ,. 8f); AnimatorSet animatorSet = new AnimatorSet (); animatorSet. playTogether (animator, scaleXAnim, scaleYAnim); animatorSet. setDuration (350); animatorSet. start ();/* Let X rotate an animation of 20 degrees */ObjectAnimator transX = ObjectAnimator. ofFloat (mOriginalView, "RotationX", 20366f); transX. setDuration (150); transX. start ();/* reset the X rotation angle for a certain period of time */ObjectAnimator resumeX = ObjectAnimator. ofFloat (mOriginalView, "RotationX", 0.0f); resumeX. setDuration (1, 200); resumeX. setstartdelay( 150); resumeX. start ();
The reverse animation is easy to understand.
mHoverView.setClickable(false); ObjectAnimator animator = ObjectAnimator.ofFloat(mHoverView, "alpha", 0.5f, 0); ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(mOriginalView, "scaleX", .8f, 1.0f); ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(mOriginalView, "scaleY", .8f, 1.0f); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(animator, scaleXAnim, scaleYAnim); animatorSet.setDuration(350); animatorSet.start(); ObjectAnimator transX = ObjectAnimator.ofFloat(mOriginalView,"RotationX",20.0f); transX.setDuration(150); transX.start(); ObjectAnimator resumeX = ObjectAnimator.ofFloat(mOriginalView,"RotationX",0.0f); resumeX.setDuration(200); resumeX.setStartDelay(150); resumeX.start();
The second Fragment moves up and down.
/** * Created by moon.zhong on 2015/4/12. */public class AnimationCompat implements Runnable { private Scroller mScroller; private View mAnimationView; private int mViewHeight; private final int DURATION = 350; public AnimationCompat(Context context, View view) { mScroller = new Scroller(context, new LinearInterpolator()); mAnimationView = view; mViewHeight = mAnimationView.getMeasuredHeight(); if (mViewHeight == 0) { mAnimationView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { mAnimationView.getViewTreeObserver().removeOnPreDrawListener(this); mViewHeight = mAnimationView.getMeasuredHeight(); return false; } }); } } public void startHideAnimation(boolean scrollUp) { int dy = (int) ViewCompat.getTranslationY(mAnimationView) + mViewHeight; if (!scrollUp) { dy = (int) ViewCompat.getTranslationY(mAnimationView) - mViewHeight; } int duration = (int) Math.abs(DURATION * ViewCompat.getTranslationY(mAnimationView) * 1.0f / mViewHeight); duration = duration == 0 ? DURATION : duration; mScroller.startScroll(0, (int) ViewCompat.getTranslationY(mAnimationView), 0, -dy, duration); ViewCompat.postOnAnimation(mAnimationView, this); } public void startShawAnimation() { int dy = (int) ViewCompat.getTranslationY(mAnimationView); int duration = (int) Math.abs(DURATION); mScroller.startScroll(0, dy, 0, -dy, duration); ViewCompat.postOnAnimation(mAnimationView, this); } public void abortAnimation() { mScroller.abortAnimation(); } @Override public void run() { if (mScroller.computeScrollOffset()) { ViewCompat.postOnAnimation(mAnimationView, this); ViewCompat.setTranslationY(mAnimationView, mScroller.getCurrY()); } }}
The xml page of MainActivity is pasted, because the layout of fragment is involved.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/black" android:id="@+id/id_anim_content"> <fragment class="com.test.gyzhong.funanimator.OriginalFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/id_original_fragment" /> <View android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/id_hover_view" android:background="@android:color/black" android:alpha="0"/> <RelativeLayout android:id="@+id/id_bottom_view" android:layout_width="match_parent" android:layout_height="400dp" android:background="@android:color/white" android:layout_alignParentBottom="true" android:layout_marginRight="50dp" android:layout_marginLeft="50dp"> <fragment class="com.test.gyzhong.funanimator.AnimFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/id_fragment_instruct" /> </RelativeLayout></RelativeLayout>
Here, if we put all the layout of the two Fragment into this layout file, the code will be very ugly and all will be concentrated in one file!
Summary:
If you do not summarize it, you must familiarize yourself with property animation!
Demo source code