繁体   English   中英

在UIScrollView中的UIView上绘制草图

[英]Sketch On UIView Within UIScrollView

尝试在作为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的子视图。

创建了一个小型绘图应用程序(仅在iPhone 7 Plus 10.1 Simulator上测试过)。

在此处输入图片说明

首先,我创建了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。 这是用户将使用其手指绘制的视图。 此视图一次只能处理一个手指。 我首先想到了从GameDesign绘制到位图的想法。 在游戏中,您要先将纹理绘制到内存中。 然后,当您完成所有绘图时,便将该框架Blit到屏幕上。 因为您不需要在每次操作后都更新屏幕,所以可以显着提高速度。 而是在所有图形的末尾(当用户抬起手指时)更新屏幕。

为此,我做了以下工作:

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因为这将允许您使用不同的混合选项和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:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM