如何使用 View 的子级制作绘图动画,逐条绘制每条 Path 的线条?

2023-12-24

使用我在中找到的代码这个 StackOverflow 答案 https://stackoverflow.com/a/61843394/3692177我成功地可以用手指在画布上绘制任何内容,并且在绘制时我会看到我绘制的内容。由此,我想创建一个在按下按钮时触发的函数,该函数将执行两件事:

  1. 擦除画布上绘制的内容。
  2. 通过以恒定的速度一条一条地重新绘制每条路径的线条,重播在画布被清除之前在其上绘制的所有图片。

为此,我稍微修改了onTouchEvent代码,因此它相应地存储每个绘制点:

@Override
public boolean onTouchEvent(MotionEvent event) {
    StrokePoint point;

    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
            mPath.moveTo(event.getX(), event.getY());

            // Retrieve strokes in memory
            stroke_buffer = new Stroke();
            stroke_buffer.points = new ArrayList<StrokePoint>();
            point = new StrokePoint();
            point.x = event.getX();
            point.y = event.getY();
            stroke_buffer.points.add( point );

            break;
        case MotionEvent.ACTION_MOVE:
            mPath.lineTo(event.getX(), event.getY());

            // Retrieve strokes in memory
            point = new StrokePoint();
            point.x = event.getX();
            point.y = event.getY();
            stroke_buffer.points.add( point );

            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            // Retrieve strokes in memory
            strokes.add(stroke_buffer);
            break;
        default:
            break;
    }
    return true;
}

这样,我可以稍后在循环中加载 X 和 Y 点(至少是这个想法)。问题是我不确定如何触发画布上每行的“重绘”。我尝试像这样存储“onDraw”中的画布:

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawPath(mPath, mPaint);

    // For trying to make the "redraw" later
    this.mCanvas = canvas;

    super.onDraw(canvas);
}

然后,我为要擦除并重播先前绘制的笔画的按钮创建此方法:

public void replayStrokes() {
    // I start a new path from scratch ad-hoc the "redraw" animation.
    mPath = new Path();
    Log.i("SANDBOX_INFO", "Button pressed");
    // Intention here is leaving the "whiteboard" clear again.
    mCanvas.drawRGB(255, 255, 255);
    invalidate();
    this.draw(mCanvas);
    SystemClock.sleep(1000);

    // Redraw "line by line" loop
    mPath.moveTo(strokes.get(0).points.get(0).x,
                 strokes.get(0).points.get(0).y);
    for (int i = 0; i < strokes.size(); i++) {
        for (int j = 0; j < strokes.get(i).points.size(); j++) {
            if (i == 0 && j == 0) continue;
            mPath.lineTo(strokes.get(i).points.get(j).x,
                         strokes.get(i).points.get(j).y);
            mCanvas.drawPath(mPath, mPaint);
            invalidate();
            this.draw(mCanvas);
            SystemClock.sleep(100);
        }
    }
}

当我按下按钮时,该方法replayStrokes行为不符合预期。就好像它仍然在“思考”(处理),并且在你最意想不到的时候,一击刷新了所有的变化;相反,我希望它是一个平滑的动画,您可以看到之前用手指绘制的整个路径,逐行、逐点地重播。我究竟做错了什么?我应该改变什么才能获得预期的行为?


感谢 @VitorHugoSchwaab 的评论,我最终找到了解决方案。小提醒:我在这个问题中发布的所有代码都应该位于public class DrawCanvas extends View班级。那是说:

所以,我留下了这样的“触发方法”:

private int s, p;
private boolean replay_mode;

public void replayStrokes() {
    s = 0;
    p = 0;
    replay_mode = true;
    invalidate();
}

