2016-11-28 4 views
0

J'ai un problème en essayant d'esquisser sur un UIView qui est une vue enfant dans un UIScrollView.Esquisse sur UIView dans UIScrollView

Le problème se produit lorsque vous essayez d'esquisser sur le UIView après qu'il a été zoomé ou fait défiler. Il semble que mon code d'esquisse (ci-dessous) ne prenne pas en compte le zoom ou l'échelle du UIView au sein du UIScrollView car les lignes floues ne s'affichent pas comme elles le devraient. S'il vous plaît laissez-moi savoir s'il y a quelque chose qui peut être fait à mon code ou fournir une autre solution.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

     NSLog(@"Draw touchesBegan"); 

     mouseSwipedPSVC = NO; 
     UITouch *touch = [touches anyObject]; 
     lastPointPSVC = [touch locationInView:sheetDrawView]; 

} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 

     mouseSwipedPSVC = YES; 
     UITouch *touch = [touches anyObject]; 
     CGPoint currentPoint = [touch locationInView:sheetDrawView]; 

     UIGraphicsBeginImageContext(sheetDrawView.frame.size); 
     [drawImageView.image drawInRect:CGRectMake(0, 0,  sheetDrawView.frame.size.width, sheetDrawView.frame.size.height)]; 
     CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPointPSVC.x, lastPointPSVC.y); 
     CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y); 
     CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound); 
     CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brushPSVC); 
     CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), redPSVC, greenPSVC, bluePSVC, 1.0); 
     CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal); 

     CGContextStrokePath(UIGraphicsGetCurrentContext()); 
     drawImageView.image = UIGraphicsGetImageFromCurrentImageContext(); 
     drawImageView.image = UIGraphicsGetImageFromCurrentImageContext(); 
     [drawImageView setAlpha:opacityPSVC]; 
     UIGraphicsEndImageContext(); 

     lastPointPSVC = currentPoint; 

} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 

    if(!mouseSwipedPSVC) { 
     NSLog(@"Check 1"); 

     UIGraphicsBeginImageContext(sheetDrawView.frame.size); 
     [drawImageView.image drawInRect:CGRectMake(0, 0, sheetDrawView.frame.size.width, sheetDrawView.frame.size.height)]; 
     CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound); 
     CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brushPSVC); 
     CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), redPSVC, greenPSVC, bluePSVC, opacityPSVC); 
     CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPointPSVC.x, lastPointPSVC.y); 
     CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPointPSVC.x, lastPointPSVC.y); 
     CGContextStrokePath(UIGraphicsGetCurrentContext()); 
     CGContextFlush(UIGraphicsGetCurrentContext()); 
     drawImageView.image = UIGraphicsGetImageFromCurrentImageContext(); 
     UIGraphicsEndImageContext(); 

    } 

} 

Je dois ajouter que ce code fonctionne bien si le UIView n'a pas été zoomé ou sur défiler. SheetDrawView est également une sous-vue du UIScrollView.

+0

Appliquez une AffineTransform pour redimensionner la vue de la même manière que le zoom de la vue défilante. Puis essayez de dessiner? – Brandon

+0

On dirait un bon plan. Pouvez-vous fournir un exemple de code pour AffineTransform avec lequel je peux travailler et je serai heureux d'essayer? – user2621075

Répondre

1

Créé une petite application de dessin (Testé uniquement sur iPhone 7 Plus 10.1 Simulator).

enter image description here

D'abord, je créé le PalleteView. Cette vue vous permet de sélectionner les couleurs à dessiner.

PaletteView.h:

// 
// PaletteView.h 
// DrawingIO 
// 
// Created by Brandon T on 2016-11-27. 
// Copyright © 2016 XIO. All rights reserved. 
// 

#import <UIKit/UIKit.h> 

@class PaletteView; 

@protocol PaletteViewDelegate <NSObject> 
- (void)didSelectColour:(PaletteView * _Nonnull)paletteView colour:(UIColor * _Nonnull)colour; 
@end 

@interface PaletteView : UIView 
@property (nullable, nonatomic, weak) id<PaletteViewDelegate> delegate; 
@end 

PaletteView.m:

// 
// PaletteView.m 
// DrawingIO 
// 
// Created by Brandon T on 2016-11-27. 
// Copyright © 2016 XIO. All rights reserved. 
// 

#import "PaletteView.h" 

#define kPaletteViewCell @"kPaletteViewCell" 

@interface PaletteView() <UICollectionViewDelegate, UICollectionViewDataSource> 
@property (nonnull, nonatomic, strong) UICollectionView *collectionView; 
@property (nonnull, nonatomic, strong) NSArray<NSArray<UIColor *> *> *colours; 
@end 

@implementation PaletteView 
- (instancetype)initWithFrame:(CGRect)frame { 
    if ((self = [super initWithFrame:frame])) { 
     [self initControls]; 
     [self setTheme]; 
     [self registerClasses]; 
     [self doLayout]; 
    } 
    return self; 
} 

- (void)initControls { 

    CGFloat idealWidth = (self.frame.size.width/7.0) - (2.5 * 5.0); 
    CGFloat idealHeight = (self.frame.size.height/2.0) - (2.5 * 5.0); 

    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; 
    layout.minimumLineSpacing = 5.0; 
    layout.minimumInteritemSpacing = 5.0; 
    layout.sectionInset = UIEdgeInsetsMake(5.0, 5.0, 5.0, 5.0); 
    layout.scrollDirection = UICollectionViewScrollDirectionVertical; 
    layout.itemSize = CGSizeMake(idealWidth, idealHeight); 

    self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; 

    self.colours = @[@[[UIColor blackColor], 
        [UIColor darkGrayColor], 
        [UIColor lightGrayColor], 
        [UIColor whiteColor], 
        [UIColor grayColor], 
        [UIColor redColor], 
        [UIColor greenColor]], 

        @[[UIColor blueColor], 
        [UIColor cyanColor], 
        [UIColor yellowColor], 
        [UIColor magentaColor], 
        [UIColor orangeColor], 
        [UIColor purpleColor], 
        [UIColor brownColor]]]; 
} 

- (void)setTheme { 
    [self.collectionView setDelegate:self]; 
    [self.collectionView setDataSource:self]; 
    [self.collectionView setAlwaysBounceHorizontal:YES]; 
    [self.collectionView setDelaysContentTouches:NO]; 
    [self.collectionView setShowsHorizontalScrollIndicator:NO]; 
    [self.collectionView setShowsVerticalScrollIndicator:NO]; 
    [self.collectionView setBackgroundColor:[UIColor colorWithRed:240.0/255.0 green:229.0/255.0 blue:227.0/255.0 alpha:1.0]]; 
} 

- (void)registerClasses { 
    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:kPaletteViewCell]; 
} 

- (void)doLayout { 
    [self addSubview:self.collectionView]; 

    [self.collectionView.leftAnchor constraintEqualToAnchor:self.leftAnchor].active = YES; 
    [self.collectionView.rightAnchor constraintEqualToAnchor:self.rightAnchor].active = YES; 
    [self.collectionView.topAnchor constraintEqualToAnchor:self.topAnchor].active = YES; 
    [self.collectionView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor].active = YES; 

    [self.collectionView setTranslatesAutoresizingMaskIntoConstraints:NO]; 
} 

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 
    return self.colours.count; //Two rows of colours. 
} 

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 
    return [self.colours[section] count]; //7 colours per row in this example. 
} 

- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 

    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kPaletteViewCell forIndexPath:indexPath]; 

    NSArray *section = [self.colours objectAtIndex:indexPath.section]; 
    [cell.contentView setBackgroundColor:section[indexPath.row]]; 

    return cell; 
} 

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 
    if ([self.delegate respondsToSelector:@selector(didSelectColour:colour:)]) { 
     NSArray *section = [self.colours objectAtIndex:indexPath.section]; 
     [self.delegate didSelectColour:self colour:section[indexPath.row]]; 
    } 
} 
@end 

Il est un simple CollectionView chaque cellule étant colorée. J'ai codé en dur les tailles des cellules.

Ensuite, j'ai créé le DrawingView. C'est la vue que l'utilisateur utilisera avec son doigt. Cette vue ne gère qu'un seul doigt à la fois. J'ai pris l'idée de dessiner à un bitmap d'abord à partir de GameDesign. Dans les jeux, vous voulez d'abord dessiner des textures en mémoire. Puis, lorsque vous avez fini de dessiner, vous faites passer ce cadre à l'écran. Cela améliore considérablement la vitesse car vous ne mettez pas à jour l'écran après chaque opération. Au lieu de cela, vous mettez à jour l'écran à la fin de tous les dessins (lorsque l'utilisateur lève le doigt).

Pour ce faire, je l'ai fait ce qui suit:

DrawingView.h:

// 
// DrawingView.h 
// DrawingIO 
// 
// Created by Brandon T on 2016-11-27. 
// Copyright © 2016 XIO. All rights reserved. 
// 

#import <UIKit/UIKit.h> 

@interface DrawingView : UIView 
- (void)setPaletteColour:(UIColor * _Nonnull)colour; 
@end 

DrawingView.m:

// 
// DrawingView.m 
// DrawingIO 
// 
// Created by Brandon T on 2016-11-27. 
// Copyright © 2016 XIO. All rights reserved. 
// 

#import "DrawingView.h" 

@interface DrawingView() 
@property (nonnull, nonatomic, strong) UIBezierPath *path; 
@property (nonnull, nonatomic, strong) UIImage *bufferedImage; 
@property (nonnull, nonatomic, strong) UIColor *strokeColour; 
@end 

@implementation DrawingView 

- (instancetype)initWithFrame:(CGRect)frame { 
    if ((self = [super initWithFrame:frame])) { 

     [self setPath:[UIBezierPath bezierPath]]; 
     [self.path setLineWidth:1.0]; 

     [self setStrokeColour:[UIColor blackColor]]; 
     [self setMultipleTouchEnabled:NO]; 
    } 
    return self; 
} 

- (void)setPaletteColour:(UIColor *)colour { 
    self.strokeColour = colour; 
} 

- (void)renderToBufferedImage { 
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0); 

    [self.strokeColour setStroke]; 
    [self.bufferedImage drawAtPoint:CGPointZero]; 
    [self.path stroke]; 

    self.bufferedImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
} 



- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    [self.path moveToPoint:[touch locationInView:self]]; 
} 

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    [self.path addLineToPoint:[touch locationInView:self]]; 
    [self setNeedsDisplay]; 
} 

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    [self.path addLineToPoint:[touch locationInView:self]]; 
    [self renderToBufferedImage]; 
    [self setNeedsDisplay]; 
    [self.path removeAllPoints]; 
} 

- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    [self.path addLineToPoint:[touch locationInView:self]]; 
    [self renderToBufferedImage]; 
    [self setNeedsDisplay]; 
    [self.path removeAllPoints]; 
} 

- (void)drawRect:(CGRect)rect { 
    [self.strokeColour setStroke]; 
    [self.bufferedImage drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0]; 
    [self.path stroke]; 
} 

@end 

Je choisi d'utiliser drawInRect:blendMode:alpha parce que cela vous permettra de dessiner avec différentes options de mélange et niveaux alpha. Pour cet exemple, je dessine des bitmaps BRAA 32 bits entièrement opaques.

Ensuite, j'ai créé le contrôleur avec un ScrollView intégré. Cela permet à l'utilisateur de ZOOM-IN/mettre à l'échelle la vue ET dessiner sur la vue zoomée/mise à l'échelle. Lorsque vous effectuez un zoom arrière, vous remarquerez que le dessin est exact (pas déformé ou mis à l'échelle).

ViewController.h:

// 
// ViewController.h 
// DrawingIO 
// 
// Created by Brandon T on 2016-11-27. 
// Copyright © 2016 XIO. All rights reserved. 
// 

#import <UIKit/UIKit.h> 

@interface ViewController : UIViewController 


@end 

viewController.m:

// 
// ViewController.m 
// DrawingIO 
// 
// Created by Brandon T on 2016-11-27. 
// Copyright © 2016 XIO. All rights reserved. 
// 

#import "ViewController.h" 
#import "PaletteView.h" 
#import "DrawingView.h" 

@interface ViewController() <UIScrollViewDelegate, PaletteViewDelegate> 
@property (nonnull, nonatomic, strong) PaletteView *paletteView; 
@property (nonnull, nonatomic, strong) DrawingView *drawingView; 
@property (nonnull, nonatomic, strong) UIScrollView *scrollView; 
@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    [self initControls]; 
    [self setTheme]; 
    [self doLayout]; 
} 


- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 


- (void)initControls { 
    self.paletteView = [[PaletteView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 100.0)]; 
    self.drawingView = [[DrawingView alloc] initWithFrame:self.view.frame]; 
    self.scrollView = [[UIScrollView alloc] init]; 
} 

- (void)setTheme { 
    [self.paletteView setDelegate:self]; 
    [self.paletteView setBackgroundColor:[UIColor whiteColor]]; 
    [self.drawingView setBackgroundColor:[UIColor whiteColor]]; 

    [self.scrollView setDelegate:self]; 
    [self.scrollView setScrollEnabled:NO]; 
    [self.scrollView setMinimumZoomScale:1.0]; 
    [self.scrollView setMaximumZoomScale:2.0]; 
} 

- (void)doLayout { 
    [self.view addSubview:self.paletteView]; 
    [self.view addSubview:self.scrollView]; 

    [self.paletteView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES; 
    [self.paletteView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor].active = YES; 
    [self.paletteView.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES; 

    [self.scrollView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES; 
    [self.scrollView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor].active = YES; 
    [self.scrollView.topAnchor constraintEqualToAnchor:self.paletteView.bottomAnchor].active = YES; 
    [self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES; 

    [self.scrollView setTranslatesAutoresizingMaskIntoConstraints:NO]; 


    //Layout drawingView 
    [self.scrollView addSubview:self.drawingView]; 
} 

- (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { 
    return self.drawingView; 
} 

- (void)didSelectColour:(PaletteView * _Nonnull)paletteView colour:(UIColor * _Nonnull)colour { 
    [self.drawingView setPaletteColour:colour]; 
} 
@end 
+0

Je travaille sur votre exemple ici. Cela vous dérange de réviser votre réponse en éliminant la palette, vu que j'ai déjà une méthode pour choisir une couleur. Je suis aussi en train de raccrocher quand j'ajoute le fichier UIView-objectif nommé drawView. Je continue d'obtenir une erreur non visible ATinterface pour 'UIResponder' déclare le sélecteur 'initWithFrame'. Même chose si j'ajoute du code à mon UIViewcontroller.m - aucun ATinterface visible pour 'UIViewController' ne déclare le sélecteur 'initWithFrame'. – user2621075

+0

Ce code est censé être tel quel. Si vous souhaitez remplacer la palette par la vôtre, vous pouvez la remplacer et remplacer celle-ci par la vôtre. En ce qui concerne le problème UIResponder. Vous avez une référence forte à la vue en tant que UIResponder. UIView est déjà conforme à UIResponder, il n'est donc pas nécessaire de le stocker comme UIResponder. – Brandon

+0

Deux questions restantes. Les lignes sont noires en étant dessinées. Comment puis-je changer cela pour être une couleur différente? Les lignes tracées apparaissent floues sur les bords lors d'un zoom avant. Comment puis-je rendre cette ligne plus nette/plus propre? – user2621075