在安卓5.0 的时候加入了触摸反馈,也就是水波纹
使用
1.现在创建新的工程的时候一般默认按钮有水波纹效果,如果想去掉,给view指定一个颜色就没有了
代码:
android:background="?android:attr/selectableItemBackground"波纹有边界
android:background="?android:attr/selectableItemBackgroundBorderless"波纹超出边界
设置水波纹颜色,目前我发现只能通过主题设置,不可以直接写到xml中修改 主题:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
设置水波纹颜色
<item name="colorControlHighlight">@color/colorAccent</item>
选中颜色设置,控件,CheckBox,RadioButton之类的控件
<item name="colorControlHighlight">@color/colorAccent</item>
Button 点击水波纹效果
ActivityOptions动画详解
ActivityOptions 是5.0 新出来动画,先来看下效果
原点爆炸
点击列表图片,过渡到下个页面动画
explode 和slide 动画效果
explode : 页面展开效果
slide : 侧滑
//Gravity.TOP 从上往下滚动
//Gravity.BOTTOM 从下往上
//Gravity.LEFT 从左滚动过来
原点爆炸动画学习
原点爆炸动画的实现,主要使用到了,页面之间共享元素,而这个元素通常指view,把A界面的元素传递到B界面,在A界面退出,B界面进来的时候,共享元素就会开始过渡,这个过渡是有动画效果的,而这个元素共享只是原点爆炸的第一步:
看下A 界面 xml布局:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:text="圆点爆炸demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="30dp"
android:layout_marginRight="10dp"
android:transitionName="@string/fb_sharedelementname"
android:src="@android:drawable/ic_dialog_email"/>
</RelativeLayout>
FloatingActionButton在界面的右下角,细心的同学会看到多了一个不认识的标签:
android:transitionName="@string/fb_sharedelementname"
这个标签就是用来标记共享元素的,A界面的元素,跟B界面的元素都是独立view,用 android:transitionName关联起来,形成元素共享,稍后看B 界面的xml你就懂了。
FloatingActionButton 点击事件,跳转到下一级界面:
activity = CircularRevealMainActivity.this;
final FloatingActionButton fb = (FloatingActionButton) findViewById(R.id.fb);
fb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityOptions activityOptions=ActivityOptions.
makeSceneTransitionAnimation
(activity,fb,fb.getTransitionName());
Intent intent=new Intent(activity,CircularRevealPaoZaActivity.class);
activity.startActivity(intent,activityOptions.toBundle());
}
});
第一个参数上下文,第二个参数共享view,第三个参数共享元素的名字
ActivityOptions. makeSceneTransitionAnimation (activity,fb,fb.getTransitionName());
ActivityOptions 这个类只能兼容到5.0,低版本运行会奔溃,如果你兼容到低版本需要做版本控制:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.0 以上执行
} else {
//低版本执行
}
每次需要做版本控制,很烦,刚好有一个兼容类ActivityOptionsCompat,此类能兼容到4.x,动画都能出现,那么这个类就可以用了,我注意了下,目前主流APP,qq,今日头条,基本上只兼容到4.0左右,也就是说低版本不需要适配动画了,而且ActivityOptions 的动画效果ActivityOptionsCompat都有,只是在跳转的时候小小的改变
例:共享元素跳转方法,只要替换成这样,其他不改变
ActivityOptionsCompat options5 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, iv, "options5");
ActivityCompat.startActivity(context, new Intent(context, Activity_A.class), options5.toBundle());
接下来讲FloatingActionButton 触发点击事件跳到下一界面
B界面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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_rl"
android:background="@android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.FloatingActionButton
android:id="@+id/shared_fb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
app:elevation="0dp"
app:fabSize="normal"
android:background="@color/colorAccent"
app:pressedTranslationZ="8dp"
android:transitionName="@string/fb_sharedelementname" />
<RelativeLayout
android:id="@+id/context_rl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
android:background="@color/colorAccent"
tools:visibility="visible">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:gravity="center"
android:text="内容中心"
android:textSize="30dp" />
</RelativeLayout>
</RelativeLayout>
先讲下 FloatingActionButton ,在布局中为什么这么写
<android.support.design.widget.FloatingActionButton
android:id="@+id/shared_fb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
app:elevation="0dp"
app:fabSize="normal"
android:background="@color/colorAccent"
app:pressedTranslationZ="8dp"
android:transitionName="@string/fb_sharedelementname" />
- android:transitionName=”@string/fb_sharedelementname” 给view设置共享标记,这一个要设置的
- app:elevation=”0dp” 为什么写这个,FloatingActionButton 不会因为自己被下一个view覆盖,他会永远浮在rootview的最上层。
- FloatingActionButton 定位到布局中间
做完这个操作我们就可以看到这样的动画效果:
在之前的效果图片上我们看到,他有一个微微弯曲的效果,不知道你们注意没
//这段就是给共享元素设置了一个动画过渡
Transition transition= TransitionInflater.from(this).inflateTransition(R.transition.arc_motion);
getWindow().setSharedElementEnterTransition(transition);
transition.addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
}
@Override
public void onTransitionEnd(Transition transition) {
transition.removeListener(this);
//共享元素过渡动画执行完毕后,开始执行爆炸动画效果
showCircularReveal();
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
这段代码的作用就是给共享元素加入一个微微弯曲的动画
Transition transition= TransitionInflater.from(this).
inflateTransition(R.transition.arc_motion);
getWindow().setSharedElementEnterTransition(transition);
arc_motion 布局
<?xml version="1.0" encoding="utf-8"?>
<transitionSet
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:interpolator="@android:interpolator/linear_out_slow_in">
<changeBounds>
<!--suppress AndroidElementNotAllowed -->
<arcMotion
android:maximumAngle="90"
android:minimumHorizontalAngle="90"
android:minimumVerticalAngle="0"/>
</changeBounds>
</transitionSet>
showCircularReveal(); 用来显示爆炸圆的动画
private void showCircularReveal() {
int cx = (main_rl.getLeft() + main_rl.getRight()) / 2;
int cy = (main_rl.getTop() + main_rl.getBottom()) / 2;
float finalRadius = (float) Math.hypot(main_rl.getWidth(), main_rl.getHeight());
// 设置圆形显示动画
//第一个参数就是执行动画的view;第二,第三个参数就是执行动员的x,y轴距离;第四个参数动画起始大 //小半径;第五个参数动画最大执行半径
Animator anim = ViewAnimationUtils.createCircularReveal(main_rl, cx, cy, shared_fb.getWidth()/2, finalRadius);
anim.setDuration(300);
anim.setInterpolator(new AccelerateDecelerateInterpolator());
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
main_rl.setVisibility(View.VISIBLE);
setInitAnimation();
}
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
main_rl.setBackgroundColor(ContextCompat.getColor(activity, R.color.colorAccent));
}
});
anim.start();
}
- ViewAnimationUtils.createCircularReveal() 5.0的新特性
- xml 布局中最外层view,用来获取界面的中心点
int cx = (main_rl.getLeft() + main_rl.getRight()) / 2;
int cy = (main_rl.getTop() + main_rl.getBottom()) / 2;
- 获取界面的对角线
float finalRadius = (float) Math.hypot(main_rl.getWidth(), main_rl.getHeight());
爆炸动画执行完毕后,执行下面这个方法,让context_rl 显示,在布局中是占位存在,覆盖掉布局中的
FloatingActionButton。
public void setInitAnimation()
{
Animation animation = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
animation.setDuration(300);
context_rl.startAnimation(animation);
context_rl.setVisibility(View.VISIBLE);
}
不可以在控制FloatingActionButton 的时候setVisibility()控制隐藏 ,
最好的办法就是,布局覆盖。
由于没有给 B Activity 设置 销毁动画( ReturnTransition),所以在退出B Activity的时候,动画会自动翻转执行。
设置了ReturnTransition ,点击back按钮会执行这个动画
Fade fade = new Fade();
getWindow().setReturnTransition(fade);
fade.setDuration(300);
explode 和slide 动画学习
explode , getWindow().setExitTransition(explode);设置退出activity 过渡动画
A activity
展开动画
/**
* 设置窗口 离开动画
* <p>
* 测试证明 这个方法在这个Activity 跳转之前设置都有效果
*/
public void setWindsExitAnimations() {
Explode explode = new Explode();
explode.setDuration(500);
getWindow().setExitTransition(explode);
}
跳转
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation
(ActivityOptionsAnimationSetActivity.this);
activity.startActivity(new Intent(ActivityOptionsAnimationSetActivity.this, ExplodeActivity.class), options.toBundle());
B activity
渐变动画
private void setWindsEnterAnimations() {
Fade slide=new Fade();
slide.setDuration(300);
getWindow().setEnterTransition(slide);
}
slide
slide 侧滑动画
A activity
private void setWindsSlideExitAnimations() {
//Gravity.TOP 从上往下滚动
//Gravity.BOTTOM 从下往上
//Gravity.LEFT 从左滚动过来
Slide slide = new Slide(Gravity.LEFT);
slide.setDuration(500);
slide.setInterpolator(new AccelerateDecelerateInterpolator());
getWindow().setExitTransition(slide);
}
跳转
ActivityOptions options1 = ActivityOptions.makeSceneTransitionAnimation
(ActivityOptionsAnimationSetActivity.this);
activity.startActivity(new Intent(ActivityOptionsAnimationSetActivity.this, SlideActivity.class), options1.toBundle());
B activity
Fade slide=new Fade();
slide.setDuration(300);
getWindow().setEnterTransition(slide);
Fade ,slide,explode 也可以用xml建立
<?xml version="1.0" encoding="utf-8"?>
<slide xmlns:android="http://schemas.android.com/apk/res/"
android:duration="1000"/>
Slide slide = TransitionInflater.from(this).inflateTransition(R.transition.activity_slide);
getWindow().setExitTransition(slide);
在写Slide ,explode demo的时候,A 界面进入B 界面,B界面按返回键,操作过快情况下返回A 界面,就会出现空白,或者view 缺少
我这样处理还是不行,还是会出现空白,这就坑了,不过我知道一个解决方法
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) {
finishAfterTransition();//退出动画一定要这么写,要不然会出现bug
return false;
}
return super.onKeyDown(keyCode, event);
}
解决方法:
这样处理就不会出现,我也不知道这样处理是不是对的
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
- Exit Transition:可以理解为activity进入后台的过渡动画
- Enter Transition:可以理解为创建activity并显示时的过渡动画
- Return Transition:可以理解为销毁activity时的过渡动画
- Reenter Transition:可以理解为activity从后台进入前台时的过渡动画
View的高度与阴影
View高度 = elevation + translationZ
- elevation表示view的高度,高度越大,阴影越大,可以在xml中直接使用属性, 也可以在代码中使用view.setEvelvation();
android:elevation="10dp"
- transtionZ属性表示view在Z方向移动的距离,一般用于属性动画中
android:translationZ="10dp"
- 高度影响View的绘制顺序,过去是按View添加顺序绘制,先添加的先绘制,现在高度小的先绘制,因为高度小的,层级低,在下面, 高度相同的,按添加顺序绘制
注意:
如果View的背景色为透明,则不会显示出阴影效果
只有子View的大小比父View小时,阴影才能显示出来
git地址:https://github.com/Followk/demoanimation
参考大神:
Transition 动画参考
http://blog.csdn.net/caroline_wendy/article/details/50756717
http://blog.csdn.net/ss1168805219/article/details/53445063
https://damonzh.github.io/2016/04/04/transition-framework/
http://blog.csdn.net/qq_23547831/article/details/51821159
http://blog.csdn.net/tm1989tm/article/details/51025309
5.0新特性参考:
http://blog.csdn.net/tianzhu2725/article/details/52775285
http://blog.csdn.net/yangxi_pekin/article/details/50610818
http://blog.csdn.net/a396901990/article/details/40187203