我想出了一些可以工作的手势处理程序,因此您正在操作的视图不会超出您指定的区域。My View 托盘由kscreenEditorSpace
, 2048 定义。
Pan 手势只是调用 calcCenterFromXposition:yPosition:fromBoundsInSuperView: 方法来设置它的中心,如果中心超出边界它只是调整并保持元素在边界内
//--------------------------------------------------------------------------------------------------------
// handlePanGesture
// Description: Called when scrollView got a DoubleFinger DoubleTap Gesture
// We want to Zoom out one ZOOM_STEP.
//
//--------------------------------------------------------------------------------------------------------
- (void)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer {
UIView *element = [gestureRecognizer view];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ) {
[[self superview] bringSubviewToFront:self];
}
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
//Front and Center Mr Element!
// Find out where we are going
CGPoint translation = [gestureRecognizer translationInView:[element superview]];
CGRect elementBoundsInSuperView = [element convertRect:element.bounds toView:[element superview]];
CGFloat xPosition = CGRectGetMidX(elementBoundsInSuperView) + translation.x;
CGFloat yPosition = CGRectGetMidY(elementBoundsInSuperView) + translation.y;
CGPoint newCenter = [self calcCenterFromXposition:xPosition yPosition:yPosition fromBoundsInSuperView:elementBoundsInSuperView];
//Re position ourselves
[element setCenter:newCenter];
//set the translation back to 0 point
[gestureRecognizer setTranslation:CGPointZero inView:[element superview]];
[self setNeedsDisplay];
}
if ([gestureRecognizer state] == UIGestureRecognizerStateEnded ) {
}
}
所以手柄捏和旋转非常相似。我们不是直接调用计算中心,而是调用另一个方法来帮助确定我们是否在边界内。
//--------------------------------------------------------------------------------------------------------
// handlePinchGesture
// Description: Called when scrollView got a DoubleFinger DoubleTap Gesture
// We want to Zoom out one ZOOM_STEP.
//
//--------------------------------------------------------------------------------------------------------
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer {
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ) {
[[self superview] bringSubviewToFront:self];
}
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
BOOL aSelectedElementOffscreen = FALSE;
if ([[gestureRecognizer view] pinchOffScreen:[gestureRecognizer scale]]) {
aSelectedElementOffscreen = TRUE;
}
if (!aSelectedElementOffscreen) {
[gestureRecognizer view].transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
//Update ourself
[self contentSizeChanged];
}
[gestureRecognizer setScale:1];
}
if ([gestureRecognizer state] == UIGestureRecognizerStateEnded) {
if (![self becomeFirstResponder]) {
NSLog(@" %@ - %@ - couldn't become first responder", INTERFACENAME, NSStringFromSelector(_cmd) );
return;
}
}
}
}
捏离屏幕方法
//--------------------------------------------------------------------------------------------------------
// pinchOffScreen
// Description: Called to see if the Pinch Gesture will cause element to go off screen Gesture
//
//--------------------------------------------------------------------------------------------------------
- (BOOL)pinchOffScreen:(CGFloat)scale {
// Save Our Current Transform incase we go off Screen
CGAffineTransform elementOrigTransform = [self transform];
//Apply our Transform
self.transform = CGAffineTransformScale([self transform], scale, scale);
// Get our new Bounds in the SuperView
CGRect newElementBoundsInSuperView = [self convertRect:self.bounds toView:[self superview]];
//Find out where we are in the SuperView
CGFloat xPosition = CGRectGetMidX( newElementBoundsInSuperView);
CGFloat yPosition = CGRectGetMidY( newElementBoundsInSuperView);
//See if we are off the Screen
BOOL offScreen = [self calcOffEditorFromXposition:xPosition yPosition:yPosition fromBoundsInSuperView: newElementBoundsInSuperView];
// We just wanted to Check. Revert to where we were
self.transform = elementOrigTransform;
return offScreen;
}
Handle Rotation 类似于 Pinch,我们有一个辅助方法来查看我们是否旋转到屏幕外。
//--------------------------------------------------------------------------------------------------------
// handleRotationGesture
// Description: Called when we get a rotation gesture
// toggle the scroll/zoom lock
//
//--------------------------------------------------------------------------------------------------------
- (void) handleRotationGesture:(UIRotationGestureRecognizer *)gestureRecognizer{
UIView *element = [gestureRecognizer view];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ) {
[[self superview] bringSubviewToFront:self];
}
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
BOOL aSelectedElementOffscreen = FALSE;
if ([element rotateOffScreen:[gestureRecognizer rotation]]) {
aSelectedElementOffscreen = TRUE;
}
if (!aSelectedElementOffscreen) {
[gestureRecognizer view].transform = CGAffineTransformRotate([element transform], [gestureRecognizer rotation]);
//Update ourself
[self contentSizeChanged];
}
[gestureRecognizer setRotation:0];
}
if ([gestureRecognizer state] == UIGestureRecognizerStateEnded) {
}
}
}
旋转离屏方法
//--------------------------------------------------------------------------------------------------------
// rotateOffScreen
// Description: Called to see if the Rotation Gesture will cause element to go off screen Gesture
//
//--------------------------------------------------------------------------------------------------------
- (BOOL)rotateOffScreen:(CGFloat)rotation {
// Save Our Current Transform incase we go off Screen
CGAffineTransform elementOrigTransform = [self transform];
//Apply our Transform
self.transform = CGAffineTransformRotate([self transform], rotation);
// Get our new Bounds in the SuperView
CGRect newElementBoundsInSuperView = [self convertRect:self.bounds toView:[self superview]];
//Find out where we are in the SuperVire
CGFloat xPosition = CGRectGetMidX( newElementBoundsInSuperView);
CGFloat yPosition = CGRectGetMidY( newElementBoundsInSuperView);
//See if we are off the Screen
BOOL offScreen = [self calcOffEditorFromXposition:xPosition yPosition:yPosition fromBoundsInSuperView: newElementBoundsInSuperView];
// We just wanted to Check. Revert to where we were
self.transform = elementOrigTransform;
return offScreen;
}
Calc 屏幕定位辅助方法
#pragma mark -
#pragma mark === Calc Screen Positioning ===
#pragma mark
//--------------------------------------------------------------------------------------------------------
// calcCenterFromXposition: yPosition: fromBoundsInSuperView:
// Description: calculate the center point in the element's super view from x, y
//
//--------------------------------------------------------------------------------------------------------
-(CGPoint) calcCenterFromXposition: (CGFloat) xPosition yPosition:(CGFloat) yPosition fromBoundsInSuperView:(CGRect) elementBoundsInSuperView{
// Ge the Height/width based on SuperView Bounds
CGFloat elementWidth = CGRectGetWidth(elementBoundsInSuperView);
CGFloat elementHeight = CGRectGetHeight(elementBoundsInSuperView);
//Determine our center.x from the new x
if (xPosition < elementWidth/2) {
xPosition = elementWidth/2;
} else if (xPosition + elementWidth/2 > kscreenEditorSpace) {
xPosition = kscreenEditorSpace - elementWidth/2;
}
//Determine our center.y from the new y
if (yPosition < elementHeight/2) {
yPosition = elementHeight/2;
} else if (yPosition + elementHeight/2 > kscreenEditorSpace) {
yPosition = kscreenEditorSpace - elementHeight/2;
}
return (CGPointMake(xPosition, yPosition));
}
//--------------------------------------------------------------------------------------------------------
// calcOffEditorFromXposition: yPosition: fromBoundsInSuperView:
// Description: Determine if moving the element to x, y will it be off the editor screen
//
//--------------------------------------------------------------------------------------------------------
-(BOOL) calcOffEditorFromXposition: (CGFloat) xPosition yPosition:(CGFloat) yPosition fromBoundsInSuperView:(CGRect) elementBoundsInSuperView{
BOOL offScreen = NO;
// Ge the Height/width based on SuperView Bounds
CGFloat elementWidth = CGRectGetWidth(elementBoundsInSuperView);
CGFloat elementHeight = CGRectGetHeight(elementBoundsInSuperView);
// Off Screen on Left
if (xPosition < elementWidth/2) {
offScreen = YES;
}
//Off Screen Right
if (xPosition + elementWidth/2 > kscreenEditorSpace) {
offScreen = YES;;
}
// Off Screen Top
if (yPosition < elementHeight/2) {
offScreen = YES;
}
//Off Screen Bottom
if (yPosition + elementHeight/2 > kscreenEditorSpace) {
offScreen = YES;
}
return (offScreen);
}