谁说Android的动画不廉价(四)之元素动画
16lz
2021-01-23
本系列文章一共5篇
谁说Android的动画不廉价(一)之项目分层
谁说Android的动画不廉价(二)之转场动画
谁说Android的动画不廉价(三)之共享元素动画
谁说Android的动画不廉价(四)之元素动画
谁说Android的动画不廉价(五)之水波纹动画
GitHub源码
引言
本篇博文是基于上一篇博文谁说Android的动画不廉价(三)之共享元素动画的基础上做的拓展。
目标效果图
转场动画前提说明
其实这篇博文分为两个动画。
- 第一种就是标题上的元素动画。就是View的位置,大小发生改变时伴随着动画效果。
- 另一种就是场景动画,同一些元素,在不同layout里面的位置大小不同,然后通过切换场景来模拟View的位置大小改变。不同的layout元素可以不一样,Android根据id来判断是否为同一个元素。两个layout没有相同元素的旧layout元素将会使用退出动画,然后没有相同元素的新layout元素将会使用进入动画
元素动画
如何开启
改变View的大小,位置之前使用TransitionManager.beginDelayedTransition(ViewGroup sceneRoot, [Transition transition]);
开启
- sceneRoot : 元素所在的ViewGroup
- transition : 改变时的动画效果
场景动画
如何加载场景
通过Scene.getSceneForLayout(ViewGroup viewGroup,int layoutID,Context context);
方法加载一个场景
-
viewGroup
: layout需要加入的ViewGroup,类似于Fragment使用中的FrameLayout容器 -
layoutID
: 场景的布局文件资源id
如何切换
通过TransitionManager.go(Scene scene,[Transition transition]);
方法来切换场景
元素动画
布局文件
activity_view_animation.xml
元素动画布局<?xml version="1.0" encoding="utf-8"?>
代码
MainActivity.java
public void viewAnimations(View v) { Intent intent = new Intent(this, ViewAnimationActivity.class); ActivityOptionsCompat activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this); startActivity(intent, activityOptionsCompat.toBundle()); }
ViewAnimationActivity.java
package demo.august1996.top.transitionanimationsdemo;import android.content.Intent;import android.support.v4.app.ActivityOptionsCompat;import android.transition.TransitionManager;import android.view.Gravity;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;import demo.august1996.top.transitionanimationsdemo.Activity.ToolbarActivity;public class ViewAnimationActivity extends ToolbarActivity { ViewGroup container; View imageView; boolean isChangeSize = false; boolean isChangePosition = false; @Override protected String getToolbarTitle() { return "元素动画"; } @Override protected void initView() { imageView = findViewById(R.id.img); container = (ViewGroup) findViewById(R.id.container); } @Override protected int getContentViewID() { return R.layout.activity_view_animation; } @Override protected boolean canBack() { return true; } /** * 修改指定View的大小,根据isChangeSize来判断 * isChangeSize == true:为修改过的大小,大小*2 * isChangeSize == false:为原始的大小,大小/2 * @param v */ public void changeSize(View v) { TransitionManager.beginDelayedTransition(container); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) imageView.getLayoutParams(); if (isChangeSize) { layoutParams.width = layoutParams.width * 2; } else { layoutParams.width = layoutParams.width / 2; } layoutParams.height = layoutParams.width; imageView.setLayoutParams(layoutParams); isChangeSize = !isChangeSize; } /** * 与changeSize类似 * @param v */ public void changePosition(View v) { TransitionManager.beginDelayedTransition(container); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) imageView.getLayoutParams(); if (isChangePosition) { layoutParams.gravity = Gravity.CENTER; } else { layoutParams.gravity = Gravity.LEFT; } imageView.setLayoutParams(layoutParams); imageView.postInvalidate(); isChangePosition = !isChangePosition; } public void next(View v) { Intent intent = new Intent(this, SceneActivity.class); ActivityOptionsCompat activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this); startActivity(intent, activityOptionsCompat.toBundle()); }}
改变View的布局参数前开启动画效果TransitionManager.beginDelayedTransition(container);
场景动画
布局文件
比较多,1个Activity的layout加上5个场景的layout
第一个是初始化的场景,其余四个是含有相同的元素,只是位置不同。
activity_scene.xml
<?xml version="1.0" encoding="utf-8"?>
-
FrameLayout
就是我们场景需要加载的地方 - 而且我们看到按钮有放大且透明出现的效果,所以我们先把
scaleX
、scaleY
和alpha
设置成0
sences_layout_0.xml
<?xml version="1.0" encoding="utf-8"?>
sences_layout_1.xml
<?xml version="1.0" encoding="utf-8"?>
sences_layout_2.xml
<?xml version="1.0" encoding="utf-8"?>
sences_layout_3.xml
<?xml version="1.0" encoding="utf-8"?>
sences_layout_4.xml
<?xml version="1.0" encoding="utf-8"?>
代码
SceneActivity.java
package demo.august1996.top.transitionanimationsdemo;import android.transition.ChangeBounds;import android.transition.Scene;import android.transition.Slide;import android.transition.TransitionManager;import android.transition.TransitionSet;import android.view.View;import android.view.ViewGroup;import android.view.animation.BounceInterpolator;import java.util.ArrayList;import java.util.List;import demo.august1996.top.transitionanimationsdemo.Activity.ToolbarActivity;public class SceneActivity extends ToolbarActivity { /** * 用于动画效果的按钮 */ List buttonList = new ArrayList<>(); /** * 添加场景到该ViewGroup */ ViewGroup viewRoot; /** * 一共5个场景,0为默认场景 */ Scene scene0; Scene scene1; Scene scene2; Scene scene3; Scene scene4; @Override protected void beforeInitView() { super.beforeInitView(); } @Override protected String getToolbarTitle() { return "场景动画"; } @Override protected void initView() { /** * 初始化按钮View */ buttonList.add(findViewById(R.id.one)); buttonList.add(findViewById(R.id.two)); buttonList.add(findViewById(R.id.three)); buttonList.add(findViewById(R.id.four)); viewRoot = (ViewGroup) findViewById(R.id.viewRoot); /** * 初始化场景 */ scene0 = Scene.getSceneForLayout(viewRoot, R.layout.sences_layout_0, this); scene1 = Scene.getSceneForLayout(viewRoot, R.layout.sences_layout_1, this); scene2 = Scene.getSceneForLayout(viewRoot, R.layout.sences_layout_2, this); scene3 = Scene.getSceneForLayout(viewRoot, R.layout.sences_layout_3, this); scene4 = Scene.getSceneForLayout(viewRoot, R.layout.sences_layout_4, this); /** * 当场景1被切换的时候,按钮显示动画 */ scene0.setEnterAction(new Runnable() { @Override public void run() { for (int i = 0; i < buttonList.size(); i++) { View view = buttonList.get(i); view.animate() .setDuration(1000) .scaleX(1) .scaleY(1) .alpha(1) .start(); } } }); /** * 切换到场景0 */ TransitionManager.go(scene0); } /** * 使用简单动画切换场景1 * @param v */ public void one(View v) { TransitionManager.go(scene1, new ChangeBounds()); } /** * 使用混合动画加载场景2 * @param v */ public void two(View v) { TransitionSet transitionSet = new TransitionSet(); transitionSet.setDuration(1000); Slide slide = new Slide(); ChangeBounds changeBounds = new ChangeBounds(); transitionSet.addTransition(slide); transitionSet.addTransition(changeBounds); TransitionManager.go(scene2, transitionSet); } /** * 使用混合动画加载场景3,并设置动画顺序 * @param v */ public void three(View v) { TransitionSet transitionSet = new TransitionSet(); transitionSet.setDuration(1000); Slide slide = new Slide(); ChangeBounds changeBounds = new ChangeBounds(); transitionSet.addTransition(slide); transitionSet.addTransition(changeBounds); transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL); TransitionManager.go(scene3, transitionSet); } /** * 使用混合动画加载场景4,并设置动画顺序和差时器 * @param v */ public void four(View v) { TransitionSet transitionSet = new TransitionSet(); transitionSet.setDuration(1000); transitionSet.setInterpolator(new BounceInterpolator()); Slide slide = new Slide(); ChangeBounds changeBounds = new ChangeBounds(); transitionSet.addTransition(slide); transitionSet.addTransition(changeBounds); transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL); TransitionManager.go(scene4, transitionSet); } @Override protected int getContentViewID() { return R.layout.activity_scene; } @Override protected boolean canBack() { return true; }}
我们的效果图
我们的效果图更多相关文章
- 谁说Android的动画不廉价(五)之水波纹动画
- Android属性动画设置中心点
- Android多种View动画:EasyAndroidAnimations
- Android之gif动画实现
- RecyclerView 实现item点击水波纹动画
- android启动画面
- android 设置布局动画
- RotateAniamtion_实现Android简单动画旋转案例