Android动画属性一
标签: Android 动画属性
1. 控件添加动画属性
布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/content_layout">
<ImageView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/back2"
android:scaleType="centerCrop"
android:onClick="rotateAnimation"/>
</RelativeLayout>
其中ImageView添加了一个属性 android:onClick="rotateAnimation"
点击时会执行rotateAnimation
rotateAnimation
并不是系统给的,是自己实现的。rotateAnimation
只是一个名字,要实现这个名字的方法。
如下:
public class ScrollingActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scrolling);
}
public void rotateAnimation(View view){
//具体动画
}
}
2. ObjectAnimator 动画效果
1、ofFloat实现旋转
如下:
public class ScrollingActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scrolling);
}
public void rotateAnimation(View view){
/**
* rotationX 绕着X轴旋转
* 从初始夹角180度开始旋转到10度
* 最后显示10度的状态
*/
ObjectAnimator.ofFloat(view,"rotationX",180.0f,10.0f).setDuration(500).start();
}
}
使用了ObjectAnimator动画效果
rotationX 绕着X轴旋转
ofFloat(控件对象,方向,起始角度,终止角度);
或者 ofFloat(控件对象,方向,终止角度);
setDuration(动画持续时间);
start()开始;
对于ObjectAnimator
1、提供了ofInt、ofFloat、ofObject,这几个方法都是设置动画作用的元素、作用的属性、动画开始、结束、以及中间的任意个属性值。
当对于属性值,只设置一个的时候,会认为当然对象该属性的值为开始(getPropName反射获取),然后设置的值为终点。如果设置两个,则一个为开始、一个为结束~~~
动画更新的过程中,会不断调用setPropName更新元素的属性,所有使用ObjectAnimator更新某个属性,必须得有getter(设置一个属性值的时候)和setter方法~
2、如果你操作对象的该属性方法里面,比如上例的setRotationX如果内部没有调用view的重绘,则你需要自己按照下面方式手动调用。
anim.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
// view.postInvalidate();
// view.invalidate();
}
});
2、实现缩放和淡出
方法一
public void rotateAnimation(final View view){
ObjectAnimator animator = ObjectAnimator.ofFloat(view,"xyz",1.0f,0.0f).setDuration(500);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float cVal = (float) animation.getAnimatedValue();
view.setAlpha(cVal); //设置控件透明度
view.setScaleY(cVal); //设置控件x轴宽度
view.setScaleX(cVal); //设置控件Y轴宽度
}
});
这里设置了变化量为“xyz”就是一个没有的量,初始值为1,终值为0,点击时变化。
这样就获得了1-0的渐变量,然后设置监听器,变化更新时:
view.setAlpha(cVal); 设置当前渐变量为当前透明度。
view.setScaleX(cVal); 设置当前渐变量为当前View的宽度。
view.setScaleY(cVal); 设置当前渐变量为当前View的高度。
方法二
使用 propertyValuesHolder 同时设置多个变化属性。
public void propertyValuesHolder(View view)
{
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,
0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f,
0, 1f);
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f,
0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(1000).start();
}
3、ValueAnimator属性动画
先是布局代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.valueanimatortest.MainActivity">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/redball"
android:id="@+id/red_ball"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button
android:id="@+id/line"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="LineRun"
android:text="垂直"/>
<Button
android:id="@+id/not_line"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="NotLineRun"
android:text="抛物线"/>
</LinearLayout>
</RelativeLayout>
一个ImageView是一个红球,两个按键分别实现两种动画。
下面是主活动
public class MainActivity extends Activity {
private ImageView mRedBall;
private int mScreenHeight;
public int getScreenHeight(){
Display mDisplay = getWindowManager().getDefaultDisplay();
Point mPoint = new Point();
mDisplay.getSize(mPoint);
return mPoint.y;
}
public int getScreemWidth(){
Display mDisplay = getWindowManager().getDefaultDisplay();
Point mPoint = new Point();
mDisplay.getSize(mPoint);
return mPoint.x;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mRedBall = (ImageView) findViewById(R.id.red_ball);
mScreenHeight = getScreenHeight();
}
public void LineRun(View view){
//设置一个变量,大小从0到屏幕长度
ValueAnimator animator = ValueAnimator.ofFloat(0,mScreenHeight-mRedBall.getHeight());
animator.setTarget(mRedBall);
animator.setDuration(2000);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//不断的改变红球的Y坐标
mRedBall.setTranslationY((Float) animation.getAnimatedValue());
}
});
}
//抛物线运动
public void NotLineRun(View view){
ValueAnimator animator = new ValueAnimator();
animator.setDuration(2000);
//设置初始值
animator.setObjectValues(new PointF(0, 0));
animator.setInterpolator(new LinearInterpolator()); //时间差值 线性变化
//自定义数值如何变化
animator.setEvaluator(new TypeEvaluator<PointF>() {
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
float x = 200 * fraction * 3;
float y = 0.5f * 200 * fraction * 3 * fraction * 3;
PointF pointF = new PointF(x, y);
return pointF;
}
});
animator.start();
//监听数值变化,不断改变X,Y坐标
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF pointF = (PointF) animation.getAnimatedValue();
mRedBall.setTranslationX(pointF.x);
mRedBall.setTranslationY(pointF.y);
}
});
}
}
animator.setInterpolator(new LinearInterpolator());
setInterpolator表示设置变化速率。LinearInterpolator为匀速效果,Accelerateinterpolator为加速效果、DecelerateInterpolator为减速效果。
这里有几种X的值:
TranslationX 控件坐标(是TranslationX坐标,和X的左标不同)
RotationX 翻转角度(和基点对比)
PivotX 基线(旋转中心的X坐标)
ScaleX 控件宽度
X 控件坐标(应该是布局文件中定义的位置坐标)
动画监听
可以在动画的不同阶段设置监听器。
比如我要删除个元素,我可能希望是个淡出的效果,但是最终还是要删掉,并不是你透明度没有了,还占着位置,所以我们需要知道动画如何结束。
public void fadeOut(View view)
{
ObjectAnimator anim = ObjectAnimator.ofFloat(mBlueBall, "alpha", 0.5f);
anim.addListener(new AnimatorListener()
{
@Override
public void onAnimationStart(Animator animation)
{
Log.e(TAG, "onAnimationStart");
}
@Override
public void onAnimationRepeat(Animator animation)
{
// TODO Auto-generated method stub
Log.e(TAG, "onAnimationRepeat");
}
@Override
public void onAnimationEnd(Animator animation)
{
Log.e(TAG, "onAnimationEnd");
ViewGroup parent = (ViewGroup) mBlueBall.getParent();
if (parent != null)
parent.removeView(mBlueBall);
}
@Override
public void onAnimationCancel(Animator animation)
{
// TODO Auto-generated method stub
Log.e(TAG, "onAnimationCancel");
}
});
anim.start();
}
3、多动画的运行次序
//多动画一起执行
public void togetherRun(View view)
{
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",
1.0f, 2f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",
1.0f, 2f);
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(2000);
animSet.setInterpolator(new LinearInterpolator());
//两个动画同时执行
animSet.playTogether(anim1, anim2); //一起执行
animSet.start();
}
public void playWithAfter(View view)
{
float cx = mBlueBall.getX();
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",
1.0f, 2f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",
1.0f, 2f);
ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall,
"x", cx , 0f);
ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall,
"x", cx);
/**
* anim1,anim2,anim3同时执行
* anim4接着执行
*/
AnimatorSet animSet = new AnimatorSet();
animSet.play(anim1).with(anim2);
animSet.play(anim2).with(anim3);
animSet.play(anim4).after(anim3);
animSet.setDuration(1000);
animSet.start();
}
第一:使用playTogether两个动画同时执行,当然还有playSequentially依次执行~~
第二:如果我们有一堆动画,如何使用代码控制顺序,比如1,2同时;3在2后面;4在1之前等~就是效果2了
有一点注意:animSet.play().with();也是支持链式编程的,但是不要想着狂点,比如 animSet.play(anim1).with(anim2).before(anim3).before(anim5); 这样是不行的,系统不会根据你写的这一长串来决定先后的顺序,所以按照上面例子的写法,多写几行。