Android动画及图片的缩放和旋转分析

你猜 阅读:175 2020-04-07 15:16:03 评论:0

Android动画有2种,一种是Tween Animation,另一种是Frame Animation

  Tween动画是对视图对象中的内容进行一系列简单的转换,比如位置的移动,大小的缩放,旋转,透明度得变化等等。Tween动画可以写到一个xml文件中,就像定义布局文件一样,当然,也可以写到android代码中,不过推荐写到xml文件中,因为它具备的阅读性,可重用性大大超过了硬编码。xml文件放在工程的res/anim目录中,这个目录中要包含一个根元素,可以是<scale>,<translate>,<alpha>或者<rotate>,当然,这些元素都可以放到一个动画集合<set>中,默认情况下,所有的动画指令都是同时发生的,为了让他们按顺序发生,需要设置一个特殊的属性startOffset。下面定义了一个动画的集合:

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shareInterpolator="false"> 
    <scale 
        android:duration="7000" 
        android:fillAfter="false" 
        android:fromXScale="1.0" 
        android:fromYScale="1.0" 
        android:interpolator="@android:anim/accelerate_decelerate_interpolator" 
        android:pivotX="50%" 
        android:pivotY="50%" 
        android:toXScale="1.4" 
        android:toYScale="0.6"></scale> 
    <set android:shareInterpolator="@android:anim/decelerate_interpolator"> 
        <scale 
            android:duration="4000" 
            android:fillBefore="false" 
            android:fromXScale="1.4" 
            android:fromYScale="0.6" 
            android:pivotX="50%" 
            android:pivotY="50%" 
            android:startOffset="7000" 
            android:toXScale="0.0" 
            android:toYScale="0.0"></scale> 
        <rotate 
            android:duration="4000" 
            android:fromDegrees="0" 
            android:pivotX="50%" 
            android:pivotY="50%" 
            android:startOffset="7000" 
            android:toDegrees="-45"></rotate> 
 
    </set> 
</set>

 

这里解释一下这段代码的作用:

首先是一个动画的集合set,在这个set中有一个属性shareInterpolater,如果设置为true,则这个集合下面所有的子元素都享有同样的interpolater,api上面是这样说的:

android:shareInterpolator
Boolean. "true" if you want to share the same interpolator among all child elements.
紧跟在这个集合后面的是一个缩放动画,里面有一些个属性,下面一一介绍:
android:interpolator属性:这是值定一个动画的插入器,有一些常用的插入器:accelerate_decelerate_interpolator加速-减速动画插入器,顾名思义,就是先加速后减速,accelerate_interpolator加速动画插入器,decelerate_interpolator减速动画插入器
android:fromXScale属性为动画起始时,x坐标上的伸缩尺寸
android:toXScal属性为动画结束时,x坐标上的伸缩尺寸
android:fromYScale属性为动画起始时,y坐标上的伸缩尺寸
android:toYScale属性为动画结束时,y坐标上的伸缩尺寸
关于伸缩尺寸这里还要罗嗦一下:
也就是上面的四个属性的值:0.0表示收缩到没有,1.0表示正常无收缩,值小于1.0表示收缩,值大于1.0表示放大。
android:fillAfter属性当设置为true时,该动画转化在动画结束后被应用,同理还有android:fillBefore属性,当设置为true时,该动画转化在动画开始前被应用
android:duration属性表示动画持续的时间,单为时毫秒
android:pivotX属性为动画相对于x坐标的起始位置
android:pivotY属性为动画相对于y坐标的起始位置
这2个属性有不同的格式表示,如值为50,表示是相对于父类的50%,如值为50%,表示是相对于自己的50%
这里的50%表示相对于自身x,y坐标上的中点位置
紧跟着是一个动画集合,里面有缩放和旋转,这个集合的interpolater为减速动画插入器
这里的缩放里面还有一个属性,android:startOffset属性是设置动画开始的时间,这里设置700是表示700毫秒之后开始,也就是第一个缩放完成之后开始。
旋转里面的属性跟scale里面的都差不多,只是旋转讲究的角度。
android:fromDegrees属性表示动画起始时的角度
android:toDegrees属性表示动画结束时旋转的角度,可以大于360度
动画文件写好了之后,我们就可以在代码中调用这个动画了,先写一个布局文件,布局文件里面有一个ImageView,然后我们让这个ImageView做动画。
布局文件如下:
<?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:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="com.example.lj.chapter8.MainActivity"> 
 
    <TextView 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="This is a rotate animation" 
        android:id="@+id/textView" 
        android:layout_centerVertical="true" 
        android:layout_centerHorizontal="true" /> 
</RelativeLayout>
然后我们让这个图片按照我们xml中指定的动画运动:
代码:
package com.example.lj.chapter8; 
 
import android.graphics.drawable.AnimationDrawable; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.MotionEvent; 
import android.view.animation.Animation; 
import android.view.animation.AnimationUtils; 
import android.widget.ImageView; 
import android.widget.TextView; 
 
public class MainActivity extends AppCompatActivity { 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
 
