gesture分类
遗留问题
关于使用CTM 旋转、缩放对子视图和父视图相关坐标的影响。
相关功能
对view的拖动、缩放、旋转功能
关键代码(值得注意学习的地方标注在注释中)
// adds a set of gesture recognizers to one of our piece subviews
- (void)addGestureRecognizersToPiece:(UIView *)piece
{
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotatePiece:)];
[piece addGestureRecognizer:rotationGesture];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(scalePiece:)];
[pinchGesture setDelegate:self];
[piece addGestureRecognizer:pinchGesture];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panPiece:)];
[panGesture setMaximumNumberOfTouches:2];
[panGesture setDelegate:self];
[piece addGestureRecognizer:panGesture];
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showResetMenu:)];
[piece addGestureRecognizer:longPressGesture];
}
-(id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
firstPieceView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 90, 200, 200)];
[self addSubview:firstPieceView];
firstPieceView.userInteractionEnabled = YES;
firstPieceView.image = [UIImage imageNamed:@"YellowSquare.png"];
[self addSubview:firstPieceView];
secondPieceView = [[UIImageView alloc] initWithFrame:CGRectMake(110,190, 100, 100)];
[self addSubview:secondPieceView];
secondPieceView.userInteractionEnabled = YES;
secondPieceView.image = [UIImage imageNamed:@"CyanSquare.png"];
[self addSubview:secondPieceView];
thirdPieceView = [[UIImageView alloc] initWithFrame:CGRectMake(210, 290, 100, 100)];
[self addSubview:thirdPieceView];
thirdPieceView.userInteractionEnabled = YES;
thirdPieceView.image = [UIImage imageNamed:@"MagentaSquare.png"];
[self addSubview:thirdPieceView];
[self addGesture];
}
return self;
}
- (void)addGesture
{
[self addGestureRecognizersToPiece:firstPieceView];
[self addGestureRecognizersToPiece:secondPieceView];
[self addGestureRecognizersToPiece:thirdPieceView];
}
#pragma mark -
#pragma mark === Touch handling ===
#pragma mark
// shift the piece's center by the pan amount
// reset the gesture recognizer's translation to {0, 0} after applying so the next callback is a delta from the current position
//各个pieceview之间的层次结构,由addsubview的先后顺序决定
- (void)panPiece:(UIPanGestureRecognizer *)gestureRecognizer
{
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
UIView *panView = gestureRecognizer.view;
if (gestureRecognizer.state == UIGestureRecognizerStateBegan || gestureRecognizer.state == UIGestureRecognizerStateChanged)
{
//移动的距离
CGPoint trasitionDistance = [gestureRecognizer translationInView:panView.superview];
CGPoint transionDistance2 = [gestureRecognizer translationInView:panView];
//pieceview坐标应该变化的距离
//问题:scale之后,返回的trasitionDistance,transionDistance2是不一样的
panView.center = CGPointMake(panView.center.x + trasitionDistance.x, panView.center.y + trasitionDistance.y);
//transion归0,这样每次调用返回的就是增量
[gestureRecognizer setTranslation:CGPointZero inView:panView];
}
}
// rotate the piece by the current rotation
// reset the gesture recognizer's rotation to 0 after applying so the next callback is a delta from the current rotation
- (void)rotatePiece:(UIRotationGestureRecognizer *)gestureRecognizer
{
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
UIView *panView = gestureRecognizer.view;
if (gestureRecognizer.state == UIGestureRecognizerStateBegan || gestureRecognizer.state == UIGestureRecognizerStateChanged)
{
CGFloat rotation = gestureRecognizer.rotation;
//最关键的问题CGAffineTransformRotate变化之后,对坐标和锚点的影响
panView.transform = CGAffineTransformRotate(panView.transform, rotation);
[gestureRecognizer setRotation:0];
}
}
// scale the piece by the current scale
// reset the gesture recognizer's rotation to 0 after applying so the next callback is a delta from the current scale
- (void)scalePiece:(UIPinchGestureRecognizer *)gestureRecognizer
{//注意缩放之后,描点也会改变
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
UIView *panView = gestureRecognizer.view;
if (gestureRecognizer.state == UIGestureRecognizerStateBegan || gestureRecognizer.state == UIGestureRecognizerStateChanged)
{
CGFloat scale = gestureRecognizer.scale;
panView.transform = CGAffineTransformScale(panView.transform,scale, scale);
[gestureRecognizer setScale:1];
}
}
- (void)adjustAnchorPointForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
UIView *piece = gestureRecognizer.view;
CGPoint locationInView = [gestureRecognizer locationInView:piece];
CGPoint locationInSuperview = [gestureRecognizer locationInView:piece.superview];
piece.layer.anchorPoint = CGPointMake(locationInView.x / piece.bounds.size.width,
locationInView.y / piece.bounds.size.height);
piece.center = locationInSuperview;
}
}
-(void)showResetMenu:(UILongPressGestureRecognizer *)gesture
{
//此方法,在不同的状态都会回调,所有要对状态进行判断
if (gesture.state == UIGestureRecognizerStateBegan)
{
UIMenuController *menuController = [UIMenuController sharedMenuController];
[menuController setMenuVisible:YES animated:YES];
UIMenuItem *item = [[UIMenuItem alloc] initWithTitle:@"reset" action:@selector(reset:)];
UIMenuItem *item2 = [[UIMenuItem alloc] initWithTitle:@"reset" action:@selector(reset:)];
NSArray *array = [NSArray arrayWithObjects:item,item2, nil];
menuController.menuItems = array;
[self becomeFirstResponder];
CGPoint point = [gesture locationInView:gesture.view];
[menuController setTargetRect:CGRectMake(point.x, point.y, 100, 40) inView:gesture.view];
pieceForReset = gesture.view;
}
}