安卓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


 

Android共享元素场景切换动画的实现的更多相关文章

  1. Android的Activity屏幕切换动画(一)-左右滑动切换

    (国内知名Android开发论坛eoe开发者社区推荐:http://www.eoeandroid.com/) Android的Activity屏幕切换动画(一)-左右滑动切换 在Android开发过程 ...

  2. IOS自定义场景切换动画。

    IOS中我们可以通过Storyborad以及segue来实现我们自己的场景切换动画,新建项目使用Single View Application模板并取名为MyCustomSegue. 使用storyb ...

  3. cocos2d-x场景切换动画

    void StartScene::beginGame() {     CCLog("beginGame");          //CCTransitionScene *trans ...

  4. Android的Activity屏幕切换动画-左右滑动切换

    . --> 在Android开发过程中,经常会碰到Activity之间的切换效果的问题,下面介绍一下如何实现左右滑动的切换效果,首先了解一下Activity切换的实现,从Android2.0开始 ...

  5. Android为ViewPager增加切换动画——使用属性动画.

    ViewPager作为Android最常用的的组件之一,相信大家在项目中会频繁的使用到的,例如利用ViewPager制作引导页.轮播图,甚至做整个app的表现层的框架等等. Android3.0以下不 ...

  6. Android开发中activity切换动画的实现

    (1)我们在MainAcitvity中定义两个textview,用于点击触发切换Activity事件,下面是布局文件代码. <LinearLayout android:layout_width= ...

  7. Android至ViewPager添加切换动画——使用属性动画

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/44200623 ViewPager作为Android最经常使用的的组件之中的一个.相 ...

  8. Android为ViewPager添加切换动画——自己定义ViewPager

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/44224517 在上篇博客中,我写了一个使用属性动画为ViewPager加入切换动画 ...

  9. cocos2dx常见场景切换动画(转)

    本文转载自:http://www.cnblogs.com/linux-ios/archive/2013/04/09/3010779.html bool HelloWorld::init() { /// ...

随机推荐

  1. mui在tab选项卡中echarts图表不能动态随页面变化大小 只能固定大小

    在mui tab选项卡中一直都不能让echarts动态变化大小 只能固定大小来展示图表,网上说的window.onresize = mycharts.resize;方法根本就没有效果,后面在https ...

  2. Delphi FileListBox组件

  3. Django 数据库模块 单独使用

    pip install django pip install psycopg2 pip install mysqlclient Entity.py from django.db import mode ...

  4. 2019-2020-1 20199319《Linux内核原理与分析》第八周作业

    可执行程序工作原理 ELF目标文件格式 1.目标文件(ABI,应用程序二进制接口):编译器生成的文件. 2.目标文件的格式:out格式.COFF格式.PE(windows)格式.ELF(Linux)格 ...

  5. 使用sproxy.exe访问基于soap的webservice

    使用vc访问基于soap的webservice有多种方法,其中有一种是使用atlsoap,关于这个可以搜索sproxy.exe文章,不在这介绍(主要是我的写作能力太差).我写这个日记主要是项记录访问w ...

  6. 初学者如何从零学习人工智能?(AI)

    一.机器学习 有关机器学习领域的最佳介绍,请观看Coursera的Andrew Ng机器学习课程. 它解释了基本概念,并让你很好地理解最重要的算法. 有关ML算法的简要概述,查看这个TutsPlus课 ...

  7. dedecms织梦网站本地迁移到服务器后,后台更新栏目文档提示模板文件不存在,无法解析文档!的解决办法

    解决办法: 1.系统设置-系统基本参数-站点设置-网页主页链接,替换为空 2.系统设置-系统基本参数-核心设置-DedeCMS安装目录,替换为空

  8. mysql数据库表自增ID批量清零 AUTO_INCREMENT = 0

    mysql数据库表自增ID批量清零 AUTO_INCREMENT = 0 #将数据库表自增ID批量清零 SELECT CONCAT( 'ALTER TABLE ', TABLE_NAME, ' AUT ...

  9. 02bag模板

    cost->体积          weight->价值 hdu2844 可达/不可达 #include <stdio.h> #include <algorithm> ...

  10. Java 实现《编译原理》中间代码生成 -逆波兰式生成与计算 - 程序解析

    Java 实现<编译原理>中间代码生成 -逆波兰式生成与计算 - 程序解析 编译原理学习笔记 (一)逆波兰式是什么? 逆波兰式(Reverse Polish notation,RPN,或逆 ...