我的方法是构建撤消和重做堆栈。代码如下..它比您要求的要多一点,但也许其他人会 a) 发现它有用,b) 告诉我如何改进它..
视图控制器:
#define kBrushOpacity (1.0 / 3.0)
#define kBrushPixelStep 3
#define kBrushScale 3
#define kLuminosity 0.75
#define kSaturation 1.0
#define kPaletteHeight 30
#define kPaletteSize 25
#define kMinEraseInterval 0.5
// Padding for margins
#define kLeftMargin 10.0
#define kTopMargin 50.0
#define kRightMargin 10.0
#define kBottomMargin 550.0
#define kCGBlendModePlusLighter 30.0
CGImageRef UIGetScreenImage(void);
@implementation DrawingViewController
- (IBAction)dismiss:(id)sender {
//NSLog(@"%s", __FUNCTION__);
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewDidLoad
{
//NSLog(@"%s", __FUNCTION__);
[super viewDidLoad];
pathArray=[[NSMutableArray alloc]init];
bufferArray=[[NSMutableArray alloc]init];
tempArray=[[NSMutableArray alloc]init];
orientation = [[UIApplication sharedApplication] statusBarOrientation];
[self.window addSubview:window];
[self.window makeKeyAndVisible];
drawingView =[[DrawingView alloc]initWithFrame:CGRectMake (0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
drawingView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[drawingView setBackgroundColor:[UIColor blackColor]];
//[self backgroundSwitchChange];
[self.view addSubview:drawingView];
rect = [[UIScreen mainScreen] bounds];
brushSize = [[NSUserDefaults standardUserDefaults] valueForKey:@"brushKey"];
moved = 0;
[self buildColorBar];
[self buildToolBar];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(brushChange) name:@"brushNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pictureChange) name:@"pictureNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backgroundSwitchChange) name:@"backgroundNotification" object:nil];
[self showAlert];
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
savedImage.image = drawImage.image;
UIGraphicsEndImageContext();
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//NSLog(@"%s", __FUNCTION__);
return YES;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
//NSLog(@"%s", __FUNCTION__);
[toolControls removeFromSuperview];
[colorControls removeFromSuperview];
[self buildColorBar];
[self buildToolBar];
}
- (void)setupNotifications {
//NSLog(@"%s", __FUNCTION__);
NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
[dnc addObserver:self selector:@selector(brushChange) name:@"brushChange:" object:nil];
[dnc addObserver:self selector:@selector(brushColorChange) name:@"createColorNotification" object:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - Top Toolbar
-(void) buildToolBar {
//NSLog(@"%s", __FUNCTION__);
toolControls = [[UISegmentedControl alloc] initWithItems:
[NSArray arrayWithObjects:
[UIImage imageNamed:@"Brush.png"],
[UIImage imageNamed:@"Undo.png"],
[UIImage imageNamed:@"Redo.png"],
[UIImage imageNamed:@"Save.png"],
[UIImage imageNamed:@"Erase.png"],
[UIImage imageNamed:@"Restore.png"],
nil]];
UIInterfaceOrientation fieldOrient = [[UIApplication sharedApplication] statusBarOrientation];
if ((fieldOrient == UIDeviceOrientationLandscapeLeft) || (fieldOrient == UIDeviceOrientationLandscapeRight)) {
//NSLog(@"Landscape");
CGRect frame = CGRectMake(0, 30, 480, 25 );
toolControls.frame = frame;
} else {
//NSLog(@"Portrait");
CGRect frame = CGRectMake(0, 30, 320, 25 );
toolControls.frame = frame;
}
[toolControls addTarget:self action:@selector(drawSegmentAction:) forControlEvents:UIControlEventValueChanged];
toolControls.momentary = YES;
toolControls.tintColor = [UIColor grayColor];
[self.view addSubview:toolControls];
}
- (IBAction)drawSegmentAction:(id)sender
{
//NSLog(@"%s", __FUNCTION__);
UISegmentedControl *segmentedControl = (UISegmentedControl *)sender;
switch (segmentedControl.selectedSegmentIndex){
case 0: { //Brushes
[self showBrushes:sender];
break;
}
case 1: { // Undo
[drawingView undoButtonClicked];
break;
}
case 2: { // Redo
[drawingView redoButtonClicked];
break;
}
case 3: { // Save
[self saveButtonTapped:self];
break;
}
case 4: { // Erase
[self eraseButtonTapped:self];
break;
}
case 5: { // Restore
[self restoreButtonTapped:self];
break;
}
default: {
//NSLog(@"default");
break;
}
}
}
- (void)doneButtonTapped {
[delegate doneButtonTapped];
}
#pragma mark - Color Bar
-(void) buildColorBar {
//NSLog(@"%s", __FUNCTION__);
colorControls = [[UISegmentedControl alloc] initWithItems:
[NSArray arrayWithObjects:
[UIImage imageNamed:@"White.png"],
[UIImage imageNamed:@"Red.png"],
nil]];
UIInterfaceOrientation fieldOrient = [[UIApplication sharedApplication] statusBarOrientation];
if ((fieldOrient == UIDeviceOrientationLandscapeLeft) || (fieldOrient == UIDeviceOrientationLandscapeRight)) {
CGRect frame = CGRectMake(0, 230, 480, 25 );
colorControls.frame = frame;
} else {
CGRect frame = CGRectMake(0, 390, 320, 25 );
colorControls.frame = frame;
}
// Add LongTap Color options
gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showMoreColors:)];
gesture.minimumPressDuration = 1.0;
[colorControls addGestureRecognizer:gesture];
//gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showMoreColors:)];
//[gesture setNumberOfTapsRequired:2];
//[colorControls addGestureRecognizer:gesture];
// When the user chooses a color, the method changeColor: is called.
[colorControls addTarget:self action:@selector(changeColor:) forControlEvents:UIControlEventValueChanged];
colorControls.segmentedControlStyle = UISegmentedControlStyleBar;
// Make sure the color of the color complements the black background
colorControls.tintColor = [UIColor grayColor];
// Add the control to the window
[self.view addSubview:colorControls];
}
// Change the brush color
- (IBAction)changeColor:(id)sender {
//NSLog(@"%s", __FUNCTION__);
colorIndex = [sender selectedSegmentIndex];
AppDelegate *mainDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
mainDelegate.colorIndex = colorIndex;
switch (colorIndex) {
case 0:
colorKey = @"0";
break;
case 1:
colorKey = @"1";
break;
case 2:
colorKey = @"2";
break;
case 3:
colorKey = @"3";
break;
default:
break;
}
[[NSUserDefaults standardUserDefaults] setObject: colorKey forKey: @"colorKey"];
[[NSNotificationCenter defaultCenter] postNotificationName: @"ColorChange" object: nil];
[drawingView changeColor:sender];
}
-(void) showMoreColors:(id)sender {
//NSLog(@"%s", __FUNCTION__);
switch (colorIndex) {
case 0:
[self showMoreWhiteColors:(id)sender];
break;
case 1:
[self showMoreRedColors:(id)sender];
break;
case 2:
[self showMoreYellowColors:(id)sender];
break;
case 3:
[self showMoreGreenColors:(id)sender];
break;
case 4:
[self showMoreBlueColors:(id)sender];
break;
case 5:
[self showMorePurpleColors:(id)sender];
break;
case 6:
[self showMoreBlackColors:(id)sender];
break;
default:
break;
}
}
#pragma mark - Brushes
//delegate methods
- (void)brushesViewControllerDidFinish:(BrushesViewController *)controller
{
//NSLog(@"%s", __FUNCTION__);
[self brushChange];
}
- (void)brushChange { //from notification
//NSLog(@"%s", __FUNCTION__);
brushSize = [[NSUserDefaults standardUserDefaults] objectForKey:@"brushKey"];
[drawingPath brushChange];
}
- (IBAction)showBrushes:(id)sender
{
//NSLog(@"%s", __FUNCTION__);
BrushesViewController *controller = [[BrushesViewController alloc] initWithNibName:@"Brushes" bundle:nil];
controller.delegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
- (void)changeBrushSize:(id)sender {
//NSLog(@"%s", __FUNCTION__);
}
#pragma mark - Colors
- (void)whiteViewControllerDidFinish:(WhiteViewController *)controller
{
//NSLog(@"%s", __FUNCTION__);
[[NSNotificationCenter defaultCenter] postNotificationName: @"ColorChange" object: nil];
[drawingView changeColor:self];
}
- (void)redViewControllerDidFinish:(RedViewController *)controller
{
//NSLog(@"%s", __FUNCTION__);
[[NSNotificationCenter defaultCenter] postNotificationName: @"ColorChange" object: nil];
[drawingView changeColor:self];
}
- (void)greenViewControllerDidFinish:(GreenViewController *)controller
{
//NSLog(@"%s", __FUNCTION__);
[[NSNotificationCenter defaultCenter] postNotificationName: @"ColorChange" object: nil];
[drawingView changeColor:self];
}
- (void)purpleViewControllerDidFinish:(PurpleViewController *)controller
{
//NSLog(@"%s", __FUNCTION__);
[[NSNotificationCenter defaultCenter] postNotificationName: @"ColorChange" object: nil];
[drawingView changeColor:self];
}
- (IBAction)showMoreWhiteColors:(id)sender {
//NSLog(@"%s", __FUNCTION__);
WhiteViewController *controller = [[WhiteViewController alloc] initWithNibName:@"White" bundle:nil];
controller.delegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
- (IBAction)showMoreRedColors:(id)sender
{
//NSLog(@"%s", __FUNCTION__);
RedViewController *controller = [[RedViewController alloc] initWithNibName:@"Red" bundle:nil];
controller.delegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
- (IBAction)showMoreYellowColors:(id)sender {
//NSLog(@"%s", __FUNCTION__);
YellowViewController *controller = [[YellowViewController alloc] initWithNibName:@"Yellow" bundle:nil];
controller.delegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
- (IBAction)showMoreBlackColors:(id)sender {
BlackViewController *controller = [[BlackViewController alloc] initWithNibName:@"Black" bundle:nil];
controller.delegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
#pragma mark - Save
- (IBAction)saveButtonTapped:(id)sender
{
[self captureToPhotoAlbum];
[self flashScreen];
}
-(void)captureToPhotoAlbum {
//NSLog(@"%s", __FUNCTION__);
UIScreen *screen = [UIScreen mainScreen];
CGRect screenRect = screen.bounds; //implicitly in Portrait orientation.
UIInterfaceOrientation fieldOrient = [[UIApplication sharedApplication] statusBarOrientation];
if ((fieldOrient == UIDeviceOrientationLandscapeLeft) || (fieldOrient == UIDeviceOrientationLandscapeRight)) {
CGRect temp;
temp.size.width = screenRect.size.height;
temp.size.height = screenRect.size.width;
screenRect = temp;
}
UIGraphicsBeginImageContext(screenRect.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
CGContextFillRect(ctx, screenRect);
[self.view.layer renderInContext:ctx];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2.0) {
// Retina
// Image cropping This is the size of the saved image.
//NSLog(@"height is %f", self.view.bounds.size.height );
CGImageRef imageRef = CGImageCreateWithImageInRect
([img CGImage],
CGRectMake (0, 75, (self.view.bounds.size.width * 2), (self.view.bounds.size.height -130)));
// NSLog(@"width is %f", self.view.bounds.size.width * 2 );
UIImage *img2Save = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
// Request to save the image to camera roll
UIImageWriteToSavedPhotosAlbum(img2Save, self, nil, nil);
} else {
CGImageRef imageRef = CGImageCreateWithImageInRect
([img CGImage],
CGRectMake (0, 75, self.view.bounds.size.width, (self.view.bounds.size.height - 130)));
UIImage *img2Save = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
// Request to save the image to camera roll
UIImageWriteToSavedPhotosAlbum(img2Save, self, nil, nil);
}
}
-(void) flashScreen {
//NSLog(@"%s", __FUNCTION__);
UIWindow* wnd = [UIApplication sharedApplication].keyWindow;
UIView* v = [[UIView alloc] initWithFrame: CGRectMake(0, 0, wnd.frame.size.width, wnd.frame.size.height)];
[wnd addSubview: v];
v.backgroundColor = [UIColor whiteColor];
[UIView beginAnimations: nil context: nil];
[UIView setAnimationDuration: 1.0];
v.alpha = 0.0f;
[UIView commitAnimations];
}
#pragma mark - Undo Redo
-(IBAction)undoButtonTapped:(id)sender
{
//NSLog(@"%s", __FUNCTION__);
[drawingView undoButtonClicked];
}
-(IBAction)redoButtonTapped:(id)sender
{
//NSLog(@"%s", __FUNCTION__);
[drawingView redoButtonClicked];
}
#pragma mark - Erase / Restore
- (IBAction)eraseButtonTapped:(id)sender {
//NSLog(@"%s", __FUNCTION__);
savedImage.image = drawImage.image;
[drawingView eraseButtonClicked];
undoFlag = 1;
}
- (IBAction)restoreButtonTapped:(id)sender {
//NSLog(@"%s", __FUNCTION__);
if (undoFlag == 1) {
drawImage.image = savedImage.image;
[drawingView restoreButtonClicked];
undoFlag = 0;
}
}
@end
界面视图:
#import "DrawingView.h"
float red = 0;
float green = 1;
float blue = 0;
float alpha = 50;
- (id)initWithFrame:(CGRect)frame
{
//NSLog(@"%s", __FUNCTION__);
if (!(self = [super initWithFrame:frame]))
return nil;
[self initializeView];
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
//NSLog(@"%s", __FUNCTION__);
if (!(self = [super initWithCoder:aDecoder]))
return nil;
[self initializeView];
return self;
}
- (void)initializeView {
_currentColor = [UIColor greenColor];
_currentArray = [NSMutableArray array];
_bufferArray = [NSMutableArray array];
_redoStack = [NSMutableArray array];
_result = @"NO";
myPath=[[UIBezierPath alloc]init];
myPath.lineCapStyle=kCGLineCapRound;
[self setUserInteractionEnabled:YES];
}
- (void)drawRect:(CGRect)rect {
//NSLog(@"%s", __FUNCTION__);
for (DrawingPath *drawingPath in self.currentArray) {
[drawingPath draw];
}
}
#pragma mark - Actions
- (void)eraseButtonClicked {
//NSLog(@"%s", __FUNCTION__);
self.bufferArray = [self.currentArray mutableCopy];
[self.currentArray removeAllObjects];
[self setNeedsDisplay];
}
- (void)restoreButtonClicked {
//NSLog(@"%s", __FUNCTION__);
self.currentArray = [self.bufferArray mutableCopy];
[self.bufferArray removeAllObjects];
[self setNeedsDisplay];
}
-(void)undoButtonClicked
{
//NSLog(@"%s", __FUNCTION__);
if ([self.currentArray count] == 0) {
//nothing to undo
return;
}
DrawingPath *undonePath = [self.currentArray lastObject];
[self.currentArray removeLastObject];
[self.redoStack addObject:undonePath];
[self setNeedsDisplay];
}
-(void)redoButtonClicked
{
//NSLog(@"%s", __FUNCTION__);
if ([self.redoStack count] == 0) {
// nothing to redo
return;
}
DrawingPath *redonePath = [self.redoStack lastObject];
[self.redoStack removeLastObject];
[self.currentArray addObject:redonePath];
[self setNeedsDisplay];
}
#pragma mark - Touch Methods
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//NSLog(@"%s", __FUNCTION__);
self.currentColoredPath = [[DrawingPath alloc] init];
[self.currentColoredPath setColor:self.currentColor];
UITouch *touch= [touches anyObject];
[self.currentColoredPath.path moveToPoint:[touch locationInView:self]];
[self.currentArray addObject:self.currentColoredPath];
// Remove all paths from redo stack
[self.redoStack removeAllObjects];
lastPoint = [touch locationInView:self];
lastPoint.y -= 20;
if ([touch tapCount] == 2) {
[self alertOKCancelAction];
return;
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
//NSLog(@"%s", __FUNCTION__);
UITouch *touch = [touches anyObject];
[self.currentColoredPath.path addLineToPoint:[touch locationInView:self]];
[self setNeedsDisplay];
CGPoint currentPoint = [touch locationInView:self];
currentPoint.y -= 20;
lastPoint = currentPoint;
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//NSLog(@"%s", __FUNCTION__);
self.currentColoredPath = nil;
}
# pragma mark - Brush Colors
// Change the brush color
- (void)changeColor:(id)sender
{
//NSLog(@"%s", __FUNCTION__);
colorKey = [[NSUserDefaults standardUserDefaults] objectForKey:@"colorKey"];
colorIndex = [colorKey intValue];
switch (colorIndex) {
case 0:
red = 1;
green = 1;
blue = 1;
//[selectSound play];
break;
case 1:
red = 1;
green = 0;
blue = 0;
//[selectSound play];
break;
case 2:
red = 1;
green = 1;
blue = 0;
//[selectSound play];
break;
case 3:
red = 0;
green = 1;
blue = 0;
//[selectSound play];
break;
case 4:
red = 0.11764f;
green = 0.56470f;
blue = 1;
//[selectSound play];
break;
case 5:
red = 1;
green = 0.41176f;
blue = 0.70588f;
//[selectSound play];
break;
case 6:
red = 0;
green = 0;
blue = 0;
//[selectSound play];
break;
//WHITE
case 11:
red = 0.949020f;
green = 0.949020f;
blue = 0.949020f;
//[selectSound play];
break;
case 12:
case 13:
default:
break;
}
//NSLog(@"ColorIndex is %i", colorIndex);
self.currentColor = [UIColor colorWithRed:red green:green blue:blue alpha:1];
}
#pragma mark - Alerts
- (void)shakeOKCancelAction {
// open a alert with an OK and cancel button
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"SHAKE", nil) message: NSLocalizedString(@"SHAKEERASE", nil) delegate:self cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
[alert show];
}
- (void)alertOKCancelAction {
// open a alert with an OK and cancel button
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"TWICE", nil) message: NSLocalizedString(@"TAPERASE", nil) delegate:self cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the Alert buttons
if (buttonIndex == 0)
{
return;
}
else
{
[self eraseButtonClicked];
return;
}
}
@end
and object:
@implementation DrawingPath
@synthesize path = _path;
@synthesize color = _color;
@synthesize brushSize = _brushSize;
float brush = 12;
- (id)init {
if (!(self = [super init] ))
return nil;
brushSize = [[NSUserDefaults standardUserDefaults] objectForKey:@"brushKey"];
[self brushChange];
_path = [[UIBezierPath alloc] init];
_path.lineCapStyle=kCGLineCapRound;
_path.lineJoinStyle=kCGLineJoinRound;
[_path setLineWidth:brush];
// _color = [UIColor blackColor];
return self;
}
- (void)draw {
[self.color setStroke];
[self.path stroke];
}
- (void)brushChange { //from notification
brushSize = [[NSUserDefaults standardUserDefaults] objectForKey:@"brushKey"];
//NSLog(@"DrawingPath - brushSize is %@: ", brushSize );
if (brushSize == @"128") brush = 128;
if (brushSize == @"64") brush = 64;
etc
}
@end