Android App开发动画特效中插值器和估值器的讲解以及利用估值器实现弹幕动画实战(附源码和演示视频 可直接使用)

news2024/11/17 21:50:25

需要图片集和源码请点赞关注收藏后评论区留言~~~

一、插值器和估值器

插值器用来控制属性值的变化速率,也可以理解为动画播放的速度,默认是先加速再减速。若要给动画播放指定某种速率形式,调用setInterpolator方法设置对应的插值器实现类即可,无论是补间动画,集合动画,属性动画还是属性动画组合,都可以设置插值器。

估值器专用于属性动画,主要描述该属性的数值变化要采用什么单位,比如整数类型的渐变数值要取整,颜色的渐变数值为ARGB格式的颜色对象,矩形的渐变数值为Rect对象等等。要给属性动画设置估值器,调用属性动画对象的setEvaluator方法即可。

一般情况下 无须单独设置属性动画的估值器,使用系统默认的估值器即可。

演示效果如下 可以在下拉框中选择不同的演示效果

演示视频已上传至个人主页  有需要可自行前往观看

插值器和估值器演示

 

 

 代码如下

Java类

package com.example.animation;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ArgbEvaluator;
import android.animation.FloatEvaluator;
import android.animation.ObjectAnimator;
import android.animation.RectEvaluator;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.TextView;

public class InterpolatorActivity extends AppCompatActivity implements AnimatorListener {
    private TextView tv_interpolator; // 声明一个图像视图对象
    private ObjectAnimator animAcce, animDece, animLinear, animBounce; // 声明四个属性动画对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_interpolator);
        tv_interpolator = findViewById(R.id.tv_interpolator);
        initObjectAnim(); // 初始化属性动画
        initInterpolatorSpinner(); // 初始化插值器类型的下拉框
    }

    // 初始化插值器类型的下拉框
    private void initInterpolatorSpinner() {
        ArrayAdapter<String> interpolatorAdapter = new ArrayAdapter<>(this,
                R.layout.item_select, interpolatorArray);
        Spinner sp_interpolator = findViewById(R.id.sp_interpolator);
        sp_interpolator.setPrompt("请选择插值器类型");
        sp_interpolator.setAdapter(interpolatorAdapter);
        sp_interpolator.setOnItemSelectedListener(new InterpolatorSelectedListener());
        sp_interpolator.setSelection(0);
    }

    private String[] interpolatorArray = {
            "背景色+加速插值器+颜色估值器", "旋转+减速插值器+浮点型估值器",
            "裁剪+匀速插值器+矩形估值器", "文字大小+震荡插值器+浮点型估值器"};

    class InterpolatorSelectedListener implements OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
            showInterpolator(arg2); // 根据插值器类型展示属性动画
        }

        public void onNothingSelected(AdapterView<?> arg0) {}
    }

    // 初始化属性动画
    private void initObjectAnim() {
        // 构造一个在背景色上变化的属性动画
        animAcce = ObjectAnimator.ofInt(tv_interpolator, "backgroundColor", Color.RED, Color.GRAY);
        // 给属性动画设置加速插值器
        animAcce.setInterpolator(new AccelerateInterpolator());
        // 给属性动画设置颜色估值器
        animAcce.setEvaluator(new ArgbEvaluator());
        // 构造一个围绕中心点旋转的属性动画
        animDece = ObjectAnimator.ofFloat(tv_interpolator, "rotation", 0f, 360f);
        // 给属性动画设置减速插值器
        animDece.setInterpolator(new DecelerateInterpolator());
        // 给属性动画设置浮点型估值器
        animDece.setEvaluator(new FloatEvaluator());
        // 构造一个在文字大小上变化的属性动画
        animBounce = ObjectAnimator.ofFloat(tv_interpolator, "textSize", 20f, 60f);
        // 给属性动画设置震荡插值器
        animBounce.setInterpolator(new BounceInterpolator());
        // 给属性动画设置浮点型估值器
        animBounce.setEvaluator(new FloatEvaluator());
    }

    // 根据插值器类型展示属性动画
    private void showInterpolator(int type) {
        ObjectAnimator anim = null;
        if (type == 0) { // 背景色+加速插值器+颜色估值器
            anim = animAcce;
        } else if (type == 1) { // 旋转+减速插值器+浮点型估值器
            anim = animDece;
        } else if (type == 2) { // 裁剪+匀速插值器+矩形估值器
            int width = tv_interpolator.getWidth();
            int height = tv_interpolator.getHeight();
            // 构造一个从四周向中间裁剪的属性动画,同时指定了矩形估值器RectEvaluator
            animLinear = ObjectAnimator.ofObject(tv_interpolator, "clipBounds",
                    new RectEvaluator(), new Rect(0, 0, width, height),
                    new Rect(width / 3, height / 3, width / 3 * 2, height / 3 * 2),
                    new Rect(0, 0, width, height));
            // 给属性动画设置匀速插值器
            animLinear.setInterpolator(new LinearInterpolator());
            anim = animLinear;
        } else if (type == 3) { // 文字大小+震荡插值器+浮点型估值器
            anim = animBounce;
            // 给属性动画添加动画事件监听器。目的是在动画结束时恢复文字大小
            anim.addListener(this);
        }
        anim.setDuration(2000); // 设置动画的播放时长
        anim.start(); // 开始播放属性动画
    }

    // 在属性动画开始播放时触发
    @Override
    public void onAnimationStart(Animator animation) {}

    // 在属性动画结束播放时触发
    @Override
    public void onAnimationEnd(Animator animation) {
        if (animation.equals(animBounce)) { // 震荡动画
            // 构造一个在文字大小上变化的属性动画
            ObjectAnimator anim = ObjectAnimator.ofFloat(tv_interpolator, "textSize", 60f, 20f);
            // 给属性动画设置震荡插值器
            anim.setInterpolator(new BounceInterpolator());
            // 给属性动画设置浮点型估值器
            anim.setEvaluator(new FloatEvaluator());
            anim.setDuration(2000); // 设置动画的播放时长
            anim.start(); // 开始播放属性动画
        }
    }

    // 在属性动画取消播放时触发
    @Override
    public void onAnimationCancel(Animator animation) {}

    // 在属性动画重复播放时触发
    @Override
    public void onAnimationRepeat(Animator animation) {}

}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="插值器类型:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <Spinner
            android:id="@+id/sp_interpolator"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="5"
            android:spinnerMode="dialog" />

    </LinearLayout>

    <TextView
        android:id="@+id/tv_interpolator"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:gravity="center"
        android:background="@color/gold"
        android:text="看看插值器的效果是什么"
        android:textColor="@color/black"
        android:textSize="20sp" />

