UIScrollView,可绘制视图作为子视图



我有一个应用程序,它由一个主UIScrollView和一个变量"组成;页面";子视图。每个页面都包含一个imageView、一些按钮和一个名为drawView的UIView子类,该子类负责绘制UIImageView(使用touchesBegin、touchesMoved和tochesEnded(,允许用户在页面上做笔记
不幸的是,由于所有页面都是uiscrollview的子视图,所以我的drawView无法访问
我在主界面上有一个按钮可以启用高亮显示模式,点击后我想禁用所有UIScrollView事件,这样所有事件都会转到我的drawView
我已尝试将userInteractionEnabled设置为主滚动视图,但由于我的视图是UIScrollView的子视图,因此我的drawView也不会收到任何触摸,如果我禁用滚动,也是如此。

有人对如何解决我的问题并实现它有什么建议吗?

别担心,让它变得简单。

创建一个自定义UIView类,该类将分配一个CALayer来放置UIImage,并分配第二个CALayer来在其上显示未来的图形。两个CALayer都可以放置在彼此的顶部。假设您知道如何处理图形图层的透明度。

由于两个可见部分都在一个UIView中,因此您可以继续使用
-touchesBegin:
-touchesMoved:
-touchesEnded:并处理您的BezierPath或您想要抓住手指/笔的方式。

现在要小心,用-drawRect:缩小重新绘制的CGRect大小,这样它看起来仍然很好,不会再次绘制整个图像缓冲区,这会使它更快一点。

当您在一个视图中处理两个Layers时,您可以继续使用UIScrollView,但您将使用新的CustomViewClass而不是UIViews。那么你就不需要UIImageView了。

类似的东西。

@import UIKit;
@interface ImageDrawingUIView : UIView
-(instancetype)initWithFrame:(CGRect)frame andImage:(UIImage*)img;
@property (nonatomic) UIImage *image;
@property (nonatomic) CALayer *drawLayer;
@end

#import "ImageDrawingUIView.h"
@implementation ImageDrawingUIView {
UIImage* _painting;
NSMutableArray<NSValue *> *points;
NSUInteger strokes;
}
-(instancetype)initWithFrame:(CGRect)frame andImage:(UIImage *)img {
if (!(self=[super initWithFrame:frame])) return nil;
_image = img;

CALayer *imgLayer = [CALayer layer];
imgLayer.drawsAsynchronously = YES;
imgLayer.frame = frame;
imgLayer.contents = img;
[self.layer addSublayer:imgLayer];

_drawLayer = [CALayer layer];
_drawLayer.drawsAsynchronously = YES;
_drawLayer.frame = frame;
[self.layer addSublayer:_drawLayer];
_drawLayer.contents = (__bridge id _Nullable)[self paintingImage].CGImage;

points = [NSMutableArray new];

return self;
}
-(UIImage*)imageFromPoints {
// do the CGContext image creation from array of points here
CGSize size = CGSizeMake(66, 66);
const CGFloat mid = size.width * 0.5;
CGFloat f = 1.4;

UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetLineWidth(context, 1.5);
CGContextSetLineCap(context, kCGLineCapSquare);

int strokeNum = 0;
for (int p = 0; p < [points count]; p++) {
// NSValues can store CGPoints, the points Array contains NSValues.
NSValue *value = points[p];
CGPoint dot = [value CGPointValue];
CGPoint point = CGPointMake(mid + (dot.x*f) * mid, mid + (dot.y*f) * mid);
if (strokes > strokeNum) {
CGContextMoveToPoint(context, point.x, point.y);
CGContextAddRect(context, CGRectMake(point.x - 1.5, point.y - 1.5, 3, 3));
strokeNum++;
} else {
CGContextAddLineToPoint(context, point.x, point.y);
}
}

CGContextStrokePath(context);
CGContextRestoreGState(context);
UIImage *i = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return i;
}
-(UIImage*)paintingImage {
if (!_painting) {
_painting = [self imageFromPoints];
}
return _painting;
}
// following code is not complete, just showing the methods
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// capture first finger, store first point in a array of CGPoints
[points addObject:[NSValue valueWithCGPoint: /*touches*/ CGPointMake(0, 0)]];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// capture first finger, store in array of CGPoints
[points addObject:[NSValue valueWithCGPoint: /*touches*/ CGPointMake(0, 0)]];
_painting = [self imageFromPoints]; // update painted image
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// capture first finger, store in array and arrange the next finger is another array
[points addObject:[NSValue valueWithCGPoint: /*touches*/ CGPointMake(0, 0)]];
// apply new painting to CALayer again
_drawLayer.contents = (__bridge id _Nullable)(_painting.CGImage);
}
@end

你可以像一样在UIScrollView中分配它

NSUInteger pages = 0;
ImageDrawingUIView *page = [[ImageDrawingUIView alloc] initWithFrame:CGRectMake(0,pages*pageHeight,width,height) andImage:[UIImage imageWithContentsOfFile:@"filename"]];
pages++;
[self addSubView:page];

哦,我不想把所有的快乐都花在你自己编码上。:(

PS:initWithFrame:andImage:仍然有空间分配按钮和顶部所需的东西,并与CustomUIView的内容交互。

最新更新