通过使用计时器(或处理程序)更改 ImageView 中的图像来创建动画

2024-05-05

我想通过更改 ImageView 内的帧来创建一个简单的动画。我不想使用 AnimationDrawable 因为我需要在帧更改或动画停止时接收事件,以便能够向后播放、重新启动等等。

我的问题是,尽管 setImageDrawable 被调用(在主线程上),但框架实际上并没有改变事件。所以一切似乎都工作正常,除了框架没有改变(实际上只是绘制了一个框架,第一个框架)。

所以我的代码:

public class AnimatedImageView extends ImageView implements Animatable, Runnable {

    private static final String TAG = "AnimatedImageView";

    public static interface AnimationEventsListener {
        void animationDidChangeFrame(AnimatedImageView animatedImageView);

        void animationDidStop(AnimatedImageView animatedImageView);
    }

    /* frames - ress ids */
    private int[] mFrameResIds;
    /* current frame index */
    private int mCurrentFrameIdx;
    /* number of the current repeat */
    private int loopIndex;
    /* number of animation repetiotions, 0 for infinite */
    private int mNumOfRepetitions;
    /* if animation is playing */
    private boolean playing;
    /* if animation is paused */
    private boolean paused;
    /* if animation is playing backward */
    private boolean playItBackward;
    /* animation duration */
    private long mAnimationDuration;
    /* frame animation duration (mAnimationDuration / num_of_frames) */
    private long mFrameAnimationDuration;

    /* listener for animation events */
    private AnimationEventsListener mListener;

    private Handler mHandler;

    public AnimatedImageView(Context context) {
        super(context);
        setup();
    }

    public AnimatedImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setup();
    }

    public AnimatedImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setup();
    }

    private void setup() {
        mHandler = new Handler(Looper.getMainLooper());
        this.setClickable(true);
        Logger.d("MSG", "setup, thread: " + Thread.currentThread().toString());
    }


    @Override
    public void start() {
        if (playing) {
            return;
        }
        mCurrentFrameIdx = playItBackward ? mFrameResIds.length - 1 : 0;
        loopIndex = 0;
        playing = true;
        updateFrame();
    }

    @Override
    public void stop() {
        paused = true;
    }

    public void resume() {
        paused = false;
        playing = true;
        updateFrame();
    }

    @Override
    public boolean isRunning() {
        return false;
    }

    @Override
    public void run() {
        Logger.d("MSG", "run, thread: " + Thread.currentThread().toString());
        updateFrame();
    }

    public AnimationEventsListener getListener() {
        return mListener;
    }

    public void setListener(AnimationEventsListener mListener) {
        this.mListener = mListener;
    }

    public long getAnimationDuration() {
        return mAnimationDuration;
    }

    public void setAnimationDuration(long mAnimationDuration) {
        this.mAnimationDuration = mAnimationDuration;
        if (mFrameResIds != null) {
            mFrameAnimationDuration = mAnimationDuration / mFrameResIds.length;
        }
    }

    public int[] getFrameResIds() {
        return mFrameResIds;
    }

    public void setFrameResIds(int[] mFrameResIds) {
        this.mFrameResIds = mFrameResIds;
        if (mFrameResIds != null) {
            mFrameAnimationDuration = mAnimationDuration / mFrameResIds.length;
        }
    }

    private void setCurrentFrame(int frameValue) {
        mCurrentFrameIdx = frameValue;
        this.setAnimationFrame(frameValue);
    }

    private void setAnimationFrame(int animationFrame) {
        Logger.d("MSG", "setAnimationFrame: " + animationFrame);
        if (animationFrame < 0) {
            animationFrame = 0;
        }

        if (animationFrame > -1) {
            animationFrame = mFrameResIds.length - 1;
        }

        Resources resources = getResources();
        AnimatedImageView.this.setImageDrawable(resources.getDrawable(mFrameResIds[animationFrame]));
        AnimatedImageView.this.forceLayout();
//        AnimatedImageView.this.setImageBitmap(BitmapFactory.decodeResource(resources, mFrameResIds[animationFrame]));
//        this.setImageResource(mFrameResIds[animationFrame]);
        AnimatedImageView.this.invalidate();
    }

    private void updateFrame() {
        Logger.d("MSG", "updateFrame " + mCurrentFrameIdx);
        if (!playing || paused) {
            return;
        }

        playing = false;

        if (mListener != null) {
            mListener.animationDidChangeFrame(AnimatedImageView.this);
        }

        if (!playItBackward) {
            mCurrentFrameIdx++;
            if (mCurrentFrameIdx >= mFrameResIds.length) {
                loopIndex++;
                mCurrentFrameIdx = 0;
                if (mNumOfRepetitions == loopIndex) {
                    if (mListener != null) {
                        mListener.animationDidStop(AnimatedImageView.this);
                    }
                    return;
                }
            }
        } else {
            mCurrentFrameIdx--;
            if (mCurrentFrameIdx < 0) {
                loopIndex++;
                mCurrentFrameIdx = mFrameResIds.length - 1;
                if (mNumOfRepetitions == loopIndex) {
                    if (mListener != null) {
                        mListener.animationDidStop(AnimatedImageView.this);
                    }
                    return;
                }
            }
        }

        playing = true;

        setAnimationFrame(mCurrentFrameIdx);
//        mHandler.postDelayed(AnimatedImageView.this, mFrameAnimationDuration);
//        scheduleDrawable(getResources().getDrawable(mFrameResIds[mCurrentFrameIdx]), AnimatedImageView.this, mFrameAnimationDuration);
//        postDelayed()
        postDelayed(AnimatedImageView.this, mFrameAnimationDuration);

//        SongPlayerActivity.handler.postDelayed(AnimatedImageView.this, mFrameAnimationDuration);
    }