</LinearLayout>

二、利用估值器实现弹幕动画

弹幕想必大家都不陌生,虽然弹幕效果可以使用平移动画实现,但是平移动画比较单调,而且只能控制位移不能控制速率,文字大小,文字颜色等要素,想同时操纵视图的多种属性要素的时候,需要采用属性动画加以实现 分为以下三步

1:定义一个间距估值器

2:调用ValueAnimator类的ofObject方法 

3:调用属性动画对象的addUpdateListenter方法设置刷新监听器

效果如下 点击添加评论按钮就会添加弹幕数量

演示视频已上传至个人主页 有需要可自行观看

弹幕动画

 

 

 

 代码如下

Java类

package com.example.animation;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import com.example.animation.widget.BarrageView;

import java.util.Random;

public class BarrageActivity extends AppCompatActivity {
    private String[] mCommentArray = {"武夷山", "仙霞岭", "阿里山", "白云山", "九华山",
            "长白山", "峨眉山", "五台山", "太白山", "昆仑山",
            "六盘山", "乌蒙山", "井冈山", "武当山", "普陀山",
            "祁连山", "贺兰山", "太行山", "双鸭山", "五指山"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_barrage);
        BarrageView bv_comment = findViewById(R.id.bv_comment);
        findViewById(R.id.btn_comment).setOnClickListener(v -> {
            String comment = mCommentArray[new Random().nextInt(20)];
            bv_comment.addComment(comment); // 给弹幕视图添加评论
        });
    }
}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.example.animation.widget.BarrageView
        android:id="@+id/bv_comment"
        android:layout_width="match_parent"
        android:layout_height="200dp" />

    <Button
        android:id="@+id/btn_comment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="添加评论"
        android:textColor="@color/black"
        android:textSize="17sp" />

</LinearLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/22469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Boot 分离配置文件的 N 种方式

今天聊一个小伙伴在星球上的提问&#xff1a; 问题不难&#xff0c;解决方案也有很多&#xff0c;因此我决定撸一篇文章和大家仔细说说这个问题。 1. 配置文件位置 首先小伙伴们要明白&#xff0c;Spring Boot 默认加载的配置文件是 application.properties 或者 application…

【云计算大数据_牛客_Hbase】选择/判断——Hbase

1.Hive 1.下面关于Hive metastore的三种模式的描述错误的是() Derby方式是内嵌的方式,也是默认的启动方式,一般用于单元测试local模式中,使用MySQL 本地部署实现metastoreremote模式为远程MySQLDerby方式在同一时间只能有多个进程连接使用数据库 2. 百度文库 2、代码sel…

Android App开发中集合动画和属性动画的讲解及实战演示(附源码 简单易懂 可直接使用)

需要图片集和源码请点赞关注收藏后评论区留言~~~ 一、集合动画 有时一个动画效果会加入多种动画&#xff0c;比如一个旋转一边缩放&#xff0c;这时便会用到集合动画AnimationSet把几个补间动画组装起来&#xff0c;实现让某视图同时呈现多种动画的效果 因为集合动画和补间动…

Jetson Orin使用Yolo5开源数据集训练模型检测口罩

软硬件环境&#xff1a; 乌班图 20.04 64位蟒蛇与 3.8.10英伟AGX Orin库达11.4PyTorch1.12YOLOv5-6.1感谢开源数据集下载地址 正常都是自己收集完了训练&#xff0c;今天就省略这个步骤了。 如果想自己制作看下面的流程。 软硬件环境搭建教程链接 刷机的话使用官方教程或者…

DNS协议

DNS服务器 人类更喜欢记忆主机名&#xff0c;而路由器更喜欢定长的、有结构层次的IP地址&#xff0c;DNS应运而生&#xff1a;DNS能进行主机名到IP地址转换的目录服务。 DSN是&#xff1a; &#xff08;1&#xff09;一个由分层的DNS服务器&#xff08;DNS server&#xff09;实…

元数据管理-解决方案调研二:元数据管理解决方案——Saas/内部解决方案(2)

Saas/内部解决方案 2.5、Azure Purview 地址&#xff1a;Azure Purview - Unified Data Governance Solution | Microsoft Azure 特点&#xff1a; 1、创建跨整个数据资产的统一数据地图&#xff0c;为有效的数据治理和使用奠定基础 1.1、自动化和管理混合源的元数据&#xf…

重打包实现frida持久化 笔记

修改Dex Using Frida on Android without root 修改so [翻译]在未root的设备上使用frida 2个方法本质都是通过重打包让app自己加载frida-gadget.so &#xff08;但感觉没有谁家app会让人轻易重打包吧。。。&#xff09; apktool d org.telegram.messenger_4.8.4-12207.apk -r…

Tomcat配置SSL证书别名tomcat无法识别密钥项

Tomcat配置SSL证书一直启动失败&#xff0c;主要问题如下&#xff1a; java.io.IOException: Alias name tomcat does not identify a key entry at org.apache.tomcat.util.net.jsse.JSSEUtil.getKeyManagers(JSSEUtil.java:280) 别名tomcat无法识别密钥项&#xff0c;是因…

STM32单片机远程控制大棚种植系统

想要更多项目私wo!!! 一、电路设计 ​​​​​系统示意图硬件系统 系统由五个单片机系统组成的&#xff0c;其中51系列的单片机四个&#xff0c;STM32F407单片机一个&#xff0c;各个子系统之间通过NRF24L01无线模块进行通信。 系统硬件组成框图​​​​主控制板主要由STM32…

【VuePress2.0】快速开始(不用)

