如何使用 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 的线条? 的相关文章

  • Java 客户端到服务器未知来源

    我有一个简单的乒乓球游戏 需要通过网络工作 服务器将创建一个带有球和 2 个球棒位置的游戏 当客户端连接到服务器时 服务器将创建一个名为 PongPlayerThread 的新类 它将处理客户端到服务器的输入和输出流 我的服务器工作100
  • Eclipse RCP - 将视图与编辑器区域堆叠?

    在开发 Eclipse RCP 应用程序时 是否可以将视图与编辑器区域堆叠在一起 像这样 我有多个列表 表格 我想创建一种预览组合 当通过单击鼠标选择列表上的项目时 我希望我的预览合成显示该项目的数据 如果用户双击某个项目 我想在预览合成后
  • java.lang.ClassNotFoundException: org.jboss.logging.Logger

    我有一个奇怪的问题 我有一个JMS https en wiktionary org wiki JMS客户端应用程序和MDB https en wikipedia org wiki Enterprise JavaBeans Message d
  • Android studio 找不到 Theme.AppCompat.Light.DarkActionBar [重复]

    这个问题在这里已经有答案了 我已经导入了一个Android Studio项目来自Github into Android Studio 虽然我的build gradle有dependencies dependencies compile fi
  • 如何在Android 11中获取dir文件列表

    我想编写自己的精简版文件浏览器 文件 API 现在不适用于外部存储 该版本还提供了对范围存储的改进 这使得开发人员可以更轻松地迁移到使用此存储模型 我不明白如何使用范围存储来访问 sdcard 如果您正在寻找文件选择器体验 存储访问框架 h
  • 将 Maven 控制台与 m2eclipse 一起使用

    Maven 新手在这里 有没有办法在 Eclipse 中打开控制台并在 M2Eclipse 插件上执行 Maven 命令 这是一个非常好的插件 但我环顾四周 没有找到我想要的一些功能 谢谢 如果你想运行特定的maven插件 你可以这样做 g
  • Jersey 和 Spring 中的全局异常处理?

    我正在使用 Jersey 和 Spring 3 2 以及 Open CMIS 开发 RESTful Web 服务 我没有使用 Spring 的 MVC 模式 它只是 Spring IOC 和 Jersey SpringServlet 控制器
  • IntelliJ - 无效源版本:17

    我已经在 IntelliJ 中使用 Gradle 创建了一个使用 Java 17 的新 Java 项目 运行我的应用程序时出现错误Cause error invalid source release 17 我的设置 我已经安装了openjd
  • 为什么replaceAll在这行代码中不起作用? [复制]

    这个问题在这里已经有答案了 String weatherLocation weatherLoc 1 toString weatherLocation replaceAll how weatherLocation replaceAll wea
  • Android Lollipop:将应用程序小部件添加到主屏幕时启动器崩溃

    添加小部件时 启动器在 Android Lollipop 上崩溃 并显示以下消息 在以前的 Android 版本上运行良好 编辑 这只发生在横向方向 12 16 12 35 10 208 E AndroidRuntime 960 java
  • Web 服务客户端的 AXIS 与 JAX-WS

    我决定用Java 实现Web 服务客户端 我已经在 Eclipse 中生成了 Axis 客户端 并使用 wsimport 生成了 JAS WS 客户端 两种解决方案都有效 现在我必须选择一种来继续 在选择其中之一之前我应该 考虑什么 JAX
  • 将一个整数从 C 客户端发送到 Java 服务器

    我使用此代码将一个整数从我的 Java 客户端发送到我的 Java 服务器 int n rand nextInt 50 1 DataOutputStream dos new DataOutputStream socket getOutput
  • 按钮悬停和按下效果 CSS Javafx

    我是 CSS 新手 为按钮定义了以下 CSS 样式 其中id并且应用了自定义样式 但不应用悬停和按下效果 bevel grey fx background color linear gradient f2f2f2 d6d6d6 linear
  • Android 10 通知彩色操作按钮

    I m trying to color the buttons Action in Notification like this So far this is what i m achieved so far 下面是我正在使用的代码 通知服
  • 在Java内存管理中,“PS”代表什么?

    每当我看到 Java 中对内存的引用时 各种空格总是以 PS 为前缀 PS 是什么意思 它开始困扰我 到目前为止我唯一的猜测是 泳池空间 但这将是多余的 例子 PS伊甸园空间 PS 幸存者空间 PS 终身空间 老一代 PS Perm Gen
  • java mysql 准备好的语句

    我正在尝试使用 java 向数据库中进行简单的插入 它告诉我我的 sql 语法已关闭 但是 当我复制打印出来的字符串并将其放入 phpmyadmin 中的 sql 命令中时 它会正确执行该命令 并且我似乎无法弄清楚 java 中的字符串查询
  • java中什么是静态接口?

    我正在阅读Map Entry界面 当我注意到它是一个static界面 我不太明白什么是静态接口 它与常规接口有什么不同 public static interface Map Entry
  • Volley 在第一次调用方法时返回 null

    我正在尝试使用 volley 从服务器检索数据 但是当我第一次调用此方法时 我收到服务器的响应 但该方法返回 null 如果我第二次调用它 我会得到最后的响应 public String retrieveDataFromServer Str
  • 将 SQL 数据中的一行映射到 Java 对象

    我有一个 Java 类 其实例字段 以及匹配的 setter 方法 与 SQL 数据库表的列名相匹配 我想优雅地从表中获取一行 到 ResultSet 中 并将其映射到此类的实例 例如 我有一个 Student 类 其中包含实例字段 FNA
  • 如何在顶部工具栏的购物车图标上添加商品编号?安卓

    I saw some apps made it So I am intersting at how to do it I believe there must be some trick way to do it Example 我在菜单文

随机推荐

  • 使用 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我成功地可以用手指在画布上绘制任何内容 并且在绘制时我会看到我绘制的内容 由此 我想创建一个在按