栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android

动画

文章目录

动画

1. 补间动画

1.1 简介1.2 基本使用1.3 特殊场景使用1.4 高级使用 2. 插值器

2.1 基本介绍2.2 自定义插值器 3. 估值器

3.1 自定义估值器 4. 属性动画

4.1 ValueAnimator4.2 ValueAnimator实例说明4.3 ObjectAniamtor4.4 ObjectAnimator实例说明 5. 属性动画使用技巧

5.1 组合动画5.2 快捷使用5.3 监听动画5.4 动画适配器
Android动画分类

补间动画:提供开始结束数值和动画时间,系统自动生成中间动画逐帧动画:快速播放图片形成动画属性动画:通过不断修改控件属性形成动画效果 1. 补间动画 1.1 简介

分为平移translate、缩放scale、旋转rotate和透明度alpha

特点

优点:简单、方便缺点:仅仅控制整体效果,没法控制属性

使用场景

常规动画效果特殊应用场景:

Activity切换效果Fragment切换效果ViewGroup中子元素出场效果 1.2 基本使用

xml方式

    在res/anim中创建动画效果xml文件


    Animation anim = AnimationUtils.loadAnimation(context, 动画文件)实现动画的控件.startAnimation(anim)

Java方式

    实例相应的类平移TranslateAnimation、旋转RotateAnimation、缩放ScaleAnimation、透明度AlphaAnimation,其构造方法参数对应其标签的特有属性其他设置,比如anim.setDuration(3000)实现动画的控件.startAnimation(anim)
1.3 特殊场景使用

使用系统封装的动画效果

// Activity使用
public void onCreate(Bundle savedInstanceState) {
    //							   淡入			  淡出
    //								↓				↓
    overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
    super.onCreate(savedInstanceState);
}
public void finish() {
    super.finish();
    overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
}

// Fragment使用
FragmentTransaction ft = mFragmentManager.beginTransaction();
ft.setTransition(FragmentTransaction.系统预设);
	// TRANSIT_NONE	无动画
	// TRANSIT_FRAGMNET_OPEN 标准打开动画效果
	// TRANSIT_FRAGMNET_CLOSE 标砖关闭动画效果
ft.setCustomAnimations(R.anim.in_from_right, R.anim.out_to_left); // 自定义动画

注意:进入退出页面,一个需要动画、另一个不需要动画,也必须设置时间相同的、没有任何变化的动画,否则会出现黑屏

自定义效果 创建一个动画xml文件,然后如上使用

ViewGroup子元素动画

xml设置

    设置子元素动画设置View Group动画文件

    为ViewGroup指定android:layoutAniamtion属性

Java设置

    加载子元素出场动画LayoutAnimationController controller = new LayoutAnimationController(anim)设置属性,比如controller.setDelay(0.5f)加载动画的Viewgroup.setLayoutAnimation(controller)
1.4 高级使用

组合动画

xml:使用包裹多个动画标签实现,set中可以设置公共属性Java:将其他动画类实例添加到AnimationSet类实例中(addAnimation方法) 2. 插值器 2.1 基本介绍

设置属性值从初始值过度到结束之的变化规律(匀速、加速、减速等),实现非线性动画效果

内置插值器

作用资源IDJava类
加速@android:anim/accelerate_interpolatorAccelerateInterpolator
快速完成,超出在回到结束样式…overshoot…OvershootInterpolator
加速 -> 减速…accelerate_decelerate…AccelerateDecelerateInterpolator
先退后在加速前进…anticipate…AnticipateInterpolator
先退后在加速前进,超过终点再回到重点…anticipate_overshoot…AnticipateOvershootInterpolator
最后阶段弹球效果…bounce…BounceInterpolator
减速…decelerate…DecelerateInterpolator
匀速…linear…LinearInterpolator
周期运动…cycle…CycleInterpolator
2.2 自定义插值器

根据动画进度计算出当前属性值改变的百分比

实现Interpolator或TimeInterpolater接口,重写getInterpolation()方法属性动画实现TimeInterpolater,用于兼容Interpolator接口,使得过去Interpolator实现列都可以直接用在属性动画中

