触摸反馈
触摸反馈(Touch Feedback)是 material design 给用户在与UI元素交互时提供的一种点交互。
Button 默认反馈动画用的是 RippleDrawable 类,RippleDrawable能在不同状态下有不同的涟漪效果。
也可以利用xml自定义各种样式的涟漪。
android:colorControlHighlight可以利用到主题中
主要使用RippleDrawable
系统默认提供了两种效果:
// 有界涟漪(涟漪只在Button内扩散)
?android:attr/selectableItemBackground
// 波纹涟漪(涟漪会以Button最长部分作为圆的直径进行圆形扩散)
?android:attr/selectableItemBackgroundBorderless
也可用RippleDrawable的xml定制
给View的background设置一下即有波纹效果
XML方式:
使用
1
2
3
4
5
6
7
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="@string/selectableItemBackground"
android:background="?android:attr/selectableItemBackground"/>
自定义ripple
/drawable/ripple.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@android:color/holo_red_light">
http://schemas.android.com/apk/res/android"
android:color="@android:color/darker_gray">
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#ff00ff00"/>
@android:color/holo_blue_light
@android:color/holo_green_light
揭示动画
揭示动画(RevealEffect)在UI元素出现或隐藏时,为用户提供视觉连续性。ViewAnimationUtils.createCircularReveal()方法可以使用一个附着在视图上的圆形,显示或隐藏这个视图。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31// 显示
findViewById(R.id.btn_show).setOnClickListener(newView.OnClickListener() {
@Override
publicvoidonClick(View v) {
v1.setVisibility(View.VISIBLE);
// view 操作的视图
// centerX 动画开始的中心点X
// centerY 动画开始的中心点Y
// startRadius 动画开始半径
// startRadius 动画结束半径
Animator anim = ViewAnimationUtils.createCircularReveal(v1,0,0,0, (float) Math.hypot(v1.getWidth(), v1.getHeight()));
anim.start();
}
});
// 隐藏
findViewById(R.id.btn_hide).setOnClickListener(newView.OnClickListener() {
@Override
publicvoidonClick(View v) {
v2.setVisibility(View.VISIBLE);
Animator anim = ViewAnimationUtils.createCircularReveal(v2,0,0, (float) Math.hypot(v2.getWidth(), v2.getHeight()),0);
anim.addListener(newAnimatorListenerAdapter() {
@Override
publicvoidonAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
v2.setVisibility(View.INVISIBLE);
}
});
anim.start();
}
});
Activity过度动画
material design中的activity过度动画提供了视觉衔接。你可以指定activity进出的过度动画 和 两个activity相同元素的过度动画。
activity进出过度动画有3种:
explode:从场景的中心移入或移出(从点击处爆炸)
slide:从场景的边缘移入或移出
fade:调整透明度产生渐变效果
explode:
slide:
slide有4种:slide_top、slide_bottom、slide_left、slide_right
下面是slide_bottom
fade:
XML 方式:
/values/styles.xml
1
2
3
4
5
6
7
8
9
10
11
true
@android:transition/slide_top
@android:transition/slide_bottom
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
Java Code方式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// ActivityA.java
// 允许使用过渡动画 必须并且在setOncontent()方法之前
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// 设置过度动画
getWindow().setEnterTransition(newExplode() );
getWindow().setExitTransition(newExplode() );
// 跳转时启动过度动画 xml方式时也使用此方法进行跳转
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
// ActivityB.java
// 允许使用过渡动画 必须并且在setOncontent()方法之前
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// 当从activity A -> activity B,在B中设置会使过度更好
getWindow().setAllowEnterTransitionOverlap(true);
// 为了使动画在 B 结束的时候reverse调用 Activity.finishAfterTransition() 代替Activity.finish()
finishAfterTransition();
两个activity相同元素在activity跳转时的动画有4种:
changeBounds -对目标视图的外边界进行动画
changeClipBounds -对目标视图的附着物的外边界进行动画
changeTransform -对目标视图进行缩放和旋转
changeImageTransform -对目标图片进行缩放
XML 方式:
res/style.xml
1
2
3
@transition/move_image
@transition/move_image
/res/transition.xml
1
2
3
4
5
6
7
ActivityOptions options = ActivityOptions .makeSceneTransitionAnimation(this, shareView, "shareName");
startActivity(intent, activityOptions.toBundle());
Java Code方式:
Activity A
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// 一个View共享
// 允许使用过渡动画 必须并且在setOncontent()方法之前
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// java code 和 XML 方式都需要调用此方法
ActivityOptions options = ActivityOptions .makeSceneTransitionAnimation(this, shareView,"shareName");
startActivity(intent, activityOptions.toBundle());
// 多个View共享
// 允许使用过渡动画 必须并且在setOncontent()方法之前
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(
this,
newPair(
view.findViewById(R.id.v),
"view"),
newPair(
view.findViewById(R.id.tv),
"text_view")
);
startActivity(intent, activityOptions.toBundle());
Activity B
1
2
3
4// 指定一个view调用此方法 使两个activity跳转具有联动性
v.setTransitionName("robot");
// 为了使动画可逆 在 B 结束的时候调用 Activity.finishAfterTransition() 代替Activity.finish()
finishAfterTransition();
曲线运动&PathInterpolator
material design中的动画依赖于时间差值曲线和空间移动模式。Android 5.0中,你可以为动画定义时间曲线和曲线运动模式
新引入的PathInterpolator是一个基于贝塞尔曲线或者Path对象的插值器。这个插值器定义了在 1x1 方形中的运动曲线,以及(0, 0)和(1, 1)锚点,通过控制点作为构造参数。你也可以定义一个path 插值器作为xml资源
XML方式:
1
2
3
4
5http://schemas.android.com/apk/res/android"
android:controlX1="0.4"
android:controlY1="0"
android:controlX2="1"
android:controlY2="1"/>
Java Code方式:
1
Interpolator EASE_IN =newPathInterpolator(0.0f,0.0f,0.2f,1.0f);
Material Design标准中,系统提供了三种基本的曲线:
@interpolator/fast_out_linear_in.xml
@interpolator/fast_out_slow_in.xml
@interpolator/linear_out_slow_in.xml
你可以将一个PathInterpolator对象传给Animator.setInterpolator()方法。
ObjectAnimator类有一个新的构造函数,使你可以沿一条路径使用多个属性来在坐标系中进行变换。
1
2
3
4ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
...
mAnimator.start();
视图状态改变动画
StateListAnimator类是你可以定义在视图状态改变启动的Animator.
/drawable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
http://schemas.android.com/apk/res/android">
android:propertyName="translationZ"
android:duration="@android:integer/config_shortAnimTime"
android:valueTo="30dp"
android:valueType="floatType"/>
android:propertyName="translationZ"
android:duration="100"
android:valueTo="0"
android:valueType="floatType"/>
xml方式调用
1
2
android:stateListAnimator=“@drawable/selector_xxx” />
Java方式调用
1
2AnimationInflater.loadStateListAnimator()
View.setStateListAnimator()
AnimatedStateListDrawable类使你可以创建一个在视图状态变化之间显示动画的drawable。有一些Android 5.0系统组件默认已经使用了这些动画。
/drawable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
xmlns:android="http://schemas.android.com/apk/res/android">
android:state_pressed="true"/>
android:state_focused="true"/>
android:drawable="@drawable/drawableD"/>
...
...
当主题为Material时,Button会有Z轴的动画,为了避免这种现象可以android:stateListAnimator="@null"
矢量动画
android5.0支持svg,引入了VectorDrawable,svg时矢量图形的一种图形格式,可绘制矢量图在拉伸时不会失真。
AnimatedVectorDrawable类让你可以在可绘制矢量图上面作用动画。
通常需要在三个xml文件中定义可动的矢量图:
一个矢量图使用元素,放在res/drawable/下。
一个可动的矢量图使用元素,放在res/drawable/下。
一个或更多个动画对象使用元素,放在res/anim/下。
可动矢量图可以使用和元素。元素定义一系列路径或者子组,元素定义可绘图的路径。
当你定义了一个想要作用动画的矢量可绘制图,使用android:name属性给每个group和path指定一个唯一的名字,这样你可以从动画的定义中找到他们。
svg_vector文档:Svg_vector属性详述.doc
1
2
3
4
5
6
7
8
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:layout_gravity="center"
android:text="example_from_documentation"
android:drawableBottom="@drawable/avd"/>
绘制vectordrawable
/drawable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
http://schemas.android.com/apk/res/android"
android:height="64dp"
android:width="64dp"
android:viewportHeight="600"
android:viewportWidth="600">
android:name="rotationGroup"
android:pivotX="300.0"
android:pivotY="300.0"
android:rotation="45.0">
android:name="v"
android:fillColor="#000000"
android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z"/>
可动的矢量绘制通过刚刚说到定义的名字,来找到这些path和group:
/drawable
1
2
3
4
5
6
7
8
9
10
11
http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vectordrawable">
android:name="rotationGroup"
android:animation="@anim/rotation"/>
android:name="v"
android:animation="@anim/path_morph"/>
动画的定义表现在ObjectAnimator和AnimatorSet对象中。第一个动画在这个例子中是让目标组旋转360度:
1
2
3
4
5
6
android:duration="6000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"/>
第二个动画例子是把矢量可绘图从一个形状变成另一种。所有的路径必须兼容变换:他们必须有相同数量的命令,每个命令要有相同的参数。
1
2
3
4
5
6
7
8
9
http://schemas.android.com/apk/res/android">
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
android:valueType="pathType"/>
调用动画:
1
2
3
4
5for(finalDrawable drawable : textView.getCompoundDrawables()) {
if(drawableinstanceofAnimatable) {
((Animatable) drawable).start();
}
}