2010-01-25 5 views
4

Я пытаюсь реализовать масштабируемое масштабирование/выключение для PhotoView (экземпляр UIImageView) с использованием CGAffinTransformScale (планирование использования вращения, поэтому нельзя рассчитывать на фреймы для масштабирования и добавлять subview, поэтому UIScrollView будет более сложный, я думаю). Во всяком случае, концепция была достаточно простой, чтобы понять, и код собрался очень быстро ... С тех пор я пытался решить те же две (связанные!) Проблемы, используя три разных подхода, и не могу этого сделать : 1- Мой код каким-то образом теряет отслеживание количества касаний в середине масштабирования, от count = 2 до count = 1 и обратно на iPhone, но не для симулятора. 2- Точки касания один и два продолжают прыгать назад и вперед по нескольким пикселям на каждом шагу, заставляя изображение сжиматься и увеличиваться последовательно и быстро, хотя в целом эффект является одним из масштабирования или масштабирования в соответствии с запросом пользователя (как iPhone, так и симулятор).iPhone UIImageView pinch zoom

вот код:

#import "PhotoView.h" 


@implementation PhotoView; 
@synthesize originalCenter, distance, zooming; 
- (id)initWithFrame:(CGRect)frame { 
    if (self = [super initWithFrame:frame]) { 
    // Initialization code 
     self.userInteractionEnabled = YES; 
     self.multipleTouchEnabled = YES; 
     zooming = NO; 
    } 
    return self; 
} 

float distanceBetweenTwoPoints(CGPoint point1, CGPoint point2) 
{ 
NSLog(@"point1 x: %5.2f point 2 x: %5.2f ---- point 1 y: %5.2f point 2 y: %5.2f",point1.x,point2.x,point1.y,point2.y); 
    return (sqrt(pow(point1.x -point2.x,2) + pow(point1.y - point2.y,2))); 
} 
-(void) touchesBegan: (NSSet *) touches withEvent:(UIEvent *) event { 

    if ([touches count] > 1) { 

     NSLog(@"^^^^^^^^^^^^^^^Tocuhes began with double touch!"); 

     distance = distanceBetweenTwoPoints([[[touches allObjects] objectAtIndex:0] locationInView:self], 
     [[[touches allObjects] objectAtIndex:1] locationInView:self]); 
     zooming = YES; 
    } 
    else { 
     zooming = NO; 
     origianlCenter = [[[touches allObjects] objectAtIndex:0] locationInView:self]; 
     NSLog(@">>>>>>>>>>>>Touches began with single touch"); 
    } 
} 
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 

    if (zooming) NSLog(@"!!!!!!!!!end zoom!!!!!!!"); 

    zooming = NO; 
    if ([[touches anyObject] tapCount] == 2) { 
     UITouch *thisTouch = [touches anyObject]; 
     CGPoint thisPoint = [thisTouch locationInView:self]; 
    } 
} 

- (void) touchesMoved: (NSSet *) touches withEvent:(UIEvent *) event { 
    if ([touches count] > 1 && zooming) { // ignore if user added a second finger touch 
     float distanceNew = distanceBetweenTwoPoints([[[touches allObjects] objectAtIndex:0]  locationInView:self], 
       [[[touches allObjects] objectAtIndex:1] locationInView:self]); 
     if (distance <= 0.f) { // should never be true - but it is sometimes!!! 
      distance = distanceNew; 
     } 
     float delta = 1.0f + ((distanceNew-distance)/distance); 
     self.transform = CGAffineTransformScale(self.transform, delta, delta); 
     distance = distanceNew; 
    } 
    else { 
     if (zooming) { 
      NSLog(@"*************shouldn't be here********* %d",[touches count]); 
      return; 
     } 
     CGPoint thisPoint = [[[touches allObjects] objectAtIndex:0] locationInView:self]; 
     self.transform = CGAffineTransformTranslate(self.transform, thisPoint.x-originalCenter.x, thisPoint.y-originalCenter.y); 

    } 
} 
- (void)dealloc { 
    [super dealloc]; 
} 
@end 

Журнал выборки:

^^^^^^^^^^^^^^^Tocuhes began with double touch! 
point1 x: 87.33 point 2 x: 235.63 ---- point 1 y: 322.30 point 2 y: 117.09 
point1 x: 90.76 point 2 x: 232.02 ---- point 1 y: 318.29 point 2 y: 123.51 
point1 x: 86.22 point 2 x: 236.71 ---- point 1 y: 323.30 point 2 y: 117.42 
point1 x: 89.51 point 2 x: 232.38 ---- point 1 y: 319.47 point 2 y: 123.47 
point1 x: 84.97 point 2 x: 237.02 ---- point 1 y: 324.48 point 2 y: 116.56 
*************shouldn't be here********* 1 
point1 x: 88.49 point 2 x: 232.52 ---- point 1 y: 321.27 point 2 y: 122.91 
*************shouldn't be here********* 1 
point1 x: 83.95 point 2 x: 237.11 ---- point 1 y: 327.21 point 2 y: 116.96 
!!!!!!!!!end zoom!!!!!!! 

Я начинаю подозревать, что я теряю след из точек касания из-за CGAffinTransformScale; однако я ничего не нашел в Интернете, чтобы предложить, чтобы это было проблемой. Любые подсказки (включая «прочитать документацию по xyz») будут оценены!

Заранее спасибо.

ответ

6

Вообще говоря, всякий раз, когда вы реализуете непрерывное поведение пользовательского интерфейса, вам нужно измерить его против того, что не меняется.

Так что, если ваши прикосновения приводят к изменению преобразования View, вы должны измерить касания против того, что не меняется - например, родительский вид. Таким образом, вместо вызова:

[touch locationInView:self] 

вы должны использовать

[touch locationInView:[self superview]] 

Я не уверен, если это будет исправить вашу проблему, но она устранит одну возможную причину ваших проблем.

+0

Это было! Большое спасибо. – cameron

17

Ответ от левого поля, возможно, но альтернатива может быть, чтобы поместить UIImageView внутри UIScrollView, определить viewForZoomingInScrollView: метод на ваш взгляд прокрутки делегата, и установите maximumZoomScale/minimumZoomScale свойства, и вы будете иметь свой щепотку масштабирование без необходимости выполнять вычисления, чтобы настроить преобразование самостоятельно? Я только что сделал это в недавнем проекте, и он работал хорошо.

+0

Да ... примерно в тысячу раз легче, чем наоборот. Благодаря! – glenc

+0

У Apple есть хорошая документация по этой технике: http://developer.apple.com/library/ios/#DOCUMENTATION/WindowsViews/Conceptual/UIScrollView_pg/ZoomZoom/ZoomZoom.html – Stickley