public interface Interpolator {
    float getInterpolator(float input) {
        // input 变化范围(0~1),随动画进度均匀变化,开始为0,结束为1
        return xxx;	// 返回值用于估值器继续计算fraction值
    }
}
// LinearInterpolator
return input;
// AccelerateDecelerateInterpolator
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
3. 估值器

设置属性值从开始值过度到结束值的变化具体数值

系统内置估值器

Intevaluator 以整型的形式进行过度Floatevaluator 以浮点型的形式进行过度Argbevaluator 以Argb类型的形式进行过度 3.1 自定义估值器

实现Typeevaluator接口,重写evaluate()方法

public class Objectevaluator implements Typeevaluator{  

    @Override  
    public Object evaluate(float fraction, Object startValue, Object endValue) {  
        // 参数说明
        // fraction:表示动画完成度(根据它来计算当前动画的值),也是插值器getInterpolation()的返回值
        // startValue:动画的初始值
        // endValue:动画的结束值
        
        // 返回对象动画过渡逻辑计算后的值
        // 即赋给动画属性的具体数值
        return value;  
    } 
4. 属性动画

视图动画存在缺陷:作用对象局限(View)、仅改变视觉效果、动画效果单一

属性动画

可以作用于任意Java对象可以自定义动画效果

工作原理:不对对属性值进行修改,不断将值赋给对象属性

主要通过ValueAnimator和ObjectAnimator类实现

4.1 ValueAnimator

通过不断控制值的变化,再不断手动赋给对象属性

ValueAnimator.ofInt(int value) 内置估值器IntevaluatorValueAnimator.ofFloat(float value) 内置估值器FloatevaluatorValueAnimator.ofObject(int value)

xml设置

    在res/animator创建动画xml文件
      使用标签特有属性:valueFrom、valueTo、valueType(变化值类型,floatType & intType)公共属性和补间动画中相同
    Animator animator = AnimatorInflater.loadAnimator(context, 动画xml)animator.setTarget(view) 设置动画对象animator.start()

Java设置

    ValueAniamtor anim = ValueAnimator.toInt(0, 3)
      public static ValueAnimator ofInt(int... values)
    设置其他属性将改变的值手动赋值给对象的属性值,通过动画的更新监听器
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    public void onAnimaionUpdate(ValueAnimator animation) {
        int currentValue = (Integer) animation.getAnimatedValue();
        // 以按钮宽度改变为例
        btn.getLayoutParams().width = currentValue;
        btn.requestLayout();	// 刷新视图,重新绘制
    }
})
    anim.start()

ValueAnimator.ofObject()

ValueAnimator anim = ValueAnimator.ofObject(new 自定义估值器, object1, object2)

需要自定义估值器

4.2 ValueAnimator实例说明

实现一个圆形从左上角移动到右下角

// Point.kt
class Point(val x: Float, val y: Float);

自定义估值器

// Pointevaluator.kt
class Pointevaluator : Typeevaluator {
    override fun evaluate(fraction: Float, start: Point, end: Point): Point {
        val x = start.x + fraction * (end.x - start.x)
        val y = start.y + fraction * (end.y - start.y)
        
        val point = Point(x, y)
        return point
    }

}

将属性动画作用到自定义View当中

public class MyView extends View {
    public static final float RADIUS = 70f;
    private Point currentPoint;
    private Paint mPaint;

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.BLUE);
    }

    protected void onDraw(Canvas canvas) {
        if (currentPoint == null) {
            currentPoint = new Point(RADIUS, RADIUS);
            float x = currentPoint.getX();
            float y = currentPoint.getY();
            canvas.drawCircle(x, y, RADIUS, mPaint);
            // 创建开始动画对象点和结束动画对象点
            Point start = new Point(RADIUS, RADIUS);
            Point end = new Point(700f, 1000f);
            // 创建动画对象,设置初始值和结束值
            ValueAnimator anim = ValueAnimator.ofObject(new Pointevaluator(), start, end);
            anim.setDuration(5000);
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                public void onAnimationUpdate(ValueAnimator animation) {
                    currentPoint = (Point) animation.getAnimatedValue();
                    // 重新绘制
                    invalidate();
                }
            });
            anim.start();
        } else {
            float x = currentPoint.getX();
            float y = currentPoint.getY();
            canvas.drawCircle(x, y, RADIUS, mPaint);
        }
    }
}

