I have an image which I am processing, and I have two buttons, undo and redo. I need the code to undo/redo previous touch action if either of those two buttons are clicked. I know I have to use a stack. How should I implement it?
There are two main patterns for implementing Undo/Redo:
- The "memento" pattern.
- The "command" pattern.
1. Memento Pattern
The idea of the memento pattern is that you can save a copy of the entire internal state of an object (without violating encapsulation) to be restored later.
It would be used (for example) like this:
// Create your object that can be "undone"
ImageObject myImage = new ImageObject()
// Save an "undo" point.
var memento = myImage.CreateMemento();
// do a bunch of crazy stuff to the image...
// ...
// Restore to a previous state.
myImage.SetMemento(memento);
2. Command Pattern
The idea of the command pattern is to encapsulate the actions that are actually performed on an object. Each "action" (or, "command") can optionally know how to roll itself back. Alternatively, when a rollback needs to occur, the entire chain of commands can be executed again.
It would be used (for example) like this:
// Create your object that can be "undone"
ImageObject myImage = new ImageObject()
// Create a "select all" command
var command = new SelectAllCommand(myImage); // This does not actually execute the action.
// Apply the "select all" command to the image
selectAll.Execute(); // In this example, the selectAll command would "take note" of the selection that it is overwriting.
// When needed, rollback:
selectAll.Rollback(); // This would have the effect of restoring the previous selection.
It all depends what your touch events do in the first place. You have to abstract what your application does in response to the touches into a class that you can fill a Stack with. Then, the stack implementation is easy.
If it's image manipulation, it might take up too much memory to keep a whole stack of Bitmaps around. You'll probably get the infamous OutOfMemoryException after pushing two or three items onto your stack. What you'd probably be better off doing is abstract the actions available in your app and rebuilding on undo/redo. You're basically creating a stack of instruction sets. This makes it slower the larger your stack is, but if the images in memory are large it might be the only way to do it.
In the newer Android versions (22+) you could use a Snackbar. Here's small code fragment for listener:
public class MyUndoListener implements View.OnClickListener{
&Override
public void onClick(View v) {
// Code to undo the user's last action
}
}
and creating a message at the bottom of the screen for an "undo" action:
Snackbar mySnackbar = Snackbar.make(findViewById(R.id.myCoordinatorLayout),
R.string.email_archived, Snackbar.LENGTH_SHORT);
mySnackbar.setAction(R.string.undo_string, new MyUndoListener());
mySnackbar.show();
© 2022 - 2024 — McMap. All rights reserved.