我正在努力尝试弄清楚是否有可能创建一个结合了 UIPinchGestureRecognizer 和 UIPanGestureRecognizer 的单一组合手势识别器。
我使用平移进行 View 平移,使用捏合进行 View 缩放。我正在进行增量矩阵串联以导出应用于 View 的最终转换矩阵。该矩阵具有比例和平移。使用单独的手势识别器会导致抖动的移动/缩放。不是我想要的。因此,我想在一个手势中处理一次缩放和平移的连接。有人可以阐明如何执行此操作吗?
最佳答案
6/14/14:更新了带有 ARC 的 iOS 7+ 示例代码。
UIGestureRecognizers 可以一起工作,你只需要确保你不会破坏当前 View 的转换矩阵。使用将变换作为输入的 CGAffineTransformScale 方法和相关方法,而不是从头开始创建它(除非您自己维护当前的旋转、缩放或平移。
下载Xcode项目
注意:iOS 7 在 IB 中应用了 Pan/Pinch/Rotate 手势的 UIView 时表现得很奇怪。 iOS 8 修复了它,但我的解决方法是像这个代码示例一样在代码中添加所有 View 。
演示视频
将它们添加到 View 并符合 UIGestureRecognizerDelegate 协议(protocol)
@interface ViewController () <UIGestureRecognizerDelegate> @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 150, 150)]; blueView.backgroundColor = [UIColor blueColor]; [self.view addSubview:blueView]; [self addMovementGesturesToView:blueView]; // UIImageView's and UILabel's don't have userInteractionEnabled by default! UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"BombDodge.png"]]; // Any image in Xcode project imageView.center = CGPointMake(100, 250); [imageView sizeToFit]; [self.view addSubview:imageView]; [self addMovementGesturesToView:imageView]; // Note: Changing the font size would be crisper than zooming a font! UILabel *label = [[UILabel alloc] init]; label.text = @"Hello Gestures!"; label.font = [UIFont systemFontOfSize:30]; label.textColor = [UIColor blackColor]; [label sizeToFit]; label.center = CGPointMake(100, 400); [self.view addSubview:label]; [self addMovementGesturesToView:label]; } - (void)addMovementGesturesToView:(UIView *)view { view.userInteractionEnabled = YES; // Enable user interaction UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; panGesture.delegate = self; [view addGestureRecognizer:panGesture]; UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)]; pinchGesture.delegate = self; [view addGestureRecognizer:pinchGesture]; }
实现手势方法
- (void)handlePanGesture:(UIPanGestureRecognizer *)panGesture { CGPoint translation = [panGesture translationInView:panGesture.view.superview]; if (UIGestureRecognizerStateBegan == panGesture.state ||UIGestureRecognizerStateChanged == panGesture.state) { panGesture.view.center = CGPointMake(panGesture.view.center.x + translation.x, panGesture.view.center.y + translation.y); // Reset translation, so we can get translation delta's (i.e. change in translation) [panGesture setTranslation:CGPointZero inView:self.view]; } // Don't need any logic for ended/failed/canceled states } - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinchGesture { if (UIGestureRecognizerStateBegan == pinchGesture.state || UIGestureRecognizerStateChanged == pinchGesture.state) { // Use the x or y scale, they should be the same for typical zooming (non-skewing) float currentScale = [[pinchGesture.view.layer valueForKeyPath:@"transform.scale.x"] floatValue]; // Variables to adjust the max/min values of zoom float minScale = 1.0; float maxScale = 2.0; float zoomSpeed = .5; float deltaScale = pinchGesture.scale; // You need to translate the zoom to 0 (origin) so that you // can multiply a speed factor and then translate back to "zoomSpace" around 1 deltaScale = ((deltaScale - 1) * zoomSpeed) + 1; // Limit to min/max size (i.e maxScale = 2, current scale = 2, 2/2 = 1.0) // A deltaScale is ~0.99 for decreasing or ~1.01 for increasing // A deltaScale of 1.0 will maintain the zoom size deltaScale = MIN(deltaScale, maxScale / currentScale); deltaScale = MAX(deltaScale, minScale / currentScale); CGAffineTransform zoomTransform = CGAffineTransformScale(pinchGesture.view.transform, deltaScale, deltaScale); pinchGesture.view.transform = zoomTransform; // Reset to 1 for scale delta's // Note: not 0, or we won't see a size: 0 * width = 0 pinchGesture.scale = 1; } } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; // Works for most use cases of pinch + zoom + pan }
资源
关于ios - UIPinchGestureRecognizer 和 UIPanGestureRecognizer 可以合并吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4935539/