将自定义View放到布局中

ofObject()本质上还是操作值,只不过采用将多个值封装到一个对象中,对多个值一起操作

与ObjectAnimator区别

ValueAnimator不断改变值,手动赋值给对象的属性从而实现动画效果,间接对对象属性操作ObjectAnimator不断改变值,自动赋值给对象的属性从而实现动画效果,直接对对象属性操作 4.3 ObjectAniamtor

继承自ValueAnimator

Java设置

    ObjectAnimator anim = ObjectAnimator.ofFloat(object, proprty, values)
      Object object 操作对象String property 操纵的对象属性float… values 动画初始值 & 结束值ofObject还有一个参数是自定义估值器
    其他设置anim.start()

xml设置

    在res/animtor创建动画xml文件
      使用标签相关属性:valueFrom、valueTo、valueType、propertyName(对象变化属性名称)
    Animator anim = AnimatorInflater.loadAnimator(context, 动画xml文件)anim.setTraget(动画对象)anim.start()

第二个参数作用是让ObjectAnimator类根据传入属性名去寻找改对象对应属性名的set()、get()方法,从而进行对象属性值的赋值

原理解析

@Override  
public void start() {  
    AnimationHandler handler = sAnimationHandler.get();  

    ...
    
    super.start();  
   // 调用父类的start()
   // 因为ObjectAnimator类继承ValueAnimator类,所以调用的是ValueAnimator的star()
   // 经过层层调用,最终会调用到 自动赋值给对象属性值的方法 ->关注1
}  


// 步骤1:初始化动画值
private void setupValue(Object target, Keyframe kf) {  
    if (mProperty != null) {  
        kf.setValue(mProperty.get(target));  
        // 初始化时,如果属性的初始值没有提供,则调用属性的get()进行取值
    }  
        kf.setValue(mGetter.invoke(target));   
    }  
}  

// 步骤2:更新动画值
// 当动画下一帧来时(即动画更新的时候),setAnimatedValue()都会被调用
void setAnimatedValue(Object target) {  
    if (mProperty != null) {  
        mProperty.set(target, getAnimatedValue());  
        // 内部调用对象该属性的set(),从而将新的属性值设置给对象属性
    }   
}  

采用ObjectAnimator实现动画效果,需要操作的对象就必须有该属性的get、set方法

4.4 ObjectAnimator实例说明

实现一个圆形颜色渐变

设置对象类谁能够的set、get方法

直接法:继承原始类,直接加上该属性的get、set方法

该对象本身没有这个属性时,采用直接法 间接法:包赚原始动画对象,间接给对象加上该属性的get、set方法,即用一个类来包装原始对象

当属性存在set方法但set方法无法带来预期的UI变化时使用间接法 5. 属性动画使用技巧 5.1 组合动画

使用AnimatorSet类

play(anim) 播放当前动画after(delay) 将现有动画延迟x毫秒执行with(anim) 将现有动画和传入动画同时执行after(anim) 将现有动画插入到传入动画之后执行before(anim) …

xml设置:前面讲解过

5.2 快捷使用

ViewPropertyAnimator类

View.animate().xxx().xxx();
// ViewPropertyAnimator的功能建立在animate()上
// 调用animate()方法返回值是一个ViewPropertyAnimator对象,之后的调用的所有方法都是通过该实例完成
// 调用该实例的各种方法来实现动画效果
// ViewPropertyAnimator所有接口方法都使用连缀语法来设计,每个方法的返回值都是它自身的实例
// 因此调用完一个方法后可直接连缀调用另一方法,即可通过一行代码就完成所有动画效果
View.animate().alpha(0f).setDuration(5000).setInterpolator(new BounceInterpolator());
5.3 监听动画

Animation类监听动画开始 / 结束 / 重复时的操作addListener()中设置 5.4 动画适配器

解决并不需要监听动画所有时刻的问题,解决实现接口繁琐问题

//							动画适配器
//								↓
anim.addListener(new AnimatorListenerAdapter() {
    public void onAnimationStart(Animator animation) {
        // 只需要重写自己需要的动画时刻
    }
})
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/782743.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号