以下都需要运行在5.0以上
一、揭露动画效果
参考:使用Circular Reveal为你的应用添加揭露动画效果
最主要的类Circular Reveal
官方将这一动画称为揭露效果,它在官网中的描述是这样的:
当您显示或隐藏一组 UI 元素时,揭露动画可为用户提供视觉连续性。[ViewAnimationUtils.createCircularReveal()](https://developer.android.com/reference/android/view/ViewAnimationUtils.html?hl=zh-cn#createCircularReveal(android.view.View, int, int, float, float))
方法让您能够为裁剪区域添加动画以揭露或隐藏视图。
很明显,我们使用ViewAnimationUtils.createCircularReveal()方法就能达到基本的揭露动画效果了。那么我们就直接开始看一下这个方法到底需要哪些参数吧
Animator createCircularReveal (View view, // The View will be clipped to the animating circle.
int centerX, // The x coordinate of the center of the animating circle, relative to view
int centerY, // The y coordinate of the center of the animating circle, relative to view
float startRadius, // The starting radius of the animating circle.
float endRadius // The ending radius of the animating circle.
)
ViewAnimationUtils.createCircularReveal()方法所执行的效果,就是将一个View裁剪成圆,然后从圆心逐渐揭露展现视图。
参数 | 参数说明 |
---|---|
view | 要执行动画效果的View |
centerX | 圆心x坐标 |
centerY | 圆心y坐标 |
startRadius | 开始时的圆半径 |
endRadius | 结束时的圆半径 |
其实参数都是比较容易理解的,主要是涉及到了动画开始的x,y坐标,以及圆形揭露的半径变化startRadius->endRadius。
在此我就以最上面的那个效果图为例,对createCircularReveal ()的使用进行一个简单的引入吧。
简单使用:
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewAnimationUtils;
public class MainActivity extends AppCompatActivity {
private View mView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mView = findViewById(R.id.view);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_enter:
revealEnter();
break;
case R.id.btn_exit:
revealExit();
break;
}
}
/**
* 进入动画
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void revealEnter() {
//获取视图的宽度
int w = mView.getWidth();
int h = mView.getHeight();
//设置基准点(园的中心点)的位置 从左上角开始(0,0)
//(w,h) 应该在视图的右下角
int cx = w;
int cy = h;
//Math.hypot() 函数返回它的所有参数的平方和的平方根,即:视图的对角线
//开始的圆的半径
int r = (int) Math.hypot(w, h);
Animator animator = ViewAnimationUtils.createCircularReveal(mView, cx, cy, 0, r);
//设置显示动画的时间间隔
animator.setDuration(2000);
mView.setVisibility(View.VISIBLE);
animator.start();
}
/**
* 离开动画
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void revealExit() {
//获取视图的宽度
int w = mView.getWidth();
int h = mView.getHeight();
//设置基准点(园的中心点)的位置 从左上角开始(0,0)
int cx = w;
int cy = h;
//Math.hypot() 函数返回它的所有参数的平方和的平方根,即:视图的对角线
//开始的圆的半径
int r = (int) Math.hypot(w, h);
/**
*
*/
Animator animator = ViewAnimationUtils.createCircularReveal(mView, cx, cy, r, 0);
//设置显示动画的时间间隔
animator.setDuration(2000);
animator.start();
//当动画结束后让视图不可见
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mView.setVisibility(View.INVISIBLE);
}
});
}
}
二、转场动画(场景间 同一个Activity中)
Transition框架核心Scene、Transition和TransitionManager类
-
Scene:场景 (定义了界面当前的状态信息,保存了布局中所有View的属性值)
其中Scene是一个容器,就是放置你定义的布局,而真正去做场景之间切换这个动作是Transition框架中TransitionManager 调用其中go方法或者transitionTo方法完成场景之间切换,而真正创建具体动画交由Transition子类来完成,开始动画交给Transition来执行。
转:Android场景动画(Scene)Scene.getSceneForLayout() 参数介绍如下:
- sceneRoot 表示从什么地方开始切换场景。
- layoutId 切换到什么场景的布局文件,比如上述例子中生成Scene2实例,layoutId 就是场景2中的布局。
- context 上下文
-
Transition:转换
当一个场景改变的时候,transition主要负责:捕获每个View在开始场景和结束场景时的状态(各种属性值);
根据两个场景(开始和结束)之间的区别自动创建一个Animator。
监听一个容器内部有控件的状态发生改变后执行的动画
一个有四种动画效果:
- Slide 划入
- Explode 爆炸
- Fade 隐藏
- changeBounds 位置与大小变化
-
TransitionManager:负责场景之间的跳转和添加效果
- 这个类将
Sence
与Transition
关联了起来,大多数情况下的场景变化都会使用AutoTransition(默认动画)
。只有当应用程序需要不同的转换行为时,才需要指定其他的Transition来满足特定的场景需求。
- setTransition(Scene scene, Transition transition)
设置需要的场景与过渡动画
- setTransition(Scene fromScene, Scene toScene, Transition transition)
设置起始场景和结束场景与过渡动画
- go(Scene scene)
切换到指定的场景
- go(Scene scene, Transition transition)
切换到指定的场景以及所使用的过渡动画,transition如果传了null,那么就没有了过渡动画。
- beginDelayedTransition(ViewGroup sceneRoot, Transition transition)
可以自定义场景过渡的方法,调用此方法时,TransitionManager会捕获sceneRoot中View的属性值,然后发出请求以在下一帧上进行转换。那时候,sceneRoot中的新值将被捕获,变化的过程将会以动画的形式展现出来。我们没有必要创建一个新的Scene,因为这个方法主要是用来展现当前场景到下一帧的过渡效果。
- void endTransitions (ViewGroup sceneRoot)
结束指定场景根目录在准备/正在进行的转换。
更详细的解释,请移步官方API。
示例代码:
效果:
自定义动画效果:在res目录中创建transition文件夹 创建transition.xml文件
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<!--第一种动画效果-->
<changeImageTransform android:duration="1000">
<!--指定图片控件的id-->
<targets android:targetId="@id/image" />
</changeImageTransform>
<!--第二种动画效果 淡入淡出-->
<fade android:duration="1000" android:startDelay="1000">
</fade>
</transitionSet>
实现类
public class SceneActivity extends AppCompatActivity {
private Scene mOverViewScene;
private Scene mInfoScene;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scene);
//根布局
ViewGroup sceneRoot = (ViewGroup) findViewById(R.id.scene_root);
//搭建第一个场景
mOverViewScene = Scene.getSceneForLayout(sceneRoot, R.layout.scene_overview, getBaseContext());
//搭建第二个场景
mInfoScene = Scene.getSceneForLayout(sceneRoot, R.layout.scene_info, getBaseContext());
//首先跳转到第一个场景
TransitionManager.go(mOverViewScene);
}
//点击事件实现场景的跳转逻辑
public void onClick(View view) {
switch (view.getId()) {
//点击info图标时
case R.id.btnInfo:
//加载自定义的跳转动画
Transition transition = TransitionInflater.from(getBaseContext())
.inflateTransition(R.transition.transition);
TransitionManager.go(mInfoScene, transition);
//默认是AutoTransition
//TransitionManager.go(mInfoScene);
break;
//点击close图标时
case R.id.btnClose:
TransitionManager.go(mOverViewScene);
break;
}
}
}
三、Activity间的转场动画
转:android 学习使用Activity转场动画及shareElement
转场动画(Activity Transition)基本介绍
Android 5.0 提供了三种Transition类型
- 进入:决定Activity中的所有的视图怎么进入屏幕。
- 退出:决定一个Activity中的所有视图怎么退出屏幕。
- 共享元素(shareElement):决定两个activities之间的过渡,怎么共享(它们)的视图。
进入和退出包含如下动画效果
- explode(分解) – 从屏幕中间进或出
- slide(滑动) - 从屏幕边缘进或出地
- fade(淡出) –通过改变屏幕上视图的不透明度达到添加或者移除视图的效果
共享元素包含如下动画效果
- changeBounds - 改变目标视图的布局边界
- changeClipBounds - 裁剪目标视图边界
- changeTransform - 改变目标视图的缩放比例和旋转角度
- changeImageTransform - 改变目标图片的大小和缩放比例
Transition 与 Activity的跳转动画有以下几个
- setEnterTransition 进入的动画
- setExitTransition 退出的动画
- setReturnTransition 返回的动画
-
setReenterTransition 重入的动画
示例:
第一个Activity
public class FirstActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void onClick(View view) {
int resId = -1;
switch (view.getId()) {
case R.id.iv1:
resId = R.drawable.pic1;
break;
case R.id.iv2:
resId = R.drawable.pic2;
break;
case R.id.iv3:
resId = R.drawable.pic3;
break;
case R.id.iv4:
resId = R.drawable.pic4;
break;
}
/**
* 每点击一张图片
* 都会将这一张图片的资源id传出去
*/
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("resId", resId);
//创建transition
Transition transition = new Explode();
//指定状态栏不变(指定某一个控件不使用动画)(排除某个元素不在转场动画中)
transition.excludeTarget(android.R.id.statusBarBackground, true);
//设置进场动画
getWindow().setEnterTransition(transition);
//设置离场动画
getWindow().setExitTransition(transition);
//重进动画
getWindow().setReenterTransition(transition);
//设置共享元素进场动画
getWindow().setSharedElementEnterTransition(transition);
//设置共享元素(当前view 和 共享元素id 根据这个id来匹配)
Pair<View, String> shareElement = Pair.create(view, "img");
//makeSceneTransitionAnimation 可以不设置或者设置多个共享元素
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, shareElement);
//通过toBundle方法传给startActivity
startActivity(intent, options.toBundle());
}
}
第二个Activity
public class SecondActivity extends Activity {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
//拿到传来的图片资源id
int resId = getIntent().getExtras().getInt("resId");
ImageView iv = findViewById(R.id.iv);
//共享元素的id
iv.setTransitionName("img");
//设置给当前布局的ImageView
iv.setImageResource(resId);
Transition transition = new Explode();
//指定状态栏不变(指定某一个控件不使用动画)(排除它)
transition.excludeTarget(android.R.id.statusBarBackground, true);
//设置进场动画
getWindow().setEnterTransition(transition);
//设置离场动画
getWindow().setExitTransition(transition);
}
}
除了可以在代码中开启转场还可以定义在Style中
启动转场
<style name="BaseAppTheme" parent="android:Theme.Material">
<!– 启动窗口内容转场 -->
<item name="android:windowContentTransitions">true</item>
<!– 窗口进入/离开时演示的动画 -->
<item name="android:windowEnterTransition">@transition/explode</item> <item name="android:windowExitTransition">@transition/explode</item>
<!– 共享元素进入/离开时演示的动画 -->
<item name="android:windowSharedElementEnterTransition">
@transition/change_image_transform</item>
<item name="android:windowSharedElementExitTransition">
@transition/change_image_transform</item>
</style>