如何在EditText中执行重做撤消操作

时间:2012-01-03 07:45:07

标签: android

我想知道是否有任何方法或任何链接或教程在Android edittext中执行重做撤消操作。如果有人知道,请告诉我。

5 个答案:

答案 0 :(得分:3)

对于Android EditText,有一个undo / redo实现 http://credentiality-android-scripting.googlecode.com/hg/android/ScriptingLayerForAndroid/src/com/googlecode/android_scripting/activity/ScriptEditor.java

代码可以正常工作,但不能正确处理配置更改。我正在修复,并会在完成后发布。

我的Google搜索是: - android edittext onTextChanged undo

答案 1 :(得分:3)

关于Antti-Brax / Divers(Kidinov)解决方案的快速说明。它工作得很好,除非你尝试将它与TextView post-API 23一起使用,否则你会遇到问题,因为猜测 - 谷歌实际上添加了一个隐藏的UndoManager(android.content.UndoManager)并且没有记录它或使它明显存在。但是如果你在Marshmallow或Nougat中有硬/蓝牙键盘并且点击^ Z或SHIFT- ^ Z,你将获得撤销/重做。

如果你已经将Antti-Brax的类与EditText一起使用,并且你也将它挂钩到^ Z并且shift-^ Z,问题就出现了,你会遇到使用硬键盘的人遇到的问题。即,^ Z将触发本机和Antti-Brax的撤销,同时导致两个撤消,这是不好的。在他们中的一些之后,你可能会得到一个跨越界限的跨越。

我发现一个可能的解决方案是继承TextView / TextEdit / whatever并拦截来自TextView的undo / redo调用,因此它们不会按如下方式运行:

    @Override
    public boolean onTextContextMenuItem(int id) {
        int ID_UNDO, ID_REDO;

        try {
            ID_UNDO = android.R.id.undo;
            ID_REDO = android.R.id.redo;
        } catch (Resources.NotFoundException e) {
            ID_UNDO = 16908338; // 0x1020032
            ID_REDO = 16908339; // 0x1020033
        }
        return !((id == ID_UNDO) || (id == ID_REDO)) && super.onTextContextMenuItem(id);
    }

找到了那些神奇的id号码here,如果找不到android.R.id.undo值,它们仅用作备份。 (也可以合理地假设,如果值不存在,则不存在该特征,但无论如何......)

这不是最佳解决方案,因为两个撤消跟踪器仍在那里并且两者都在后台运行。但至少你不会同时用^ Z触发它们。这是我能想到的最好的事情,直到它被正式记录并且TextView的getUndoManager()方法不再被隐藏...

为什么他们制作了一个你无法关闭的功能(甚至不知道它是否存在)在发布的Android中“直播”我不能说。

我刚刚在Android的问题跟踪器上开了一个issue,如果有人想要这样做的话。

答案 2 :(得分:1)

这是从Gary Phillips的答案中提取的撤消/重做实现,该答案被提取为可重用且通用的撤销/重做插件,用于从TextView下载的任何窗口小部件。我添加了一些用于保存撤消历史记录的代码。

http://code.google.com/p/android/issues/detail?id=6458#c123

希望这有帮助。

答案 3 :(得分:1)

保留关于撤消的EditText样式: 您可以创建ArrayList<EditText>ArrayList<String>(包含html文本的字符串)来存储最近的10个(例如)操作。所以ArrayList [0]将包含来自第一个操作的html文本,ArrayList [9]将包含来自 last 操作的html文本。每次用户在您的应用中点击“撤消”时,您都会将ArrayList [size()-1]应用于您的EditText,然后从您的数组中删除ArrayList [size() - 1]。

答案 4 :(得分:1)

我知道这是一个老问题,但由于没有接受的答案,这是一个我从多个角度处理自己的问题,我想添加我的解决方案以防万一。我的答案可能与需要此功能的大量(1,000字以上)大量文本编辑应用程序最相关。

解决此问题的最简单方法是定期复制屏幕上的所有文本,将其保存到数组中,并在每次调用Undo方法时调用setText()。这是一个可靠的系统,但它不适用于大型(即1,000字以上)文本编辑应用程序。这是因为它:

  • 浪费。可能只有一个单词在一个两千字的文档中发生了变化,因此这一千字,九百九十九个单词不必要地致力于记忆。
  • 可能导致性能问题,因为一些低层硬件在渲染大量文本时会遇到困难。在我的一些测试设备上,只要调用Undo,这种方法就会导致冻结几秒钟。

我目前使用的解决方案比较复杂,但我已将结果发布在library here

基本上,这个库在用户开始输入后立即保存文本副本,然后在他们停止输入一段时间后(在我的情况下,两秒钟)保存另一个文本副本。然后比较两个文本字符串,返回更改的文本部分,发生更改的索引,以及有关更改是否添加新文本,删除或使用新文本替换旧文本的详细信息。

最终结果是只保存了必要的文本,并且在调用撤消时,只有本地delete()replace()insert()来电,这样可以更快对大文本字段的操作。