(iOS)使用UIGestureRecognizer缩放和平移视图

时间:2012-06-19 07:26:39

标签: ios zooming uipangesturerecognizer panning uipinchgesturerecognizer

我正在尝试使用UIGestures执行类似于UIScrollView的缩放和平移。

我的观点来自ON / OFF单元格矩阵,需要能够支持数千个单元格。 drawRect:方法负责将矩阵坐标转换为屏幕坐标。视图具有缩放量的属性和保持偏移的CGPoint。

我想如果我能弄清楚下面的缩放和平移,我应该很好。对不起下面的代码墙,但它代表了一个完整的实现,它反映了我更复杂的程序。

现在,缩放可以缩放所有内容,但它需要一种自我居中的方式,就像UIScrollView缩放一样。

平移根本不起作用。


ZoomView.h

ZoomView负责绘制bool矩阵。

#import <Foundation/Foundation.h>
#import "ZoomModel.h"

@interface ZoomView : UIView
{
    ZoomModel *m;
}
@property (nonatomic) float zoomScale;
@property (nonatomic) CGPoint offset;

- (id)initWithFrame:(CGRect)frame
           andModel:(ZoomModel *)model;

- (BOOL)checkCellAt:(float)x
               andY:(float)y;

- (CGSize)resize;

@end


ZoomView.m

drawRect:方法执行计算以确定哪个矩阵元素应位于屏幕的可见部分。屏幕的可见部分由zoomScale和偏移确定。

#import "ZoomView.h"
#import <QuartzCore/QuartzCore.h>

@implementation ZoomView
@synthesize zoomScale, offset, holdZoom;

- (id)initWithFrame:(CGRect)frame
           andModel:(ZoomModel *)model
{
    self = [super initWithFrame:frame];
    if (self) {
        m = model;
        zoomScale = 1.0;
        offset = CGPointMake(0, 0);
    }
    return self;
}

- (void)setZoomScale:(float)s
{
    zoomScale *= s;
    if (zoomScale < 1.0) {
        zoomScale = 1.0;
    }
}

- (void)setOffset:(CGPoint)o
{
    //This function is to make sure we don't pan outside the content range
    //it needs some work, I'm having trouble getting the panning to work
    float size = m.cellSize * zoomScale;
    offset = o;
    if ((offset.x - self.frame.size.width/size) <= 0) {
        //offset.x = self.frame.size.width;
        NSLog(@"X MIN");
    }
    if ((offset.x + self.frame.size.width/size) >= (m.gridLength*size)) {
       // offset.x = (m.gridLength*size) - self.frame.size.width;
        NSLog(@"X MAX");
    }
    if ((offset.y - self.frame.size.height/size) <= 0) {
        //offset.y = self.frame.size.height;
        NSLog(@"Y MIN");
    }
    if ((offset.y + self.frame.size.height/size) >= (m.gridLength*size)) {
       // offset.y = (m.gridHeight*size) - self.frame.size.height;
        NSLog(@"Y MAX");
    }
}

- (BOOL)checkCellAt:(float)x
               andY:(float)y
{
    int X = (int)(x/m.cellSize * zoomScale);
    int Y = (int)(y/m.cellSize * zoomScale);

    return [m cellAtX:X andY:Y];
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    [[UIColor blackColor] setFill];
    CGContextFillRect(ctx, rect);

    float size = m.cellSize * zoomScale;
    [[UIColor whiteColor] setFill];

    float a = offset.x;
    float b = offset.y;

    //the -5 is there to give a little buffer so that half cells can be seen
    // -a is taken because the offset is negative
    int startX = (int)(-a/size) - 5;
    int startY = (int)(-b/size) - 5;

    int endX = (int)(startX) + (int)(rect.size.width/size) + 10;
    int endY = (int)(startY) + (int)(rect.size.height/size) + 10;

    if (startX < 0)
        startX = 0;
    if (startY < 0)
        startY = 0;
    if (endX > m.gridLength)
        endX = m.gridLength;
    if (endY > m.gridHeight)
        endY = m.gridHeight;

    [[UIColor whiteColor] setFill];

    for (float i=startX; i<endX; ++i) {
        for (float j=startX; j<endY; ++j) {
            if ([m cellAtX:(int)i andY:(int)j]) {
                //ii and jj are there to make the drawing start on the top left corner of the view
                float ii = i - startX;
                float jj = j - startY;
                CGRect cell = CGRectMake(size*ii, size*jj, size, size);
                CGContextFillRect(ctx, cell);
            }
        }
    }
}
@end