        TextView textView= (TextView) findViewById(R.id.textView); 
        Animation animation= AnimationUtils.loadAnimation(this,R.anim.text_animation); 
        textView.startAnimation(animation); 
    } 
}
/******************************************/
Frame Animation也就是帧动画,可以使用AndroidDrawable来负责帧动画,同样它可以在xml文件中很方便的列出所有的帧,按照周期去执行每帧动画,下面是一个定义帧动画的例子:
<?xml version="1.0" encoding="utf-8"?> 
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" 
    android:oneshot="false"> 
    <item 
        android:drawable="@drawable/mtlogo0" 
        android:duration="200"></item> 
    <item 
        android:drawable="@drawable/mtlogo1" 
        android:duration="200"></item> 
    <item 
        android:drawable="@drawable/mtlogo2" 
        android:duration="200"></item> 
    <item 
        android:drawable="@drawable/mtlogo3" 
        android:duration="200"></item> 
    <item 
        android:drawable="@drawable/mtlogo4" 
        android:duration="200"></item> 
    <item 
        android:drawable="@drawable/mtlogo5" 
        android:duration="200"></item> 
    <item 
        android:drawable="@drawable/mtlogo6" 
        android:duration="200"></item> 
    <item 
        android:drawable="@drawable/mtlogo7" 
        android:duration="200"></item> 
    <item 
        android:drawable="@drawable/mtlogo8" 
        android:duration="200"></item> 
    <item 
        android:drawable="@drawable/mtlogo9" 
        android:duration="200"></item> 
</animation-list>

 

这里定义了帧的名字和每帧的持续时间.
这里有3帧,通过设置android:oneshot属性为true,它将会在最后一帧停下来,如果设置为false,它将会循环播放,可以把它添加到一个背景中,让他播放,具体代码如下:
布局文件:
<?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:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="com.example.lj.chapter8.MainActivity"> 
 
    <ImageView 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:id="@+id/imageView" 
        android:layout_alignParentTop="true" 
        android:layout_centerHorizontal="true" 
        android:layout_marginTop="97dp" /> 
</RelativeLayout>
在代码里面设置imageview的背景图片,然后做动画:
package com.example.lj.chapter8; 
 
import android.graphics.drawable.AnimationDrawable; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.MotionEvent; 
import android.view.animation.Animation; 
import android.view.animation.AnimationUtils; 
import android.widget.ImageView; 
import android.widget.TextView; 
 
public class MainActivity extends AppCompatActivity { 
    AnimationDrawable animationDrawable; 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
 
        ImageView imageView = (ImageView) findViewById(R.id.imageView); 
        imageView.setBackgroundResource(R.drawable.logo_animation); 
        animationDrawable = (AnimationDrawable) imageView.getBackground(); 
    } 
 
    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
        if (event.getAction() == MotionEvent.ACTION_DOWN) { 
            animationDrawable.start(); 
            return true; 
        } else { 
            return super.onTouchEvent(event); 
        } 
    } 
}

 

这里需要注意的是:AnimationDrawable在调用OnCreate的过程中不能调用start(),这是因为AnimationDrawable不能在不完全的窗口上运行,需要一个操作来触发,如果你想立即播放动画,没有必要的交互,你可以在onWindowFocusChanged()方法中调用它,这样它将会成为窗口焦点。
下面说说图片的缩放和旋转:
这里我就写的比较简单了,代码里面的注释很详细,可以慢慢看。
package com.test.shang; 
 
import android.app.Activity; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Matrix; 
import android.graphics.drawable.BitmapDrawable; 
import android.os.Bundle; 
import android.widget.ImageView; 
import android.widget.ImageView.ScaleType; 
import android.widget.LinearLayout; 
import android.widget.LinearLayout.LayoutParams; 
 
public class BitmapTest extends Activity { 
 
@Override 
protected void onCreate (Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setTitle("测试图片的缩放和旋转"); 
LinearLayout layout = new LinearLayout(this); 
 
//加载需要操作的图片,这里是机器猫的图片 
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(), R.drawable.duola); 
 
//获取这个图片的宽和高 
int width = bitmapOrg.getWidth(); 
int height = bitmapOrg.getHeight(); 
 
//定义预转换成的图片的宽和高 
int newWidth = 200; 
int newHight = 200; 
 
//计算缩放率,新尺寸除原尺寸 
float scaleWidth = (float)newWidth/width; 
float scaleHeight = (float)newHight/height; 
 
//创建操作图片用的matrix对象 
Matrix matrix = new Matrix(); 
 
//缩放图片动作 
matrix.postScale(scaleWidth, scaleHeight); 
 
//旋转图片动作 
matrix.postRotate(45); 
 
//创建新的图片 
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, width, height, matrix, true); 
 
//将上面创建的Bitmap转换成Drawable对象,使得其可以使用在imageView,imageButton上。 
BitmapDrawable bitmapDrawable = new BitmapDrawable(resizedBitmap); 
 
//创建一个ImageView 
ImageView iv = new ImageView(this); 
 
//将imageView的图片设置为上面转换的图片 
iv.setImageDrawable(bitmapDrawable); 
 
//将图片居中显示 
iv.setScaleType(ScaleType.CENTER); 
 
//将imageView添加到布局模板中 
layout.addView(iv, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 
 
//设置为本activity的模板 
setContentView(layout); 
} 
}

 

下面是效果预览:
标签:安卓Android
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

发表评论
搜索
排行榜
关注我们

扫一扫关注我们,了解最新精彩内容