zoukankan      html  css  js  c++  java
  • Android共享元素场景切换动画的实现

    安卓5.0系统引入了共享元素,能做出非常炫酷的场景切换效果,这让人非常兴奋同时非常蛋疼,因为低版本没法使用啊,所以今天就跟大家分享一下自己写的一个库,其实只有2个文件而已就可以兼容安卓5.0以下的版本。


    重要的工具类

    import android.animation.Animator;
    import android.animation.TimeInterpolator;
    import android.app.Activity;
    import android.content.Intent;
    import android.view.View;
    import android.view.ViewTreeObserver;
    
    import java.util.ArrayList;
    
    /**
     * Tool for transition between two activities
     * <br/>
     * Created by huzn on 2017/5/8.
     */
    public class EasyTransition {
    
        public static final String EASY_TRANSITION_OPTIONS = "easy_transition_options";
        public static final long DEFAULT_TRANSITION_ANIM_DURATION = 1000;
    
        /**
         * Start Activity with transition options
         *
         * @param intent  The intent to start
         * @param options Transition options, using {@link EasyTransitionOptions#makeTransitionOptions(Activity, View...)}
         *                to build your options
         */
        public static void startActivity(Intent intent, EasyTransitionOptions options) {
            options.update();
            intent.putParcelableArrayListExtra(EASY_TRANSITION_OPTIONS, options.getAttrs());
            Activity activity = options.getActivity();
            activity.startActivity(intent);
            activity.overridePendingTransition(0, 0);
        }
    
        /**
         * Start Activity for result, with transition options
         *
         * @param intent      The intent to start
         * @param requestCode If >= 0, this code will be returned in onActivityResult() when the activity exits,
         *                    see {@link Activity#startActivityForResult(Intent, int)}
         * @param options     Transition options, using {@link EasyTransitionOptions#makeTransitionOptions(Activity, View...)}
         *                    to build your options
         */
        public static void startActivityForResult(Intent intent, int requestCode, EasyTransitionOptions options) {
            options.update();
            intent.putParcelableArrayListExtra(EASY_TRANSITION_OPTIONS, options.getAttrs());
            Activity activity = options.getActivity();
            activity.startActivityForResult(intent, requestCode);
            activity.overridePendingTransition(0, 0);
        }
    
        /**
         * Enter the Activity, invoking this method to start enter transition animations
         *
         * @param activity     The Activity entering
         * @param duration     The duration of enter transition animation
         * @param interpolator The TimeInterpolator of enter transition animation
         * @param listener     Animator listener, normally you can do your initial after animation end
         */
        public static void enter(Activity activity, long duration, TimeInterpolator interpolator, Animator.AnimatorListener listener) {
            Intent intent = activity.getIntent();
            ArrayList<EasyTransitionOptions.ViewAttrs> attrs =
                    intent.getParcelableArrayListExtra(EASY_TRANSITION_OPTIONS);
            runEnterAnimation(activity, attrs, duration, interpolator, listener);
        }
    
        /**
         * The same as {@link EasyTransition#enter(Activity, long, TimeInterpolator, Animator.AnimatorListener)}
         * with no interpolator
         */
        public static void enter(Activity activity, long duration, Animator.AnimatorListener listener) {
            enter(activity, duration, null, listener);
        }
    
        /**
         * The same as {@link EasyTransition#enter(Activity, long, TimeInterpolator, Animator.AnimatorListener)}
         * with default duration
         */
        public static void enter(Activity activity, TimeInterpolator interpolator, Animator.AnimatorListener listener) {
            enter(activity, DEFAULT_TRANSITION_ANIM_DURATION, interpolator, listener);
        }
    
        /**
         * The same as {@link EasyTransition#enter(Activity, long, TimeInterpolator, Animator.AnimatorListener)}
         * with default duration and no interpolator
         */
        public static void enter(Activity activity, Animator.AnimatorListener listener) {
            enter(activity, DEFAULT_TRANSITION_ANIM_DURATION, null, listener);
        }
    
        /**
         * The same as {@link EasyTransition#enter(Activity, long, TimeInterpolator, Animator.AnimatorListener)}
         * with default duration, no interpolator and no listener
         */
        public static void enter(Activity activity) {
            enter(activity, DEFAULT_TRANSITION_ANIM_DURATION, null, null);
        }
    
        private static void runEnterAnimation(Activity activity,
                                              ArrayList<EasyTransitionOptions.ViewAttrs> attrs,
                                              final long duration,
                                              final TimeInterpolator interpolator,
                                              final Animator.AnimatorListener listener) {
            if (null == attrs || attrs.size() == 0)
                return;
    
            for (final EasyTransitionOptions.ViewAttrs attr : attrs) {
                final View view = activity.findViewById(attr.id);
    
                if (null == view)
                    continue;
    
                view.getViewTreeObserver()
                        .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                            @Override
                            public boolean onPreDraw() {
                                view.getViewTreeObserver().removeOnPreDrawListener(this);
    
                                int[] location = new int[2];
                                view.getLocationOnScreen(location);
                                view.setPivotX(0);
                                view.setPivotY(0);
                                view.setScaleX(attr.width / view.getWidth());
                                view.setScaleY(attr.height / view.getHeight());
                                view.setTranslationX(attr.startX - location[0]); // xDelta
                                view.setTranslationY(attr.startY - location[1]); // yDelta
    
                                view.animate()
                                        .scaleX(1)
                                        .scaleY(1)
                                        .translationX(0)
                                        .translationY(0)
                                        .setDuration(duration)
                                        .setInterpolator(interpolator)
                                        .setListener(listener);
                                return true;
                            }
                        });
            }
        }
    
        /**
         * Exit the Activity, invoke this method to start exit transition animation,
         * the shared views must have same ids, or it will throws NullPointerException
         *
         * @param activity     The Activity Exiting
         * @param interpolator The TimeInterpolator of exit transition animation
         * @param duration     The duration of exit transition animation
         * @throws NullPointerException throws if shared views not found in The Activity Exiting
         */
        public static void exit(Activity activity, long duration, TimeInterpolator interpolator) {
            Intent intent = activity.getIntent();
            ArrayList<EasyTransitionOptions.ViewAttrs> attrs = intent.getParcelableArrayListExtra(EASY_TRANSITION_OPTIONS);
            runExitAnimation(activity, attrs, duration, interpolator);
        }
    
        /**
         * The same as {@link EasyTransition#exit(Activity, long, TimeInterpolator)}
         * with default duration
         */
        public static void exit(Activity activity, TimeInterpolator interpolator) {
            exit(activity, DEFAULT_TRANSITION_ANIM_DURATION, interpolator);
        }
    
        /**
         * The same as {@link EasyTransition#exit(Activity, long, TimeInterpolator)}
         * with no interpolator
         */
        public static void exit(Activity activity, long duration) {
            exit(activity, duration, null);
        }
    
        /**
         * The same as {@link EasyTransition#exit(Activity, long, TimeInterpolator)}
         * with default duration and no interpolator
         */
        public static void exit(Activity activity) {
            exit(activity, DEFAULT_TRANSITION_ANIM_DURATION, null);
        }
    
        private static void runExitAnimation(final Activity activity,
                                             ArrayList<EasyTransitionOptions.ViewAttrs> attrs,
                                             long duration,
                                             TimeInterpolator interpolator) {
            if (null == attrs || attrs.size() == 0)
                return;
    
            for (final EasyTransitionOptions.ViewAttrs attr : attrs) {
                View view = activity.findViewById(attr.id);
                int[] location = new int[2];
                view.getLocationOnScreen(location);
                view.setPivotX(0);
                view.setPivotY(0);
    
                view.animate()
                        .scaleX(attr.width / view.getWidth())
                        .scaleY(attr.height / view.getHeight())
                        .translationX(attr.startX - location[0])
                        .translationY(attr.startY - location[1])
                        .setInterpolator(interpolator)
                        .setDuration(duration);
            }
    
            activity.findViewById(attrs.get(0).id).postDelayed(new Runnable() {
                @Override
                public void run() {
                    activity.finish();
                    activity.overridePendingTransition(0, 0);
                }
            }, duration);
        }
    }
    
    import android.app.Activity;
    import android.os.Parcel;
    import android.os.Parcelable;
    import android.view.View;
    
    import java.util.ArrayList;
    
    /**
     * Transition options, using {@link EasyTransitionOptions#makeTransitionOptions(Activity, View...)}
     * to build your options
     * <br/>
     * Created by huzn on 2017/5/8.
     */
    public class EasyTransitionOptions {
    
        private Activity activity;
        private View[] views;
        private ArrayList<ViewAttrs> attrs;
    
        public EasyTransitionOptions(Activity activity, View[] views) {
            this.activity = activity;
            this.views = views;
        }
    
        /**
         * Make options for transition
         *
         * @param activity The activity who contains shared views
         * @param views    Shared views, which must contains same id between two activities
         * @return A new transition options that will be used to build our transition animations
         */
        public static EasyTransitionOptions makeTransitionOptions(Activity activity, View... views) {
            return new EasyTransitionOptions(activity, views);
        }
    
        public void update() {
            if (null == views)
                return;
    
            attrs = new ArrayList<>();
            for (View v : views) {
                int[] location = new int[2];
                v.getLocationOnScreen(location);
                attrs.add(new ViewAttrs(
                        v.getId(),
                        location[0],
                        location[1],
                        v.getWidth(),
                        v.getHeight()
                ));
            }
        }
    
        public Activity getActivity() {
            return activity;
        }
    
        public ArrayList<ViewAttrs> getAttrs() {
            return attrs;
        }
    
        public static class ViewAttrs implements Parcelable {
            public int id;
            public float startX;
            public float startY;
            public float width;
            public float height;
    
            public ViewAttrs(int id, float startX, float startY, float width, float height) {
                this.id = id;
                this.startX = startX;
                this.startY = startY;
                this.width = width;
                this.height = height;
            }
    
            // Parcelable
            @Override
            public int describeContents() {
                return 0;
            }
    
            @Override
            public void writeToParcel(Parcel dest, int flags) {
                dest.writeInt(this.id);
                dest.writeFloat(this.startX);
                dest.writeFloat(this.startY);
                dest.writeFloat(this.width);
                dest.writeFloat(this.height);
            }
    
            protected ViewAttrs(Parcel in) {
                this.id = in.readInt();
                this.startX = in.readFloat();
                this.startY = in.readFloat();
                this.width = in.readFloat();
                this.height = in.readFloat();
            }
    
            public static final Parcelable.Creator<ViewAttrs> CREATOR = new Parcelable.Creator<ViewAttrs>() {
                @Override
                public ViewAttrs createFromParcel(Parcel source) {
                    return new ViewAttrs(source);
                }
    
                @Override
                public ViewAttrs[] newArray(int size) {
                    return new ViewAttrs[size];
                }
            };
        }
    }
    

     场景使用:

    import android.content.Intent;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.BaseAdapter;
    import android.widget.ListView;
    import android.widget.TextView;
    
    import java.util.ArrayList;
    
    public class MainActivity extends AppCompatActivity {
    
        private ArrayList<String> list;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            list = new ArrayList<>();
            for (int i = 0; i < 20; i++) {
                list.add("name" + i);
            }
            ListView listView = (ListView) findViewById(R.id.lv);
            listView.setAdapter(new MyAdapter());
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    // ready for intent
                    Intent intent = new Intent(MainActivity.this, DetailActivity.class);
                    intent.putExtra("name", list.get(position));
    
                    // ready for transition options
                    EasyTransitionOptions options =
                            EasyTransitionOptions.makeTransitionOptions(
                                    MainActivity.this,
                                    view.findViewById(R.id.iv_icon),
                                    view.findViewById(R.id.tv_name),
                                    findViewById(R.id.v_top_card));
    
                    // start transition
                    EasyTransition.startActivity(intent, options);
                }
            });
        }
    
    
        private class MyAdapter extends BaseAdapter {
    
            @Override
            public int getCount() {
                int count = 0;
                if (null != list)
                    count = list.size();
                return count;
            }
    
            @Override
            public Object getItem(int position) {
                return list.get(position);
            }
    
            @Override
            public long getItemId(int position) {
                return position;
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View view = null;
                if (null != convertView) {
                    view = convertView;
                } else {
                    view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_main_list, null, false);
                }
                TextView tvName = (TextView) view.findViewById(R.id.tv_name);
                tvName.setText(list.get(position));
                return view;
            }
        }
    }
    
    import android.animation.Animator;
    import android.animation.AnimatorListenerAdapter;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.v7.app.AppCompatActivity;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.animation.DecelerateInterpolator;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.ScrollView;
    import android.widget.TextView;
    
    public class DetailActivity extends AppCompatActivity {
    
        private LinearLayout layoutAbout;
        private ImageView ivAdd;
        private boolean finishEnter;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_detail);
    
            // pre init some views and data
            initViews();
    
            // if re-initialized, do not play any anim
            long transitionDuration = 800;
            if (null != savedInstanceState)
                transitionDuration = 0;
    
            // transition enter
            finishEnter = false;
            EasyTransition.enter(
                    this,
                    transitionDuration,
                    new DecelerateInterpolator(),
                    new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            // init other views after transition anim
                            finishEnter = true;
                            initOtherViews();
                        }
                    });
        }
    
        private void initViews() {
            TextView tvName = (TextView) findViewById(R.id.tv_name);
            tvName.setText(getIntent().getStringExtra("name"));
        }
    
        private void initOtherViews() {
            layoutAbout = (LinearLayout) findViewById(R.id.layout_about);
            layoutAbout.setVisibility(View.VISIBLE);
            layoutAbout.setAlpha(0);
            layoutAbout.setTranslationY(-30);
            layoutAbout.animate()
                    .setDuration(300)
                    .alpha(1)
                    .translationY(0);
    
            ivAdd = (ImageView) findViewById(R.id.iv_add);
            ivAdd.setVisibility(View.VISIBLE);
            ivAdd.setScaleX(0);
            ivAdd.setScaleY(0);
            ivAdd.animate()
                    .setDuration(200)
                    .scaleX(1)
                    .scaleY(1);
        }
    
        @Override
        public void onBackPressed() {
            if (finishEnter) {
                finishEnter = false;
                startBackAnim();
            }
        }
    
        private void startBackAnim() {
            // forbidden scrolling
            ScrollView sv = (ScrollView) findViewById(R.id.sv);
            sv.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    return true;
                }
            });
    
            // start our anim
            ivAdd.animate()
                    .setDuration(200)
                    .scaleX(0)
                    .scaleY(0);
    
            layoutAbout.animate()
                    .setDuration(300)
                    .alpha(0)
                    .translationY(-30)
                    .setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            // transition exit after our anim
                            EasyTransition.exit(DetailActivity.this, 800, new DecelerateInterpolator());
                        }
                    });
        }
    }
    

     activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.hzn.easytransition.MainActivity"
        >
    
        <TextView
            android:id="@+id/title_bar"
            android:layout_width="match_parent"
            android:layout_height="55dp"
            android:background="@color/colorPrimary"
            android:gravity="center_vertical"
            android:paddingLeft="16sp"
            android:text="TITLE"
            android:textColor="#ffffff"
            android:textSize="25sp"
            />
    
        <View
            android:id="@+id/v_top_card"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_below="@id/title_bar"
            android:background="@color/colorPrimary"
            />
    
        <ListView
            android:id="@+id/lv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/title_bar"
            />
    </RelativeLayout>
    

    activity_detail.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.hzn.easytransition.MainActivity"
        >
    
        <TextView
            android:id="@+id/title_bar"
            android:layout_width="match_parent"
            android:layout_height="55dp"
            android:background="@color/colorPrimary"
            android:gravity="center_vertical"
            android:paddingLeft="16sp"
            android:text="TITLE"
            android:textColor="#ffffff"
            android:textSize="25sp"
            />
    
        <View
            android:id="@+id/v_top_card"
            android:layout_width="match_parent"
            android:layout_height="120dp"
            android:layout_below="@+id/title_bar"
            android:background="@color/colorPrimary"
            />
    
        <ImageView
            android:id="@+id/iv_icon"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="100dp"
            android:src="@mipmap/avatar_male"
            />
    
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/iv_icon"
            android:layout_centerHorizontal="true"
            android:layout_marginLeft="10dp"
            android:textColor="#5b5b5b"
            android:textSize="50sp"
            />
    
        <ScrollView
            android:id="@+id/sv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/tv_name"
            android:overScrollMode="never"
            android:scrollbars="none"
            >
    
            <LinearLayout
                android:id="@+id/layout_about"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="16dp"
                android:layout_marginRight="16dp"
                android:orientation="vertical"
                android:paddingBottom="40dp"
                android:paddingTop="20dp"
                android:visibility="invisible"
                >
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:drawableLeft="@mipmap/icon_phone"
                    android:drawablePadding="10dp"
                    android:gravity="center_vertical"
                    android:text="151-2121-2121"
                    android:textColor="#446880"
                    android:textSize="16sp"
                    />
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="16dp"
                    android:drawableLeft="@mipmap/icon_email"
                    android:drawablePadding="10dp"
                    android:gravity="center_vertical"
                    android:text="243666666@gmail.com"
                    android:textColor="#446880"
                    android:textSize="16sp"
                    />
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="16dp"
                    android:drawableLeft="@mipmap/icon_location"
                    android:drawablePadding="10dp"
                    android:gravity="center_vertical"
                    android:text="China, Guangdong, Shenzhen"
                    android:textColor="#446880"
                    android:textSize="16sp"
                    />
            </LinearLayout>
        </ScrollView>
    
        <ImageView
            android:id="@+id/iv_add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:padding="16dp"
            android:src="@mipmap/icon_add"
            android:visibility="gone"
            />
    </RelativeLayout>
    

    item_main_list.xml

    <?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:orientation="vertical"
                    android:padding="16dp"
        >
    
        <ImageView
            android:id="@+id/iv_icon"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@mipmap/avatar_male"
            />
    
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_toRightOf="@+id/iv_icon"
            android:text="name"
            android:textColor="#5b5b5b"
            android:textSize="20sp"
            />
    
    </RelativeLayout>
    

     效果图:


    学习来源:http://blog.csdn.net/u012199331/article/details/72137112


     
  • 相关阅读:
    Cookie、Session和自定义分页
    ORM版学员管理系统 2
    ORM版学员管理系统 3
    ORM版学员管理系统
    Django之ORM
    Django模板语言相关内容
    Django之视图
    MySQL表单查询
    模块和包—Day28
    MySQL windows下cmd安装操作
  • 原文地址:https://www.cnblogs.com/loaderman/p/6957030.html
Copyright © 2011-2022 走看看