ZoomViewController.h

此视图控制器包含手势识别器和处理程序

#import <Foundation/Foundation.h>
#import "ZoomModel.h"
#import "ZoomView.h"

@interface ZoomViewController : UIViewController  <UIGestureRecognizerDelegate>
{
    ZoomModel *m;
    ZoomView *v;
}

- (void)handleZoom:(UIPinchGestureRecognizer *)recognizer;
- (void)handlePan:(UIPanGestureRecognizer *)recognizer;

@end


ZoomViewController.m

zoomView设置在UIView中,屏幕框架作为其框架。 zoomView本身比屏幕略大,允许绘制半个单元格。

#import "ZoomViewController.h"
#import <QuartzCore/QuartzCore.h>

@implementation ZoomViewController

- (void)loadView
{
    CGRect screenRect = [[UIScreen mainScreen] bounds];

    UIView *mainView = [[UIView alloc] initWithFrame:screenRect];

    float cellSize = 1;
    int ni = (int)(screenRect.size.width/cellSize);
    int nj = (int)(screenRect.size.height/cellSize);

    CGRect zoomRect = CGRectMake(0, 0, 1.2*screenRect.size.width, 1.2*screenRect.size.height);

    m = [[ZoomModel alloc] initWithLength:ni andHeight:nj andCellSize:cellSize];
    v = [[ZoomView alloc] initWithFrame:zoomRect andModel:m];
    v.center = CGPointMake(v.frame.size.width/2.0, v.frame.size.height/2.0);

    UIPinchGestureRecognizer *zRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self
                                                                                      action:@selector(handleZoom:)];
    zRecognizer.delegate = self;
    [v addGestureRecognizer:zRecognizer];

    UIPanGestureRecognizer *pRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self
                                                                                  action:@selector(handlePan:)];
    [pRecognizer setMaximumNumberOfTouches:1];
    [pRecognizer setMinimumNumberOfTouches:1];

    pRecognizer.delegate = self;
    [v addGestureRecognizer:pRecognizer];

    [mainView addSubview:v];

    [self setView:mainView];
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
{        
    return YES;
}

- (void)handleZoom:(UIPinchGestureRecognizer *)recognizer
{
    [v setZoomScale:recognizer.scale];

    //need code to zoom around the center instead of the top left corner
    recognizer.scale = 1;
    [v setNeedsDisplay];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    //Adjusts the offset of the view, which is used in its drawRect:
    CGPoint translation = [recognizer translationInView:self.view];
    CGPoint newOffset = CGPointMake(v.offset.x - translation.x, v.offset.y - translation.y);
    [v setOffset:newOffset];
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
    [v setNeedsDisplay];
}
@end


ZoomModel.h

这个类只是用随机的ON / OFF值填充一个bool矩阵,这样我们就可以在屏幕上看到一些东西它在我的访问器方法中模拟了我更复杂的app模型。

#import <Foundation/Foundation.h>

@interface ZoomModel : NSObject
{
    bool *grid;
}

@property (nonatomic) int gridLength;
@property (nonatomic) int gridHeight;
@property (nonatomic) float cellSize;

- (id)initWithLength:(int)l
           andHeight:(int)h
         andCellSize:(float)s;

- (BOOL)cellAtX:(int)x
           andY:(int)y;
@end


ZoomModel.m

#import "ZoomModel.h"

@implementation ZoomModel
@synthesize gridHeight, gridLength, cellSize;

- (id)initWithLength:(int)l
           andHeight:(int)h
         andCellSize:(float)s
{
    self = [super init];
    if (self) {
        grid = malloc(l*h*sizeof(bool));
        gridHeight = h;
        gridLength = l;
        cellSize = s;

        for (int i=0; i<h*l; i++) {
            if (arc4random()%6 >= 4)
                grid[i] = true;
            else 
                grid[i] = false;
        }
    }
    return self;
}

- (BOOL)cellAtX:(int)x andY:(int)y
{
    return (BOOL)grid[x*gridLength + y];
}
@end

0 个答案:

没有答案