一、MainActivity
1、布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/MaterialAnimations.TextAppearance.Title"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@color/material_animations_primary"
android:elevation="@dimen/4dp"> //设置该组建"浮起来"的高度,使该组件有着3D效果
<TextView
android:id="@+id/title"
style="@style/MaterialAnimations.TextAppearance.Title.Inverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
android:text="@string/app_name" />
</android.support.v7.widget.Toolbar>
<android.support.v7.widget.RecyclerView
android:id="@+id/sample_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
</LinearLayout>
(1)RecyclerView
1)根据官方介绍,该控件用于有限的窗口中展示大量数据集。
可以通过LayoutManager控制其显示方式
可以通过ItemDecoration控制Item的间隔
可以通过ItemAnimation控制Item的增删动画
2)主要方法
setLayoutManager()设置布局管理器
setAdapter()设置adapter
setItemAnimator()设置动画
addItemDecoration()添加分割线
3)Adapter
在onCreateViewHolder中new MyViewHolder().inflate并且return holder
在onBindViewHolder中执行操作
自定义一个内部内MyViewHolder()extend ViewHolder
4)LayoutManager
LinearLayoutManager线性管理器,支持横向、纵向
GridLayoutManager网络布局管理器
StaggeredGridLayoutManager瀑布流式布局管理器(只需要在onBindViewHolder中为每个Item设置随机的高度)
5)ItemAnimator
setItemAnimation()
注意:这里更新数据集使用notifyItemInserted(positon)和notifyItemRemoved(postion)
6)Click和onLongClick
可以在adapter中自己提供回调
2、
二、Sample类
public class Sample implements Serializable {
final int color;
private final String name;
public Sample(@ColorRes int color, String name) {
this.color = color;
this.name = name;
}
@BindingAdapter("bind:colorTint")
public static void setColorTint(ImageView view, @ColorRes int color) {
DrawableCompat.setTint(view.getDrawable(), color); //改变图片的颜色 减少需要的图片
//view.setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
public String getName() {
return name;
}
public int getColor() {
return color;
}
}
3、TransitionHelper
class TransitionHelper {
/**
* Create the transition participants required during a activity transition while
* avoiding glitches with the system UI.
*
* @param activity The activity used as start for the transition.
* @param includeStatusBar If false, the status bar will not be added as the transition
* participant.
* @return All transition participants.
*/
public static Pair<View, String>[] createSafeTransitionParticipants(@NonNull Activity activity,
boolean includeStatusBar, @Nullable Pair... otherParticipants) {
// Avoid system UI glitches as described here:
// https://plus.google.com/+AlexLockwood/posts/RPtwZ5nNebb
View decor = activity.getWindow().getDecorView();
View statusBar = null;
if (includeStatusBar) {
statusBar = decor.findViewById(android.R.id.statusBarBackground); //获取状态栏
}
View navBar = decor.findViewById(android.R.id.navigationBarBackground); //获取底部工具栏(即虚拟键)
// Create pair of transition participants.
List<Pair> participants = new ArrayList<>(3);
//把状态栏和底部工具栏添加到列表中 如果非空的话
addNonNullViewToTransitionParticipants(statusBar, participants);
addNonNullViewToTransitionParticipants(navBar, participants);
// 添加到过渡中如果他至少有一个非空的话
if (otherParticipants != null && !(otherParticipants.length == 1
&& otherParticipants[0] == null)) {
participants.addAll(Arrays.asList(otherParticipants)); //添加
}
return participants.toArray(new Pair[participants.size()]); //返回包含所有元素的数组 类型是其中的参数 即返回Pair类型的数组
}
/**
* 非空的话就把view添加进入
* @param view
* @param participants
*/
private static void addNonNullViewToTransitionParticipants(View view, List<Pair> participants) {
if (view == null) {
return;
}
participants.add(new Pair<>(view, view.getTransitionName()));
}
}
public class SamplesRecyclerAdapter extends RecyclerView.Adapter<SamplesRecyclerAdapter.SamplesViewHolder> {
private final Activity activity;
private final List<Sample> samples;
//构造方法
public SamplesRecyclerAdapter(Activity activity, List<Sample> samples) {
this.activity = activity;
this.samples = samples; //传入需要的list
}
@Override
public SamplesViewHolder onCreateViewHolder(ViewGroup parent, int position) {
//RowSampleBinding为自动生成的继承自ViewDataBinding类 生成Binding
RowSampleBinding binding = RowSampleBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new SamplesViewHolder(binding.getRoot()); //构造方法
}
@Override
public void onBindViewHolder(final SamplesViewHolder viewHolder, final int position) {
final Sample sample = samples.get(viewHolder.getAdapterPosition()); //获取当前的sample
viewHolder.binding.setSample(sample); //设置给视图
viewHolder.binding.sampleLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {//设置点击事件
switch (viewHolder.getAdapterPosition()) { //跳转Activity 并携带对象
case 0:
transitionToActivity(TransitionActivity1.class, sample);
break;
case 1:
transitionToActivity(SharedElementActivity.class, viewHolder, sample);
break;
case 2:
transitionToActivity(AnimationsActivity1.class, sample);
break;
case 3:
transitionToActivity(RevealActivity.class, viewHolder, sample, R.string.transition_reveal1);
break;
}
}
});
}
private void transitionToActivity(Class target, Sample sample) {
final Pair<View, String>[] pairs = TransitionHelper.createSafeTransitionParticipants(activity, true); //传入需要变化的视图数组 true为包括状态栏
startActivity(target, pairs, sample); //跳转Activvity
}
private void transitionToActivity(Class target, SamplesViewHolder viewHolder, Sample sample, int transitionName) {
final Pair<View, String>[] pairs = TransitionHelper.createSafeTransitionParticipants(activity, false,
new Pair<>(viewHolder.binding.sampleIcon, activity.getString(transitionName)));//需要变化的视图为不包括状态栏,包括图
startActivity(target, pairs, sample);
}
private void transitionToActivity(Class target, SamplesViewHolder viewHolder, Sample sample) {
//需要变化的视图不包括状态栏 但包括蓝字和蓝图
final Pair<View, String>[] pairs = TransitionHelper.createSafeTransitionParticipants(activity, false,
new Pair<>(viewHolder.binding.sampleIcon, activity.getString(R.string.square_blue_name)),
new Pair<>(viewHolder.binding.sampleName, activity.getString(R.string.sample_blue_title)));
startActivity(target, pairs, sample);
}
private void startActivity(Class target, Pair<View, String>[] pairs, Sample sample) {
Intent i = new Intent(activity, target);
ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, pairs); //设置Activity跳转动画
i.putExtra("sample", sample);
activity.startActivity(i, transitionActivityOptions.toBundle());
}
@Override
public int getItemCount() {
return samples.size();
}
public class SamplesViewHolder extends RecyclerView.ViewHolder {
final RowSampleBinding binding; //获取binding对象
public SamplesViewHolder(View rootView) {
super(rootView);
binding = DataBindingUtil.bind(rootView); //绑定view
}
}
}
五、BaseActivity
public class BaseDetailActivity extends AppCompatActivity {
static final String EXTRA_SAMPLE = "sample";
static final String EXTRA_TYPE = "type";
static final int TYPE_PROGRAMMATICALLY = 0;
static final int TYPE_XML = 1;
void setupToolbar() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);//给右上角添加一个返回图标
getSupportActionBar().setDisplayShowTitleEnabled(false); //隐藏标题
}
@Override
public boolean onSupportNavigateUp() { //点击返回图标时调用
onBackPressed(); //调用返回键
return true; //如果这个Activity结束的话 返回true 否则返回false
}
//该注解的意思是对被批注的代码元素内部的某些警告保持静默
@SuppressWarnings("unchecked") void transitionTo(Intent i) {
final Pair<View, String>[] pairs = TransitionHelper.createSafeTransitionParticipants(this, true); //包括状态栏
ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this, pairs); //设置动画
startActivity(i, transitionActivityOptions.toBundle());
}
}
六、TransitionActivity
public class TransitionActivity1 extends BaseDetailActivity {
private Sample sample;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindData();
setupWindowAnimations();
setupLayout();
setupToolbar();
}
private void bindData() {
ActivityTransition1Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_transition1); //绑定数据与视图
sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE); //获取Intent传来的数据
binding.setTransition1Sample(sample);//把sample设置给视图
}
private void setupWindowAnimations() {
Visibility enterTransition = buildEnterTransition();
getWindow().setEnterTransition(enterTransition); //设置进入动画
}
private void setupLayout() {
findViewById(R.id.sample1_button1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(TransitionActivity1.this, TransitionActivity2.class);
i.putExtra(EXTRA_SAMPLE, sample);
i.putExtra(EXTRA_TYPE, TYPE_PROGRAMMATICALLY);
transitionTo(i);
}
});
findViewById(R.id.sample1_button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(TransitionActivity1.this, TransitionActivity2.class);
i.putExtra(EXTRA_SAMPLE, sample);
i.putExtra(EXTRA_TYPE, TYPE_XML);
transitionTo(i);
}
});
findViewById(R.id.sample1_button3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(TransitionActivity1.this, TransitionActivity3.class);
i.putExtra(EXTRA_SAMPLE, sample);
i.putExtra(EXTRA_TYPE, TYPE_PROGRAMMATICALLY);
transitionTo(i);
}
});
findViewById(R.id.sample1_button4).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(TransitionActivity1.this, TransitionActivity3.class);
i.putExtra(EXTRA_SAMPLE, sample);
i.putExtra(EXTRA_TYPE, TYPE_XML);
transitionTo(i);
}
});
findViewById(R.id.sample1_button5).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Visibility returnTransition = buildReturnTransition();
getWindow().setReturnTransition(returnTransition); //设置返回动画
finishAfterTransition();//在动画结束后finishActivity
}
});
findViewById(R.id.sample1_button6).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/**
* 如果没有定义return动画,那么android会倒放enter动画
*
*/
finishAfterTransition();
}
});
}
private Visibility buildEnterTransition() {
Fade enterTransition = new Fade(); //淡入淡出动画
enterTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long)); //动画事件
// 这个视图不会受到这个动画的影响 后面的boolean值决定是否要把这个视图添加到当前排除的列表或者从当前排除列表中删除
enterTransition.excludeTarget(R.id.square_red, true);
return enterTransition;
}
private Visibility buildReturnTransition() {
Visibility enterTransition = new Slide();
enterTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
return enterTransition;
}
}
七、TransitionActivity2
public class TransitionActivity2 extends BaseDetailActivity {
private int type;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindData();
setupWindowAnimations();
setupLayout();
setupToolbar();
}
private void bindData() {
ActivityTransition2Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_transition2);//绑定数据视图
Sample sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);//获取数据
type = getIntent().getExtras().getInt(EXTRA_TYPE);//获取类型
binding.setTransition2Sample(sample);//设置type
}
private void setupWindowAnimations() {
Transition transition;
if (type == TYPE_PROGRAMMATICALLY) { //如果type为代码的话
transition = buildEnterTransition();//获得动画
} else { //否则用xml文件设置动画
transition = TransitionInflater.from(this).inflateTransition(R.transition.explode);
}
getWindow().setEnterTransition(transition);//设置动画
}
private void setupLayout() {
findViewById(R.id.exit_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finishAfterTransition();//动画结束后finishActivity
}
});
}
private Transition buildEnterTransition() {
Explode enterTransition = new Explode();//向中心移入
enterTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
return enterTransition;
}
}
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<explode
android:duration="@integer/anim_duration_long" //持续时间
android:interpolator="@android:interpolator/bounce" /> //插补器 模拟球弹跳的样子
</transitionSet>
public class TransitionActivity3 extends BaseDetailActivity {
private int type;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindData();
setupWindowAnimations();
setupLayout();
setupToolbar();
}
private void bindData() {
ActivityTransition3Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_transition3);//绑定视图数据
Sample sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);//获取数据
type = getIntent().getExtras().getInt(EXTRA_TYPE);//获取类型
binding.setTransition3Sample(sample);//设置数据
}
private void setupWindowAnimations() {
Transition transition;
if (type == TYPE_PROGRAMMATICALLY) { //类型是代码的话
transition = buildEnterTransition(); //创建动画
} else {
transition = TransitionInflater.from(this).inflateTransition(R.transition.slide_from_bottom);//创建动画
}
getWindow().setEnterTransition(transition);//设置动画
}
private void setupLayout() {
findViewById(R.id.exit_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finishAfterTransition();//完成动画后finishActivity
}
});
}
private Visibility buildEnterTransition() {
Slide enterTransition = new Slide();
enterTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
enterTransition.setSlideEdge(Gravity.RIGHT);
return enterTransition;
}
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<slide
android:duration="@integer/anim_duration_long" //持续时间
android:slideEdge="bottom" /> //方向
</transitionSet>
十一、SharedElementActivity
public class SharedElementActivity extends BaseDetailActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Sample sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
bindData(sample);//绑定数据
setupWindowAnimations();
setupLayout(sample);
setupToolbar(); //设置toolbar
}
private void bindData(Sample sample) {
ActivitySharedelementBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_sharedelement);//绑定数据与视图
binding.setSharedSample(sample);//设置数据
}
private void setupWindowAnimations() {
// We are not interested in defining a new Enter Transition. Instead we change default transition duration
getWindow().getEnterTransition().setDuration(getResources().getInteger(R.integer.anim_duration_long)); //设置默认的进入动画
}
private void setupLayout(Sample sample) {
// Transition for fragment1
Slide slideTransition = new Slide(Gravity.LEFT);
slideTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
// Create fragment and define some of it transitions
SharedElementFragment1 sharedElementFragment1 = SharedElementFragment1.newInstance(sample);//获得fragment实例
sharedElementFragment1.setReenterTransition(slideTransition);//设置重返动画
sharedElementFragment1.setExitTransition(slideTransition); //设置退出动画
/**
* changeBounds 改变目标视图的布局边界
* changeClipBounds 裁剪目标边界视图
* changeTransform 改变目标视图的缩放比例和旋转角度
* changeImageTransform 改变目标图片的大小和缩放比例
*/
sharedElementFragment1.setSharedElementEnterTransition(new ChangeBounds());//设置共享元素进入动画
getSupportFragmentManager().beginTransaction()
.replace(R.id.sample2_content, sharedElementFragment1)
.commit();
}
}
public class SharedElementFragment1 extends Fragment {
private static final String EXTRA_SAMPLE = "sample";
/**
* 获取实例
*
* @param sample
* @return
*/
public static SharedElementFragment1 newInstance(Sample sample) {
Bundle args = new Bundle();
args.putSerializable(EXTRA_SAMPLE, sample);
SharedElementFragment1 fragment = new SharedElementFragment1();
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_sharedelement_fragment1, container, false);//设置视图
final Sample sample = (Sample) getArguments().getSerializable(EXTRA_SAMPLE);//获取数据
final ImageView squareBlue = (ImageView) view.findViewById(R.id.square_blue);
DrawableCompat.setTint(squareBlue.getDrawable(), sample.color);//设置颜色
view.findViewById(R.id.sample2_button1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addNextFragment(sample, squareBlue, false);
}
});
view.findViewById(R.id.sample2_button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addNextFragment(sample, squareBlue, true);
}
});
return view;
}
private void addNextFragment(Sample sample, ImageView squareBlue, boolean overlap) {
SharedElementFragment2 sharedElementFragment2 = SharedElementFragment2.newInstance(sample);//获取实例
//滑动动画
Slide slideTransition = new Slide(Gravity.RIGHT);
slideTransition.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
//changeBounds 改变目标视图的布局边界
ChangeBounds changeBoundsTransition = new ChangeBounds();
changeBoundsTransition.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
sharedElementFragment2.setEnterTransition(slideTransition);
//是否允许动画重叠
sharedElementFragment2.setAllowEnterTransitionOverlap(overlap);
sharedElementFragment2.setAllowReturnTransitionOverlap(overlap);
sharedElementFragment2.setSharedElementEnterTransition(changeBoundsTransition);
getFragmentManager().beginTransaction()
.replace(R.id.sample2_content, sharedElementFragment2)
.addToBackStack(null)
.addSharedElement(squareBlue, getString(R.string.square_blue_name))//设置要转换的view和transitionname
.commit();
}
}
public class SharedElementFragment2 extends Fragment {
private static final String EXTRA_SAMPLE = "sample";
//获取实例
public static SharedElementFragment2 newInstance(Sample sample) {
Bundle args = new Bundle();
args.putSerializable(EXTRA_SAMPLE, sample);
SharedElementFragment2 fragment = new SharedElementFragment2();
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_sharedelement_fragment2, container, false);
Sample sample = (Sample) getArguments().getSerializable(EXTRA_SAMPLE);
ImageView squareBlue = (ImageView) view.findViewById(R.id.square_blue);
DrawableCompat.setTint(squareBlue.getDrawable(), sample.color);
return view;
}
}
十四、AnimationsActivity1
public class AnimationsActivity1 extends BaseDetailActivity {
private ImageView square;
private ViewGroup viewRoot;
private boolean sizeChanged;
private int savedWidth;
private boolean positionChanged;
private Sample sample;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindData();
setupWindowAnimations();
setupLayout();
setupToolbar();
}
private void setupWindowAnimations() {
getWindow().setReenterTransition(new Fade());
}//设置淡入淡出
private void bindData() {
ActivityAnimations1Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_animations1);//绑定数据与视图
sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);//获取数据
binding.setAnimationsSample(sample);//获取视图
}
private void setupLayout() {
square = (ImageView) findViewById(R.id.square_green);
viewRoot = (ViewGroup) findViewById(R.id.sample3_root);
findViewById(R.id.sample3_button1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeLayout();
}
});
findViewById(R.id.sample3_button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changePosition();
}
});
findViewById(R.id.sample3_button3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(AnimationsActivity1.this, AnimationsActivity2.class);
i.putExtra(EXTRA_SAMPLE, sample);
transitionTo(i);
}
});
}
private void changeLayout() {
TransitionManager.beginDelayedTransition(viewRoot); //在该布局中的view发生变化时 会默认给一个动画效果
ViewGroup.LayoutParams params = square.getLayoutParams(); //获取布局参数
if (sizeChanged) { //第一次是false
params.width = savedWidth;
} else {
savedWidth = params.width; //保存一开始的大小
params.width = 200; //重新定义宽度
}
sizeChanged = !sizeChanged; //状态变为true
square.setLayoutParams(params); //设置参数
}
private void changePosition() {
TransitionManager.beginDelayedTransition(viewRoot);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) square.getLayoutParams();
if (positionChanged) {
lp.gravity = Gravity.CENTER;
} else {
lp.gravity = Gravity.LEFT;
}
positionChanged = !positionChanged;
square.setLayoutParams(lp);
}
}
十五、AnimationsActivity2
public class AnimationsActivity2 extends BaseDetailActivity {
private static final int DELAY = 100;
private Scene scene0;
private Scene scene1;
private Scene scene2;
private Scene scene3;
private Scene scene4;
private final List<View> viewsToAnimate = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindData();
setupLayout();
setupToolbar();
setupWindowAnimations();
}
private void bindData() {
//绑定数据视图 设置数据
ActivityAnimations2Binding binding = DataBindingUtil.setContentView(
this, R.layout.activity_animations2);
Sample sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
binding.setAnimationsSample(sample);
}
private void setupWindowAnimations() {
//设置进入动画
getWindow().setEnterTransition(TransitionInflater.from(this).inflateTransition(
R.transition.slide_from_bottom));
//设置监听
getWindow().getEnterTransition().addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
//结束时取消监听并且执行下一个动画
@Override
public void onTransitionEnd(Transition transition) {
getWindow().getEnterTransition().removeListener(this);
TransitionManager.go(scene0);//用一个默认动画来执行过渡
}
});
}
private void setupLayout() {
final ViewGroup activityRoot = (ViewGroup) findViewById(R.id.buttons_group);
ViewGroup sceneRoot = (ViewGroup) findViewById(R.id.scene_root);
scene0 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene0, this);
scene0.setEnterAction(new Runnable() { //新开一个线程
@Override
public void run() {
for (int i = 0; i < viewsToAnimate.size(); i++) {
View child = viewsToAnimate.get(i);
child.animate() //返回一个ViewPropertyAnimator对象 他可用于动画具体属性的设置
.setStartDelay(i * DELAY)//显示延迟的时间
.scaleX(1)//横向缩放
.scaleY(1);//纵向缩放
}
}
});
scene0.setExitAction(new Runnable() {
@Override
public void run() {
TransitionManager.beginDelayedTransition(activityRoot); //设置默认动画
View title = scene0.getSceneRoot().findViewById(R.id.scene0_title);
title.setScaleX(1); //设置缩放比例
title.setScaleY(1);
}
});
scene1 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene1, this); //设置布局
scene2 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene2, this);
scene3 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene3, this);
scene4 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene4, this);
View button1 = findViewById(R.id.sample3_button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TransitionManager.go(scene1, new ChangeBounds()); //插入布局并且执行动画
}
});
View button2 = findViewById(R.id.sample3_button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TransitionManager.go(scene2, TransitionInflater.from(AnimationsActivity2.this). //插入布局并且执行动画 并从xml中设置动画
inflateTransition(R.transition.slide_and_changebounds));
}
});
View button3 = findViewById(R.id.sample3_button3);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TransitionManager.go(scene3, TransitionInflater.from(AnimationsActivity2.this).//插入布局并且执行动画 并从xml中设置动画
inflateTransition(R.transition.slide_and_changebounds_sequential));
}
});
View button4 = findViewById(R.id.sample3_button4);
button4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {//插入布局并且执行动画 并从xml中设置动画
TransitionManager.go(scene4, TransitionInflater.from(AnimationsActivity2.this).
inflateTransition(R.transition.slide_and_changebounds_sequential_with_interpolators));
}
});
viewsToAnimate.add(button1);
viewsToAnimate.add(button2);
viewsToAnimate.add(button3);
viewsToAnimate.add(button4);
}
}
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@integer/anim_duration_long"> //时间
<slide /> //滑动
<changeBounds /> //更改大小
</transitionSet>
<pre style="font-family: 宋体; font-size: 9pt; background-color: rgb(255, 255, 255);"><pre name="code" class="java"><?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@integer/anim_duration_long" //时间
android:transitionOrdering="sequential"> //有序
<slide android:interpolator="@android:interpolator/decelerate_cubic" /> //插补器
<changeBounds android:interpolator="@android:interpolator/bounce" /> //插补器
</transitionSet>
十八、RevealActivity
public class RevealActivity extends BaseDetailActivity implements View.OnTouchListener {
private static final int DELAY = 100;
private RelativeLayout bgViewGroup;
private Toolbar toolbar;
private Interpolator interpolator;
private TextView body;
private View btnRed;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindData();
setupWindowAnimations();
setupLayout();
setupToolbar();
}
private void bindData() {
//绑定数据视图
ActivityRevealBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_reveal);
Sample sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
binding.setReveal1Sample(sample);
}
private void setupWindowAnimations() {
interpolator = AnimationUtils.loadInterpolator(this, android.R.interpolator.linear_out_slow_in);//获取插补器
//设置动画
setupEnterAnimations();
setupExitAnimations();
}
private void setupEnterAnimations() {
Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion);//获得动画
getWindow().setSharedElementEnterTransition(transition);//设置共享元素动画
transition.addListener(new Transition.TransitionListener() {//设置监听
@Override
public void onTransitionStart(Transition transition) {
}
@Override
public void onTransitionEnd(Transition transition) {
/**
* 删除监听其是非常重要的 因为在退出时动画会倒退执行一遍
* 如果不删除监听其那么这段代码会被再次执行
*/
transition.removeListener(this); //移除监听
hideTarget(); //隐藏圆圈
animateRevealShow(toolbar);//toolbar的缩放动画
animateButtonsIn();//button的入场动画
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
}
private void setupExitAnimations() {
Fade returnTransition = new Fade(); //淡入淡出
getWindow().setReturnTransition(returnTransition);
returnTransition.setDuration(getResources().getInteger(R.integer.anim_duration_medium));//时间
returnTransition.setStartDelay(getResources().getInteger(R.integer.anim_duration_medium));//延迟
returnTransition.addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
//移除监听
transition.removeListener(this);
animateButtonsOut();//button退场动画
animateRevealHide(bgViewGroup);
}
@Override
public void onTransitionEnd(Transition transition) {
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
}
private void setupLayout() {
bgViewGroup = (RelativeLayout) findViewById(R.id.reveal_root);
toolbar = (Toolbar) findViewById(R.id.toolbar);
body = ((TextView) findViewById(R.id.sample_body));
View btnGreen = findViewById(R.id.square_green);
btnGreen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
revealGreen();//变绿
}
});
btnRed = findViewById(R.id.square_red);
btnRed.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
revealRed();
}
});
View btnBlue = findViewById(R.id.square_blue);
btnBlue.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
revealBlue();
}
});
findViewById(R.id.square_yellow).setOnTouchListener(this);
}
private void revealBlue() {
animateButtonsOut();//让button消失
Animator anim = animateRevealColorFromCoordinates(bgViewGroup, R.color.sample_blue, bgViewGroup.getWidth() / 2, 0);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animateButtonsIn();//button出现
}
});
body.setText(R.string.reveal_body4);
body.setTextColor(ContextCompat.getColor(this, R.color.theme_blue_background));
}
private void revealRed() {
final ViewGroup.LayoutParams originalParams = btnRed.getLayoutParams(); //获取本来的位置
Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion); //读取动画文件
transition.addListener(new Transition.TransitionListener() { //设置监听
@Override
public void onTransitionStart(Transition transition) {
}
@Override
public void onTransitionEnd(Transition transition) {
animateRevealColor(bgViewGroup, R.color.sample_red);
body.setText(R.string.reveal_body3);
body.setTextColor(ContextCompat.getColor(RevealActivity.this, R.color.theme_red_background));
btnRed.setLayoutParams(originalParams); //设置回原来的位置
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
TransitionManager.beginDelayedTransition(bgViewGroup, transition);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); //获取layout参数
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);//设置到父控件居中的位置
btnRed.setLayoutParams(layoutParams);
}
private void revealYellow(float x, float y) {
animateRevealColorFromCoordinates(bgViewGroup, R.color.sample_yellow, (int) x, (int) y);
body.setText(R.string.reveal_body1);
body.setTextColor(ContextCompat.getColor(this, R.color.theme_yellow_background));
}
private void revealGreen() {
animateRevealColor(bgViewGroup, R.color.sample_green);
body.setText(R.string.reveal_body2);
body.setTextColor(ContextCompat.getColor(this, R.color.theme_green_background));//获取设置在color中的颜色
}
private void hideTarget() {
findViewById(R.id.shared_target).setVisibility(View.GONE);
}
private void animateButtonsIn() {
for (int i = 0; i < bgViewGroup.getChildCount(); i++) { //获取每一个button 让其一个个显示
View child = bgViewGroup.getChildAt(i);
child.animate()
.setStartDelay(100 + i * DELAY) //延迟时间
.setInterpolator(interpolator)
.alpha(1)//设置透明度
.scaleX(1)//设置缩放比例
.scaleY(1);
}
}
private void animateButtonsOut() {
for (int i = 0; i < bgViewGroup.getChildCount(); i++) {
View child = bgViewGroup.getChildAt(i);
child.animate()
.setStartDelay(i) //延迟
.setInterpolator(interpolator) //插补器
.alpha(0)//透明度
.scaleX(0f)//缩放比例
.scaleY(0f);
}
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
if (view.getId() == R.id.square_yellow) {
revealYellow(motionEvent.getRawX(), motionEvent.getRawY());
}
}
return false;
}
private void animateRevealShow(View viewRoot) {
//获取中心点坐标
int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
//获取宽高的中的最大值
int finalRadius = Math.max(viewRoot.getWidth(), viewRoot.getHeight());
/**
* 快速实现圆形缩放动画 第一个参数是你要进行圆形缩放的view 第二个参数和第三个参数是开始缩放点的x y坐标
* 第四第五个参数是开始的半径和结束的半径
*/
Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, cx, cy, 0, finalRadius);
viewRoot.setVisibility(View.VISIBLE); //设为可见
anim.setDuration(getResources().getInteger(R.integer.anim_duration_long));//设置时间
anim.setInterpolator(new AccelerateInterpolator());//设置插补器 一开始慢后来快
anim.start();
}
private void animateRevealColor(ViewGroup viewRoot, @ColorRes int color) {
//获取中心点
int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
animateRevealColorFromCoordinates(viewRoot, color, cx, cy);
}
private Animator animateRevealColorFromCoordinates(ViewGroup viewRoot, @ColorRes int color, int x, int y) {
float finalRadius = (float) Math.hypot(viewRoot.getWidth(), viewRoot.getHeight()); //获得直角三角形的斜边长
Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, x, y, 0, finalRadius);//设置动画
viewRoot.setBackgroundColor(ContextCompat.getColor(this, color));//设置颜色
anim.setDuration(getResources().getInteger(R.integer.anim_duration_long)); //时间
anim.setInterpolator(new AccelerateDecelerateInterpolator());//插补器
anim.start();
return anim;
}
private void animateRevealHide(final View viewRoot) {
//获取中心点
int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
//获取宽度
int initialRadius = viewRoot.getWidth();
//缩放动画
Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, cx, cy, initialRadius, 0);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
viewRoot.setVisibility(View.INVISIBLE); //设置为不可见
}
});
anim.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
anim.start();
}
}
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@integer/anim_duration_long"
android:interpolator="@android:interpolator/decelerate_cubic"
>
<changeBounds>
<!--patternPathMotion android:patternPathData="M0 0 L0 100 L100 0"/-->
<arcMotion
android:maximumAngle="90" //起始点和终点间最大的弧度
android:minimumHorizontalAngle="90" //起点和终点在水平靠近时最小的弧度
android:minimumVerticalAngle="0" /> 垂直靠近时最小的弧度
</changeBounds>
</transitionSet>