我试图用iPhone上的拖放来解决一个基本问题。这是我的设置:
我的UIScrollView子类有这个方法:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *tile = [contentView pointInsideTiles:[self convertPoint:point toView:contentView] withEvent:event];
if (tile) {
return tile;
} else {
return [super hitTest:point withEvent:event];
}
}
内容子视图有这种方法:
- (UIView *)pointInsideTiles:(CGPoint)point withEvent:(UIEvent *)event {
for (TileView *tile in tiles) {
if ([tile pointInside:[self convertPoint:point toView:tile] withEvent:event])
return tile;
}
return nil;
}
平铺视图有这种方法:
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.superview];
self.center = location;
}
这有效,但不完全正确:在拖动过程中,瓷砖有时会“掉落”。更确切地说,它停止接收touchesMoved:invocations,滚动视图开始滚动。我注意到这取决于拖动速度:我拖得越快,瓷砖“越来越”。
关于如何将瓷砖粘在拖动手指上的任何想法?
答案 0 :(得分:59)
我正在努力解决同样的问题 - 我试图在软木板上做很多“卡片”(UIView子类)的接口,并且软木板区域可以滚动,但仍然可以拖动 - 和 - 放下卡片。我正在做上面的hitTest()解决方案,但是一位Apple工程师问我为什么这样做。他们建议的更简单的解决方案如下:
1)在UIScrollView类中,将canCancelContentTouches的值设置为NO - 这会告诉UIScrollView类允许在子视图中进行触摸(或者,在本例中,在子视图的子视图中)。
2)在我的“card”类中,将exclusiveTouch设置为YES - 这告诉子视图它拥有内部的触摸。
在此之后,我能够拖动卡片并仍然滚动子视图。它比上面的hitTest()解决方案更简单,更清晰。
(顺便说一下,如果您使用的是iOS 3.2或4.0或更高版本,请使用UIPanGestureRecognizer类来处理拖放逻辑 - 拖放动作比覆盖touchesBegan()/ touchesMoved( )/ touchesEnded()。)
答案 1 :(得分:1)
解决了:原来应该还有touchesBegan:和touchesEnded:实现(在我的情况下有空方法帮助)在tile中,否则手势开始传播到父视图,并且他们以某种方式拦截手势。对阻力速度的依赖性是虚构的。
答案 2 :(得分:0)
根据您共享的代码,看起来您的touchesMoved:
方法只会在磁贴中调用手势。在每次触摸时,您将平铺移动到该触摸的中心位置,因此缓慢移动将在平铺内进行更新 - 并且平铺将在手指退出平铺之前用指尖“赶上”。但是,当手势更快时,(x,y)touchesMoved事件会相距更远,当一个(x,y)点距离最后一个点远远超出该点时,你将失去手势。瓦已经。
你可以通过捕捉足够大的超视图中的移动来覆盖整个可拖动区域,并从该超视图中控制区块的移动来解决这个问题。
顺便问一下,你是否有理由重写hitTest:方法?使用内置实现可能更容易(也可能更高效?)。
答案 3 :(得分:0)
首先,设置:
scrollview.canCancelContentTouches = NO;
yourSubView. exclusiveTouch = YES;
然后在您的子视图手势处理函数中
- (void)handleSubviewMove:(UIPanGestureRecognizer *)gesture {
if(gesture.state == UIGestureRecognizerStateBegan) {
if(_parentScrollView != nil) {
_parentScrollView.scrollEnabled = NO;
}
}
if(gesture.state == UIGestureRecognizerStateEnded) {
if(_parentScrollView != nil) {
_parentScrollView.scrollEnabled = YES;
}
}
CGPoint translation = [gesture translationInView:[self superview]];
/* handle your view's movement here. */
[gesture setTranslation:CGPointZero inView:[self superview]];
}