文章目录VuePress2.x1.1 安装安装VuePress2.x&#xff08;手动安装&#xff09;1.2 VuePress2.x 基本操作VuePress2.x主题2.1 安装VuePress2.x主题&#xff08;yarn&#xff09;2.2 报错解决&#xff08;没效果&#xff0c;不用看&#xff09;2.3 VuePress2.x主题 基本操作VueP…

Java基础深化和提高-------IO流

目录 IO流技术介绍 什么是IO 什么是数据源 流的概念 第一个简单的IO流程序 IO流的经典写法 IO流新语法经典写法 Java中流的概念细分 按流的方向分类&#xff1a; 按处理的数据单元分类&#xff1a; 按处理对象不同分类&#xff1a; Java中IO流类的体系 Java中IO的四大抽象…

CleanMyMac X真正好用的Mac电脑系统优化软件应用工具

最用户友好的Mac问题修复程序。删除系统垃圾、不需要的应用程序和恶意软件&#xff0c;并调整您的Mac以获得最高速度。对于速度较慢的计算机&#xff0c;CleanMyMac就能立即使用。 CleanMyMac2023之所以能够获得众多Mac的老用户们的喜爱&#xff0c;是因为其有着非常强大功能提…

数据可视化之大数据平台可视化

一 前言 在简化数据量和降低大数据应用的复杂性中&#xff0c;大数据分析发挥着关键的作用。可视化是其中一个重要的途径&#xff0c;它能够帮助大数据获得完整的数据视图并挖掘数据的价值。大数据分析和可视化应该无缝连接&#xff0c;这样才能在大数据应用中发挥最大的功效。…

nodejs+mysql航空飞机票销售酒店预订系统vue

(1)对机票预订管理系统进行需求分析、确定所需要的模块&#xff1b;建立数据字典、数据流等&#xff1b;书写可行性分析和需求分析说明书。 (2)对机票预订管理系统进行概要设计&#xff1a;建立软件体系结构&#xff0c;画出用例图、E-R图等&#xff1b;书写数据要求说明书和各…

【雷达通信】阵列信号处理(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

聊聊Go里面的闭包

以前写 Java 的时候&#xff0c;听到前端同学谈论闭包&#xff0c;觉得甚是新奇&#xff0c;后面自己写了一小段时间 JS&#xff0c;虽只学到皮毛&#xff0c;也大概了解到闭包的概念&#xff0c;现在工作常用语言是 Go&#xff0c;很多优雅的代码中总是有闭包的身影&#xff0…

嵌入式图形开发框架Qt——让牙科手术开始迈入机器人时代

Neocis软件工程总监,Jim Tieman&#xff1a; “我们Neocis是一家致力于提高科医生能力和促进病人护理的牙科机器人公司。之前我们有一个Microsoft Foundations Class (MFC)的应用程序&#xff0c;由于现在团队擅长MFC开发的技术员并不多&#xff0c;维护起来也很费劲。之前这个…

AST 初探深浅,代码还能这样玩?

AST 听起来好像是个很新的东西&#xff0c;那么具体有什么用&#xff0c;好不好用就在这篇文章中找到答案吧~ 我们简单将这个词拆分抽象、语法、树&#xff0c;如果我们能够顺利将这个词拆分&#xff0c;那么我们也就掌握了其核心所在 抽象&#xff1a;抽象的反义词是具象&…

微信小程序|使用小程序制作一个2048小游戏

文章目录一、文章前言二、创建小程序三、功能开发一、文章前言 此文主要通过小程序实现2048游戏&#xff0c;游戏操作简单&#xff0c;容易上手。 规则&#xff1a;正常打开游戏的界面&#xff0c;会只有两个2&#xff0c;每次移动后都会出现一个2&#xff0c;数字大了之后会出…

RabbitMQ初步到精通-第八章-Java-AMQP-Client源码分析

目录 第八章-Java-AMQP-Client源码分析 1、背景 1.1 客户端介绍 1.2 看源码好处 1.3 如何看源码 2、生产者 3、消费者监听 4、创建连接 5、消费者消费 6. 总结&#xff1a; 第八章-Java-AMQP-Client源码分析 1、背景 1.1 客户端介绍 通过前面几章的学习&#xff0c;大家对…