UIScrollView上的旋转手势

时间:2015-11-06 07:23:56

标签: objective-c uiscrollview rotation uigesturerecognizer

我正在使用手势进行滚动视图。我在Scroll View中添加了一个UIView,其大小等于ScrollView内容大小。我想在视图上应用捏合手势和旋转手势,这是ScrollView的子视图。我通过使用ScrollView的zoom属性和委托完成了捏手势的工作,这给了我想要的相同效果。但旋转手势正在创造问题。当我在视图上添加旋转手势时,滚动视图的缩放也会受到干扰。

那么我如何在Scroll View的子视图中应用捏合手势和旋转手势,其子大小必须最初等于ScrollView的内容大小。

任何人都可以给我这样做的方法!

这是.m文件的代码,当我们旋转视图时它变得不可见

#import "ViewController.h"

@interface ViewController ()
{
    UIView *backgroundView;
    UIScrollView *scrollView;
    CGFloat lastRotation;
}
@end

@implementation ViewController

-(void)loadView
{
    [super loadView];

    //Scroll View
    scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
    scrollView.contentSize = self.view.frame.size;
    scrollView.delegate = self;
    scrollView.backgroundColor = [UIColor grayColor];

    //Zooming factors of the Scroll View
    scrollView.minimumZoomScale = 1.0;
    scrollView.maximumZoomScale = 5.0f;
    scrollView.zoomScale = 1.0;

    [self.view addSubview:scrollView];

    //Scroll View's subview
    backgroundView = [[UIView alloc] initWithFrame:scrollView.frame];
    [backgroundView setBackgroundColor:[UIColor orangeColor]];
    [scrollView addSubview:backgroundView];

    UIRotationGestureRecognizer *bgRotationGstr = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotateBackgroundView:)];
    bgRotationGstr.delegate = self;
    bgRotationGstr.cancelsTouchesInView = NO;
    [backgroundView addGestureRecognizer:bgRotationGstr];

    //Child of background view
    UIView *childView = [[UIView alloc] initWithFrame:CGRectMake(20, 50, 100, 100)];
    childView.backgroundColor = [UIColor grayColor];
    [backgroundView addSubview:childView];

}

//Rotation of the background view
-(void)rotateBackgroundView:(UIRotationGestureRecognizer*)gesture
{
    CGFloat rotation = 0.0 - (lastRotation - [(UIRotationGestureRecognizer*)gesture rotation]);

    CGAffineTransform currentTransform = backgroundView.transform;
    CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform,rotation);

    [backgroundView setTransform:newTransform];

    lastRotation = [(UIRotationGestureRecognizer*)gesture rotation];

    if (gesture.state == UIGestureRecognizerStateBegan || gesture.state == UIGestureRecognizerStateChanged)
    {
        scrollView.scrollEnabled = NO;
    }
    else if (gesture.state == UIGestureRecognizerStateEnded)
    {
        lastRotation = 0.0;
        scrollView.scrollEnabled = YES;
        return;
    }
}

#pragma mark<UIScrollViewDelegate>

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return backgroundView;
}

#pragma mark<UIGetsureRecognizer>
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    return YES;
}
@end

4 个答案:

答案 0 :(得分:2)

经过多天的努力,我找到了一个明确的解决方案,以便将UIScrollView集成缩放行为与UIRotationGestureRecognizer一起使用,就像魅力一样。您必须添加容器虚拟视图作为滚动视图的子视图,并将UIImageView作为容器视图的子视图。然后,返回 viewForZoomingInScrollView 方法中的容器视图,并将UIRotationGestureRecognizer添加到scrollview,将CGAffineTransformRotate应用于UIImageView。最后,在 shouldRecognizeSimultaneouslyWithGestureRecognizer 方法中返回true。通过这种方式,scrollView将捕获两个手指的旋转手势和缩放到缩放手势:缩放将应用于虚拟视图并旋转到uiimageview,而不会发生转换之间的冲突。

在代码中:让我们考虑让UIViewController呈现一个UIScrollView。我们想要使用scrollview的缩放行为以及UIImageView旋转。

1)包含UIScrollView的控制器(或任何其他对象)必须符合UIGestureRecognizerDelegate协议。

在myViewController.h中

@interface myViewController : UIViewController < UIGestureRecognizerDelegate> {
}

2)创建UIScrollView,将虚拟视图添加为子视图,最后添加UIImageView作为虚拟视图的子视图。

在myViewController.m

//Scrollview
myScrollView=[[UIScrollView alloc] initWithFrame:CGRectMake(0,0, view.frame.size.width, view.frame.size.height)];
myScrollView.delegate=self;
[view addSubview:myScrollView];

//Dummy View
UIView *dummyView=[[UIView alloc] initWithFrame:CGRectMake(0, 0, myScrollView.frame.size.width, myScrollView.frame.size.height)];
[self addSubview:dummyView];

//ImageView
imageView=[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, dummyView.frame.size.width, dummyView.frame.size.height)];
imageView.contentMode=UIViewContentModeScaleAspectFit;        
[dummyView addSubview:imageView];

//Add rotation gesture to the scrollView
rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotate:)];
[myScrollView addGestureRecognizer:_rotationGestureRecognizer];

//Set the controller as delegate of the recognizer
rotationGestureRecognizer.delegate=self;


[...]


#pragma UIScrollViewDelegate

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    //Set the dummy view (imageview's superview) as view for zooming
    return imageView.superview;
}


[...]


#pragma Mark - UIGestureRecognizerDelegate

- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

    //Make it possibile to recognize simultaneously pinch and rotation gestures
    return TRUE;
}


[...]


- (IBAction) handleRotate:(UIRotationGestureRecognizer*)recognizer {

    //Apply the rotation to imageView
    imageView.transform = CGAffineTransformRotate(imageView.transform, recognizer.rotation);
    recognizer.rotation = 0;    
}

出于简单的目的,我在同一个控制器中编写了所有内容。您可以自由地继承UIScrollView。请记住,技巧是:

1)将容器虚拟视图返回为 viewForZoomingInScrollView ,这样缩放将影响容器视图,旋转将影响uiimageview。

2)将包含scrollview的viewcontroller设置为旋转手势识别器的委托,并为 shouldRecognizeSimultaneouslyWithGestureRecognizer 返回TRUE。

答案 1 :(得分:0)

将此添加到.m

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

另外,请确保您没有在任何手势识别器上启用独占触控。

答案 2 :(得分:0)

尝试将可扩展/可旋转内容放在内容视图的子视图中。 (也许您必须将内容视图的“剪辑内容”属性设置为true - 不确定)

这样滚动视图不再受转换的影响,因为它的内容视图保持不变。

如果必须显示剪切的内容(例如,如果旋转正方形,角落会从初始区域移出),请重新计算内容视图并更新滚动视图。

由于您提供了代码,我建议您尝试:

//Scroll View's subview
backgroundViewHolder = [[UIView alloc] initWithFrame:scrollView.frame];
[backgroundViewHolder setBackgroundColor:[UIColor orangeColor]];
[scrollView backgroundViewHolder];

//Holder View's subview
backgroundView = [[UIView alloc] initWithFrame:backgroundViewHolder.bounds];
[backgroundViewHolder addSubview:backgroundView];

其他一切应该保持不变。这只是一个想法...不确定这是正确的答案。

答案 3 :(得分:-1)

  1. 将其添加到您的工具文件中,将其设为UIGestureRecognizerDelegate
  2. - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
        return YES;
    }
    
    1. rotationGeustureRecognozier.delegate = self; //(工具文件)