目前我正在开发允许用户绘图的应用程序。简单的想想,只要扩展 Canvas 类,大部分事情就完成了。
这是我最初的想法和想法。但是由于 Canvas 很小,因为这只是用户在屏幕上看到的内容,所以没有太多的空间可以绘制。通过文档,我发现 translate() 方法允许我移动 Canvas 。我确实发现,当我移动它时,会有一些空白,就像你移动一张纸一样。我知道这是完全正常的,正如我之前所说 - Canvas 只是“屏幕”。
我的问题是 - 是否有可能制作无限 Canvas 之类的东西,这样你就可以制作一幅巨大的画并移动所有东西?
在这个问题之前,我在想两件事:如何做这样的事情:
同时移动 Canvas 上的所有对象 - 坏主意,因为如果你有很多对象,那么移动速度会非常糟糕。
当您移动它(或更好地在屏幕上看到)时,执行与在 ListView 中所做的类似的操作,仅加载屏幕上的 View 以及之前的 View 和之后的 View 到内存和其余部分在需要时动态上传。我认为这是实现这一目标的最佳选择。
编辑:
Kai 给出的问题/答案告诉我,有必要编辑我的问题以澄清一些事情。
关于用户可以做什么的基本假设:
首先考虑无限,我考虑的是相当多的屏幕 - 每边至少 30 个 1x 缩放。我只需要让我的用户在他们正在做的事情上有更大的自由。
在此屏幕上,一切都可以正常进行 - 绘制、缩放(TouchListener、ScaleListener、DoubleTapListener)。说到缩放,还有一个不得不关注和联系到 Canvas 的“无限”。当用户缩小时,屏幕或不可见“邻居”上更精确的对象应该以适当的比例显示,就像您在现实生活中缩小相机一样。
我刚刚意识到的另一件事是可以在较小的缩放级别上绘制 - 即在两个或三个屏幕上然后放大 - 我想它应该将其剪切并重新计算为更小的部分。
我希望至少支持 API 10 的设备,而不仅仅是高端设备。
关于时间的问题是最关键的。我希望一切都尽可能顺利,这样用户就不会知道每次都在创建新的 Canvas 。
最佳答案
我认为这真的取决于很多事情:
如果要绘制的对象/命令真的不多,并且您不打算支持旧版/低端手机,那么您可以只绘制所有内容。 gfx 系统会进行检查并只绘制实际显示的内容,因此您只会浪费一些时间将通过 JNI 边界的命令发送到 gfx 系统和相关的矩形检查。
如果您决定需要一种更有效的方法,您可以将所有 gfx 对象的位置存储在 4 个树结构中,因此当您搜索左上/右上/左下/右下“窗口”时"屏幕应该显示,它会很快找到与这个窗口相交的 gfx 对象,然后只绘制那些对象。
[编辑]
First of all thinking about infinity I was thinking about quite big number of screens - at least 30 on zoom 1x in each side. I just need to give my users bigger freedom in what they are doing.
如果您只是描述 Canvas 对象的相对位置,那么 Canvas 的大小几乎没有限制,但可能必须提供一个按钮,将用户带到他们熟悉的 Canvas 上的某个点,以免他们迷路。
When talking about scaling, there is another thing that has to be concerned and connected with "infinity" of canvas. When user is zooming out then screens, or more precise objects on the invisible "neighbours" should appear with proper scaling as you would zoom out camera in real life.
如果您将 Canvas 对象存储在“虚拟空间”中,并使用“转换因子”将对象从虚拟空间转换到屏幕空间,那么放大/缩小之类的事情将变得微不足道,例如
screenObj.left=obj.left*transFactor-offsetX;
screenObj.right=obj.right*transFactor-offsetX;
screenObj.top=obj.top*transFactor-offsetY;
screenObj.bottom=obj.bottom*transFactor-offsetY;
//draw screenObj
例如,这是我的电影预订应用程序的屏幕截图:
下方窗口显示了电影院的所有座位,上方窗口是同一影院的放大 View 。它们被实现为相同 SurfaceView 类的两个实例,除了用户输入处理之外,唯一的区别是上面的那个应用了上述“转换因子”。
I assume that on all screens there will be maximum 500-800 rectangles or circles.
其实还不错。阅读您的编辑,我认为如果用户将大量对象添加到 Canvas 的同一部分,则可能会出现更大的问题。那么,如果您只绘制实际显示的对象而不绘制其他任何东西,那么 FPS 仍然很差,因为 GPU 的填充率已经饱和。
所以实际上有两个潜在的问题来源:
这两个问题需要非常不同的策略(第一个使用树结构对对象进行排序,第二个使用动态生成的位图缓存)。由于用户使用您的应用的方式可能与您预想的不同,因此我强烈建议在不进行上述优化的情况下实现功能,并尝试让尽可能多的人进行测试,然后 对您遇到的每个瓶颈应用优化,直到获得令人满意的性能。
[编辑 2]
实际上只有500~800个物体,你可以只计算所有物体的位置,然后检查它们是否在屏幕上可见,你甚至不需要使用一些花哨的数据结构,比如树有自己的管理费用。
关于Android - 是否有可能制作无限 Canvas ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18018248/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub