2016-11-28 5 views
0

UIScrollView의 하위 뷰 인 UIView에서 스케치 할 때 문제가 있습니다.UIScrollView 내에서 UIView에 스케치

UIView을 확대/축소하거나 스케치 한 후 스케치를 시도하면이 문제가 발생합니다. 내 스케치 코드 (아래 참조)는 UIScrollView 안에있는 UIView의 확대/축소 또는 축소를 고려하지 않으므로 선이 흐려 지거나 나타나지 않아야합니다. 내 코드에 대해 수행 할 수있는 작업이나 다른 솔루션을 제공 할 수 있는지 알려주십시오.

- (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(); 

    } 

} 

나는 UIView이 확대거나 스크롤되지 않은 경우이 코드가 잘 작동하는지 추가해야합니다. 또한 sheetDrawView는 UIScrollView의 하위 뷰입니다.

+0

AffineTransform을 적용하여 뷰의 배율을 scrollView의 줌과 동일하게 조정합니다. 그럼 그림 그리기? – Brandon

+0

좋은 계획 같아요. 내가 할 수있는 AffineTransform을위한 샘플 코드를 제공해 주시겠습니까? – user2621075

답변

1

작은 드로잉 응용 프로그램을 만들었습니다 (iPhone 7 Plus 10.1 시뮬레이터에서만 테스트되었습니다).

enter image description here

먼저 나는 PalleteView를 만들었습니다. 이 뷰에서는 그릴 색을 선택할 수 있습니다.

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 : 그것은 각 셀에 간단한 collectionView 착색되는 것

// 
// 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 

. 나는 세포의 크기를 하드 코드했다.

다음으로 나는 DrawingView를 만들었습니다. 이것은 사용자가 손가락을 사용하여 그림을 그립니다. 이보기는 한 번에 한 손가락 만 처리합니다. 저는 먼저 GameDesign에서 드로잉 아이디어를 비트 맵으로 가져갔습니다. 게임에서는 먼저 텍스처를 메모리에 그려야합니다. 그런 다음 모든 도면 작업을 마쳤 으면 그 프레임을 화면에 표시합니다. 모든 작업 후에 화면을 업데이트하지 않으므로 속도가 크게 향상됩니다. 대신, 모든 도면의 끝에서 사용자가 손가락을 들었을 때 화면을 업데이트하고 있습니다.

는이를 위해, 나는 다음을했다 :

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 

내가 그에게 당신을 허용하기 때문 drawInRect:blendMode:alpha를 사용하기로 결정했습니다 다른 혼합 옵션과 알파 레벨로 그립니다. 이 예제에서는 완전히 불투명 한 32 비트 BGRA 비트 맵을 그립니다.

다음으로 필자는 내장 된 ScrollView를 사용하여 컨트롤러를 만들었습니다. 이를 통해 사용자는 뷰를 ZOOM-IN/Scale하고 줌 - 인/스케일 된 뷰를 그릴 수 있습니다. 확대/축소하면 도면이 정확함을 알 수 있습니다 (왜곡되거나 축소되지 않음).

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

나는 여기서 당신의 예를 연구 중이다. 팔레트보기를 제거하여 답을 수정 하시겠습니까? 이미 색상을 선택하는 방법이 있습니다. 나는 또한 drawView라는 UIView objective-c 파일을 추가 할 때 끊었습니다. 난 오류 표시 점점 'UIResponder'선택기 'initWithFrame'선언 ATinterface. 내 UIViewcontroller.m에 코드를 추가하는 경우와 동일한 작업 - 'UIViewController'의 표시 가능한 ATinterface가 선택기 'initWithFrame'을 선언하지 않습니다. – user2621075

+0

이 코드는있는 그대로의 의미입니다. 직접 팔레트보기를 바꾸려면 대신 팔레트보기를 바꾸고 자신 만의 델리게이트로 바꿀 수 있습니다. UIResponder 문제에 관해서. UIResponder로보기에 대한 강력한 참조가 있습니다. UIView는 이미 UIResponder를 준수하므로 UIResponder로 저장할 필요가 없습니다. – Brandon

+0

두 가지 질문이 남아 있습니다. 그려지는 동안 선은 검은 색입니다. 이 색상을 다른 색상으로 어떻게 바꿀 수 있습니까? 확대했을 때 그려진 선이 가장자리 주위에 흐리게 나타납니다. 이 선을 더 선명하게/깨끗하게하려면 어떻게합니까? – user2621075