我的 xml 布局中有一个 AnimatedImageView 对象,在我的活动中,我通过 id 找到它并在单击时启动动画:

final AnimatedImageView mDriverAnimation = (AnimatedImageView) findViewById(R.id.driver);
        mDriverAnimation.setFrameResIds(new int[]{R.drawable.song1_driver1, R.drawable.song1_driver2, R.drawable.song1_driver3});
        mDriverAnimation.setAnimationDuration(3 * 1000);
        mDriverAnimation.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mDriverAnimation.start();
            }
        });

有任何想法吗? :) 谢谢。


我认为 TransitionDrawable 可以解决您的问题:http://developer.android.com/reference/android/graphics/drawable/TransitionDrawable.html http://developer.android.com/reference/android/graphics/drawable/TransitionDrawable.html

Drawable[] layers = new Drawable[2];
layers[0] = //your first drawable
layers[1] = //your second drawable
TransitionDrawable transition = new TransitionDrawable(layers);
myImageView.setImageDrawable(transition);
transition.startTransition(1500);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过使用计时器(或处理程序)更改 ImageView 中的图像来创建动画 的相关文章

  • Android:使用 OAuth 访问 google 任务时出现问题

    由于 google 任务没有公共 api 我想编写解决方法并像浏览器一样请求数据 然后解析结果以进一步显示 为了访问数据 我使用 google 实现了 OAuth 身份验证来访问此 url https mail google com htt
  • 安卓定位不准确

    我正在尝试获取当前用户的位置 我试图重构我的代码以获得更好的结果 但我只是不断得到关于准确度的荒谬位置 它在 900 600 米之间 如何才能得到更好的结果 使其精度达到50m以内 这是我的代码 package com agam mapsl
  • Android 如何更改 OnTouchListener 上的按钮背景

    你好 我在 xml 中有一个按钮 我正在使用OnTouchListener在我的活动中获得button按下并释放 但问题是 当我按下按钮时背景颜色没有改变 当我延长可能的活动时OnClickListener背景正在改变 任何人都可以告诉我的
  • 从 React Native Js 代码调用 Android Native UI 组件方法

    我创建了一个 CustomView SignatureView java 它扩展了 LinearLayout 以捕获 Android Native 中的签名 并创建了SignatureCapturePackage java和Signatur
  • 如何在React Native Android中获取响应头?

    您好 我想在获取 POST 请求后获取响应标头 我尝试调试看看里面有什么response with console log response 我可以从以下位置获取响应机构responseData但我不知道如何获取标题 我想同时获得标题和正文
  • 如何为发布而不是调试创建密钥库?扑

    我按照使用此网站部署 flutter 的步骤进行操作https flutter io android release https flutter io android release 当我运行 flutter build apk 时出现此错
  • 出现错误错误:res/menu/mainMenu.xml:文件名无效:必须仅包含[a-z0-9_。]

    我是安卓新手 刚刚开始使用 我在 res 文件夹中创建了一个文件 menu mainMenu xml 但我得到了错误 Error res menu mainMenu xml invalid file name must contain on
  • glTexImage2D: 之前出错:( 0x506 内部 0x1908 格式 0x1908 类型 0x1401

    当使用 Android Studio 运行模拟器时 我在模拟器屏幕上看不到任何内容 一切都是黑色的 我得到以下事件日志 模拟器 glTexImage2D 出错了 0x506 内部 0x1908 格式 0x1908 类型 0x1401 我已经
  • 如何检查 Android 中连接的 wifi 网络是否处于活动状态

    如何自动检查android中连接的WiFi网络上的互联网是否处于活动状态 我可以检查 wifi 是否已启用或 wifi 网络是否已连接 但我不确定如何检查互联网是否已连接 这可能吗 private boolean connectionAva
  • 画透明圆,外面填充

    我有一个地图视图 我想在其上画一个圆圈以聚焦于给定区域 但我希望圆圈倒转 也就是说 圆的内部不是被填充 而是透明的 其他所有部分都被填充 请参阅这张图片了解我的意思 http i imgur com zxIMZ png 上半部分显示了我可以
  • react-native run-android 失败并出现错误:任务 ':app:dexDebug' 执行失败

    我使用的是 Windows 8 1 和react native cli 1 0 0 and react native 0 31 0 添加后react native maps对于该项目 我运行了命令react native upgrade并给
  • VisualStateManager 和生成的转换

    正当我以为我明白的时候VisualStateManager 有些事情证明我错了 我正在使用 WPF 4 并且尝试简单地在鼠标悬停时放大某个项目 并在鼠标离开时将其缩小 我想我只需定义每个状态VisualStateGroup然后指定一个Vis
  • 如何修改 Skobbler 注释而不重新添加它

    我必须修改 SKAnnotation 的图像 注释生成器代码 private SKAnnotation getAnnotationFromView int id int minZoomLvl View view SKAnnotation a
  • Android:监听状态栏通知

    有没有办法在状态栏被下拉时监听通知 1 用于检测状态栏变化 您可以注册一个监听器来获取系统UI可见性变化的通知 因此 要在您的活动中注册侦听器 Detecting if the user swipe from the top down to
  • 模块中的类无法加载

    我正在开发一个 2D Unity android 游戏 其中我最近添加了 Firebase Beta SDK 但添加后FirebaseAnalytics unitypackage我面临的错误是 无法加载模块中的类 当我删除文件夹时Fireb
  • 在 KitKat 4.4.2 中获取 SDard 路径和大小

    我在 Google Play 上有一个设备信息应用程序 在该应用程序中我有存储信息 我知道 Android 4 4 在访问外部 SD 卡方面发生了一些变化 内部似乎没有给我带来问题 我的问题是 如何可靠地获取 KitKat 上 SD 卡的大
  • 使用 JobScheduler API 进行位置更新

    下面是我使用 FireBaseJobDispatcher 启动作业的演示代码 public class MainActivity extends AppCompatActivity Override protected void onCre
  • Android应用程序可以像旧的普通java小程序一样嵌入到网页中吗?

    我对 android 平台一无所知 也无法在互联网上找到这个基本问题的答案 更新 好的 我本身无法嵌入 Android 应用程序 但是我可以在 Android Webbrowser 中嵌入 Java 的东西吗 不可以 您无法将 Androi
  • Android 中带有组的列表视图

    我有一个列表视图 每行都有一些日期和文本 我可以像 iPhone 中那样将这个 listView 分组 组之间有标题吗 在 android 中是否可能 请帮忙 即 我需要在 Listview 行之间有标题栏 以便如果我使用日期对其进行分组
  • 使用velocity.js制作可拖动元素的动画

    我正在使用velocity js 为用户拖动的可拖动 SVG 元素设置动画 然而 velocity js 将先前的 mousemove 坐标排队并通过所有后续的 mousemove 坐标进行动画处理 我想要的是velocity js 不要对

随机推荐

  • SVG 视图框显示屏幕外项目

    我正在使用 HTML5 制作游戏svg标签为图形提供多分辨率显示 游戏的大部分内容已经完成 但在测试中我刚刚遇到了一个主要错误 其中涉及 SVG 对象可见 尽管在非本机分辨率下位于视图框之外 我不确定这是否是我的代码或浏览器本身的缺陷 Go
  • 从 WPF 打印/报告的最佳方法是什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在单击片段的按钮时替换该片段?

    我有一个包含多个片段的活动 Activity 最初有片段 其中有两个按钮 单击此按钮后 我必须用新片段替换该片段 每个片段都有各种小部件 并将当前片段替换为各种事件 这是我的问题 我怎样才能实现这个目标 给我建议 您可以用 Fragment
  • 从现有 MongoDB 创建可视化的工具[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我接手了一个现有 MongoDB 的项目 我想获得现有数据的视觉图像 图表等 显然 MongoDB 与
  • Android USB_DEVICE_ATTACHED 持久权限

    如何让 Android 在每次重新连接 USB 设备时都不再请求权限 我想让它记住 USB 设备的 默认使用 复选标记 这样我就不必每次都向同一设备授予权限 我以编程方式检测 USB 设备 Android 手机 何时连接到我的主机设备 An
  • 如何找到一组值的精确匹配?

    我有一个简单的表来存储师生关系 以显示学生正在上谁的课或老师正在教谁 无论哪种方式 为便于阅读 按老师排序 CREATE TABLE TS RELATIONSHIP Teacher NVARCHAR 10 Student NVARCHAR
  • 求反射角的弧度

    我正在编写一个简单的 Flash 游戏 只是为了学习 Flash 并提高我的数学能力 但我对弧度感到非常困惑 因为这对我来说是新的 到目前为止 我所做的是使用鼠标 单击并释放 使用弧度向该方向射出一个球 现在我想要发生的是 当球撞到墙壁时
  • Node exec 无权执行脚本

    直到最近 它都运行良好 但是当我今天尝试使用它时 它无法正常运行 它返回以下错误 错误 命令失败 bin sh c home pi RPi Computer Power RPi Server routes scripts hash js 1
  • Cordova 3.0,应用程序错误与服务器的连接失败。 (暂停)

    我在尝试加载本地 index html 文件时遇到超时问题 但我不知道如何增加默认的 20 秒超时时间 我见过人们在 droidgap 扩展 onCreate 方法中使用以下几行的帖子 super setIntegerProperty lo
  • 在 Angular 中使用异步管道设置选择元素的选定项目

    角度专家 我试图理解 Angular 中的异步管道 但我陷入了一个基本场景 我在用户界面中有两个选择元素 一个包含帖子 一个包含相关评论 我想将一个帖子 最后一个 设置为显示帖子的选择元素的最初选择的帖子 并且我想使用所选项目来过滤第二个选
  • cmake 找不到 boost 库,因为它查找错误的文件名

    我根据文档在 Windows 8 1 机器上构建了 boost 1 56 库 作为共享库和静态库 他们全部出现在BOOST ROOT stage lib目录 文件名格式如下 boost thread vc120 mt 1 56 dll bo
  • 在 GAE/J 上创建文件并上传到 Google 文档

    是否可以在 GAE J 上创建任何类型的文件并上传到 google 文档 我问过一个类似的问题 https stackoverflow com questions 3996495 uploading a pdf file to google
  • 可与 switch() 一起使用的自定义结构/类型

    我的一个项目有一个值类型 结构 表示视频格式的自定义标识符字符串 在本例中 它将包含内容类型字符串 但这可能会有所不同 我使用了一个结构体 因此它在传递时可以是强类型的 并对初始字符串值执行一些健全性检查 实际的字符串值可以是任何内容并由外
  • 在ReactJS中,如果我们不为useEffect提供依赖数组,是否会导致该函数每次都被调用?

    我看到在ReactJS 文档 https reactjs org docs hooks overview html的依赖数组useEffect fn 是可选的 不提供它应该与提供空数组相同 但是 如果我的代码如下 https codesan
  • boost::serialization 序列化期间内存消耗较高

    正如主题所示 在将大量数据序列化到文件时 我遇到了 boost serialization 的一个小问题 问题在于应用程序序列化部分的内存占用量大约是要序列化的对象内存的 3 到 3 5 倍 值得注意的是 我拥有的数据结构是基类指针和指向该
  • 新的 Angular 项目不包含 e2e 文件夹

    我的系统上已经安装了 Angular 并且大约 7 8 个月前曾短暂使用过它 不久前 我创建了一个新的 Angular 项目 ng new testproject 奇怪的是 e2e 文件夹没有创建 我尝试卸载 CLI 清除缓存并重新安装 A
  • 使用抽象类型的反射从表中获取实体

    好的 我有一个名为 Product 的抽象类 我有 3 个表 分别称为 Items Kits 和 Packages 它们实现了 Product 产品具有公开对象主键的公共属性 也就是说 我有一个传递产品的表格 我想将该产品从新的数据上下文中
  • 读取输入文件的部分内容

    我想读取 C 中的输入文件 其结构 或缺乏 将类似于一系列带有以下内容的行 文字 数字 例如 input1 10 input2 4 set1 1 2 set2 1 e3 我想把这个号码从队列中取出 然后把剩下的扔掉 数字可以是整数或双精度数
  • 如何在 Xamarin Forms 中对列表进行分组?

    我需要将下面的列表以 xamarin 形式与公司名称进行分组并需要在 ListView 中显示 我研究过 ObservableCollection 是可能的 但我不知道该怎么做 任何人都可以帮助实现这一目标吗 List public cla
  • 通过使用计时器(或处理程序)更改 ImageView 中的图像来创建动画

    我想通过更改 ImageView 内的帧来创建一个简单的动画 我不想使用 AnimationDrawable 因为我需要在帧更改或动画停止时接收事件 以便能够向后播放 重新启动等等 我的问题是 尽管 setImageDrawable 被调用