我修改了onDraw像这样的方法(我把它变成了Megamoth https://blog.codinghorror.com/new-programming-jargon/#28,但我可以稍后修复:P):

@Override
protected void onDraw(Canvas canvas) {
    if (replay_mode) {
        if (s == 0 && p == 0) {
            Log.i("SANDBOX_INFO", "Replay Mode START");
            canvas.drawRGB(255, 255, 255);
            p++;
            replayPath.reset();
            replayPath.moveTo(strokes.get(0).points.get(0).x,
                    strokes.get(0).points.get(0).y);
            invalidate();
        } else {
            Log.i("SANDBOX_INFO", "Replaying --> S:" + s + " P:" + p);
            if (p == 0) {
                replayPath.moveTo(strokes.get(s).points.get(p).x,
                        strokes.get(s).points.get(p).y);
            } else {
                replayPath.lineTo(strokes.get(s).points.get(p).x,
                        strokes.get(s).points.get(p).y);
                canvas.drawPath(replayPath, mPaint);
            }

            int points_size = strokes.get(s).points.size();
            if (s == strokes.size() - 1 && p == points_size - 1) {
                Log.i("SANDBOX_INFO", "Replay Mode END");
                replay_mode = false;
            }
            else if (p == points_size - 1) {
                s++;
                p = 0;
            } else {
                p++;
            }
        }
        invalidate();
    } else {
        canvas.drawPath(mPath, mPaint);
    }

    super.onDraw(canvas);
}

这有效。然而,重放笔画时会出现“闪烁”的小故障。我认为这可能是因为它实际上是在每一帧上“重绘”整个“重播路径”。基于这个猜测,当我有更多时间编码时,我将尝试解决这个问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 View 的子级制作绘图动画,逐条绘制每条 Path 的线条? 的相关文章

  • 如何使用 SharedPreferences 保存多个值?

    我正在开发一个字典应用程序 在我的应用程序中 我假设用户想要保存最喜欢的单词 我决定使用共享首选项保存这些值 我知道 SQLite 和文件更好 但我坚持使用 SharedPreferences 所以继续使用它 下面是我的代码 Overrid
  • 如何通过注解用try-catch包装方法?

    如果应该在方法调用中忽略异常 则可以编写以下内容 public void addEntryIfPresent String key Dto dto try Map
  • org/codehaus/plexus/archiver/jar/JarArchiver(不支持的major.minor版本49.0)-Maven构建错误

    下午大家 我在尝试构建项目时收到上述错误 我很确定这与使用 Java 1 6 编译的 Maven 最新更新有关 而我们尝试构建的项目是 1 4 项目 在此之前的插件工作没有问题 因此我将以下内容添加到 POM xml 文件中以尝试强制使用现
  • Android 上的 MIDI:Java 和/或 AIR 库

    一段时间以来 我一直在考虑在 iPad 上 重新 构建一个应用程序 其中我将使用 Objective C 和DSMI http dsmi tobw net 将 MIDI 信号发送到主机 这还不错 我的意思是 除了实际编写应用程序之外 现在我
  • Android NDK 代码中的 SIGILL

    我在市场上有一个 NDK 应用程序 并获得了有关以下内容的本机崩溃报告 SIGILL信号 我使用 Google Breakpad 生成本机崩溃报告 以下是详细信息 我的应用程序是为armeabi v7a with霓虹灯支持 它在 NVIDI
  • 用于缓存的 Servlet 过滤器

    我正在创建一个用于缓存的 servlet 过滤器 这个想法是将响应主体缓存到memcached 响应正文由以下方式生成 结果是一个字符串 response getWriter print result 我的问题是 由于响应正文将不加修改地放
  • 安卓。 CalendarView...一次仅显示一个月的日历

    我正在使用 CalendarView 其中我想一次仅查看一个月的日历并滚动查看下个月 但 CalendarView 一次显示所有月份 下面是我的代码
  • 我们如何测试包私有类?

    我正在看书Effective Java in Item 13 Minimize the accessibility of classes and members 它提到 为了方便测试 您可能想让类 接口或成员更易于访问 这在某种程度上是好的
  • JAVA中遍历JSON数据

    我是 JSON 新手 我使用 HTTPUrlConnections 并在 JAVA 程序中获得一些响应 响应数据将类似于 data id 1 userId 1 name ABC modified 2014 12 04 created 201
  • 使用 Play Integrity API 时,Firebase 电话身份验证会出现缺少客户端标识符错误

    使用 Firebase 电话身份验证注册 登录时 身份验证流程始终会启动 reCAPTCHA 流程 并在返回应用程序后发出missing client identifier error 我的设置之前适用于设备验证 安全网络 API 除了我的
  • Android 中的库可以有自己的意图过滤器吗?

    我想开发一个可以包含在其他 Android 应用程序中的库来拦截某些类型的意图 是否可以 我创建了一个库和一个测试项目 两者都有自己的AndroidManifest xml文件 在库的清单中 我为操作 TEST 定义了一个意图过滤器 但是
  • 哪个视图最亮?

    在Android中 哪个是轻量级视图 例如 View Textview Edittext 等 在某些情况下 我们需要使用视图来填充区域而不向用户显示视图 同时屏幕加载速度应该很快 您可以使用空间 android widget Space S
  • Android SearchView 在启动时隐藏键盘

    我有一个小问题正在尝试解决 当我打开应用程序时 键盘会显示输入搜索视图的查询 不过 我只想在单击搜索视图时显示键盘 我该如何解决 Thanks 这对我有用 用于隐藏焦点的代码 searchView SearchView view findV
  • 避免 Java 中的重复导入:继承导入?

    有没有办法 继承 导入 Example 常见枚举 public enum Constant ONE TWO THREE 使用此枚举的基类 public class Base protected void register Constant
  • onTaskRemoved() 在华为和小米设备中没有被调用

    我一直在使用onTaskRemoved 服务中的方法 用于检测应用程序何时通过滑动从设备最近列表中删除 我执行一些日志记录和发生这种情况时需要执行的一些其他操作 它工作完美 然后我在运行Android 6 0的华为设备上检查了这个方法 该方
  • 如何在android中通过蓝牙向配对设备发送短信?

    在我的应用程序中 我想通过蓝牙发送和接收短信 我可以在列表视图中看到配对设备名称和地址的列表 但是当我尝试向配对设备发送文本时 什么也没有发生 在其他设备中没有收到文本 这是我向配对设备发送消息的代码 private void sendDa
  • 如何更改操作栏背景和文本颜色

    我正在使用本教程中的导航抽屉 http www androidhive info 2013 11 android sliding menu using navigation drawer http www androidhive info
  • ArrayList.clear() 和 ArrayList.removeAll() 有什么区别?

    假如说arraylist定义为ArrayList
  • 如何使用通配符模拟泛型方法的行为

    我正在使用 EasyMock 3 2 我想基于 Spring Security 为我的部分安全系统编写一个测试 我想嘲笑Authentication http docs spring io autorepo docs spring secu
  • 基于 Spring Boot 的测试中的上下文层次结构

    我的 Spring Boot 应用程序是这样启动的 new SpringApplicationBuilder sources ParentCtxConfig class child ChildFirstCtxConfig class sib

随机推荐

  • 使用 Spring 解码主体参数

    我正在使用 Spring 为 Slack 应用程序开发 REST API 后端 我能够从 Slack 接收消息 斜线命令 但无法正确接收组件交互 按钮单击 The 官方文档 https api slack com docs message
  • 批量回显 URL

    编辑 变量没有正确定义 我不知道为什么 但我找到了解决方法 只需要 6 页 我创建了第 7 页 它将立即返回到第 1 页 因此不再需要 HTMLNxtpg 变量 我正在尝试创建一个批处理文件 它将生成一个 HTML 文件 这样用户就不需要任
  • 寻找干净的 C# WinForms MVC 教程 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何创建丰富的用户界面 Windows 应用程序 例如 Photo Shop 我正在寻找使用 C 的 WinForms 的干净 MVC 教
  • 哪个最适合数据存储结构/类?

    我们在 SO 中看到了很多关于 c 中的类与结构的讨论 大多以结论说它是一个结束堆 栈内存分配 并建议在中使用结构小数据结构 现在我面临着在这两个选择中决定简单数据存储的情况 目前 在我们的应用程序中 我们有数千个类 仅充当简单的数据存储
  • CodeIgniter 辅助函数可以使用数据库函数吗?

    我的 CodeIgniter 控制器函数之一需要调用递归函数作为其功能的一部分 如果我将函数调用放在控制器类中 函数调用就会阻塞 并且它无法访问数据库函数 this gt db gt get 如果我把它放在课堂之外 让它成为辅助函数可以解决
  • 在 UISlider 下添加数字

    我有一个用它实现的 UISliderJQuery UI 我想在显示数字的滑块下添加一个图例 我跟着这个答案 https stackoverflow com a 16877678 4861207它展示了如何实现这一点 然后将数字与百分比值一起
  • Rails:在任何来源中都找不到 minitest-4.7.5

    这里有一个麻烦 在我的远程服务器命令上gem list shows some gems minitest 4 7 5 bundle show minitest命令显示 var lib gems 1 9 1 gems minitest 4 7
  • Javascript:如何重用创建子实例的方法而不创建循环依赖项

    abstract class Fruit private content Fruit addChild Pick one at random using this as an example instead of the actual cr
  • 使用 jquery 从 获取复选框值

    http ghinda net css toggle switch bootstrap html http ghinda net css toggle switch bootstrap html 我使用上面的 css 文件和代码来制作切换开
  • Keras - 历元相关损失函数

    我正在使用 Keras 框架 我想实现一个与纪元相关的损失函数 即每个纪元的损失函数都不相同 你会怎么做 您能否添加一个示例 例如基于keras VAE 教程 https github com fchollet keras blob mas
  • iOS 设备 UDID 区分大小写吗?

    这是关于将设备添加到配置门户以进行临时测试 一个客户给我发了一个带有大写字符的 UDID 我没有检查就愚蠢地添加了它 无线部署不起作用 我想知道这是否是原因 但我想在用完我的 100 个分配之一之前先检查一下 Yes UDIDs区分大小写
  • 为什么 linq-2-sql 会创建额外的不必要的对象?

    我在数据库中有一个简单的父子表 如下所示 CREATE TABLE Parent Id int IDENTITY 1 1 NOT NULL Name nvarchar 256 NOT NULL ALTER TABLE Parent ADD
  • 使用 C# 突出显示 Docx 中的文本

    我需要突出显示 docx 文件中的一个句子 我有这段代码 并且它对于许多文档都可以正常工作 但我注意到对于某些文档 文档中的文本是逐字设置的 而不是整个句子 我的意思是每个单词它自己的Run 所以当搜索该句子时 找不到它 因为它在docx中
  • 使用 Eclipse 部署到 AppEngine 时出错

    每当我尝试将 Web 应用程序部署到 Google App Engine 时 无论女巫应用程序如何 甚至是演示应用程序 我都会遇到此问题 当我尝试部署时立即发生错误 错误是这样说的 部署到 AppEngine 时出错 部署到 App Eng
  • 如何在 Windows 上通过命令行以全屏视图打开 pdf?

    我可以使用以下命令通过命令行打开 pdf 文档 start test pdf 但我想通过命令行以全屏模式打开它 有人知道该怎么做吗 这应该可以做到 start max c nameofpdf pdf 这样做的优点是 如果用户使用非 adob
  • 如何从 pandas 数据帧计算 jaccard 相似度

    我有一个数据框如下 框架的形状是 1510 1399 列代表产品 行代表用户为给定产品分配的值 0 或 1 我怎样才能计算jaccard similarity scores 我创建了一个占位符数据框 列出了产品与产品 data ibs pd
  • AccessDenied:用户无权执行:cloudfront:CreateInvalidation

    我正在尝试使用 ember cli deploy 和 ember cli deploy cloudfront 将 ember 应用程序部署到 AWS CloudFront 我在 AWS 中设置了存储桶和用户 并为我的用户提供了 Amazon
  • 如何处理 Angular 2 中的模板错误(和其他错误)?

    当 Angular 2 中出现模板错误时 整个应用程序将无法工作 是否应该只有具有导致错误的模板的组件无法工作而应用程序的其余部分工作正常 如何处理错误以便应用程序在发生错误时不会停止响应 您可以使用自定义ErrorHandler http
  • 如何将 Kotlin 源文件转换为 Java 源文件

    我有一个 Kotlin 源文件 但我想将其转换为 Java 如何将 Kotlin 源代码转换为 Java 源代码 正如 Vadzim 所说 在 IntelliJ 或 Android Studio 中 您只需执行以下操作即可从 kotlin
  • 如何使用 View 的子级制作绘图动画,逐条绘制每条 Path 的线条?

    使用我在中找到的代码这个 StackOverflow 答案 https stackoverflow com a 61843394 3692177我成功地可以用手指在画布上绘制任何内容 并且在绘制时我会看到我绘制的内容 由此 我想创建一个在按