2016-11-28 15 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 Simulatorでのみテスト済み)を作成しました。

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:

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

それは、各セルが着色されたシンプルなcollectionViewです。私は細胞の大きさをハードコードしました。

次はDrawingViewを作成しました。これは、ユーザーが指を使って描画するビューです。このビューは、一度に1本の指だけを扱います。私はまず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でコントローラを作成しました。これにより、ユーザはビューをズームイン/スケールし、ズームイン/スケーリングされたビューを描画することができます。ズームアウトすると、図面が正確であることがわかります(歪んだり縮尺されていない)。

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:

+0

私はあなたの例をここで取り上げています。私はすでに色を選択する方法があるので、パレットビューを削除して回答を修正してください。 drawViewという名前のUIView objective-cファイルを追加すると、ハングアップしています。私はエラーを表示し続ける 'UIResponder'がセレクタ 'initWithFrame'を宣言するためのATinterface。私のUIViewcontroller.mにコードを追加した場合と同じことです - 'UIViewController'の表示可能なATinterfaceはセレクタ 'initWithFrame'を宣言しません。 – user2621075

+0

このコードはそのままであることを意図しています。独自のパレットビューをスワップアウトしたい場合は、それを置き換えて代理人を自分自身で置き換えることができます。 UIResponderの問題については、あなたはUIResponderとしてビューへの強い参照を持っています。 UIViewはすでにUIResponderに準拠しているため、UIResponderとして保存する必要はありません。 – Brandon

+0

2つの質問が残っています。描かれている間、線は黒です。これをどのようにして別の色に変えることができますか?拡大表示すると、描画された線がエッジの周りにぼやけて表示されます。このラインをもっとシャープにするにはどうすればいいですか? – user2621075

関連する問題