实现这一功能,只能经过UIScrollView的嵌套或者UIView中添加UIScrollView方式(我能想到的,有更好的作法,能够留言指出)git
但无论采用哪一种方案,有一个重要的问题须要处理:事件冲突github
在通常的状况下,只有UIScrollView及其子类才具有滚动的功能,无论是UIScrollView的嵌套仍是在普通的UIView中添加UIScrollView,都会出现冲突bash
采用UIView中添加UICollectionView,而后给UICollectionView添加拖动手势,
经过位置、拖动方向,拦截事件来肯定响应的对象。
复制代码
1.这个是UIView关于手势事件的拓展方法,返回值为NO时,表示不触发手势事件,该方法在此处运用时,即禁掉自定义添加的拖动手势,响应UICollecionView的滚动手势,咱们能够在这个方法中获取到view的当前位置,以及手势的方向,根据这两个因素,就能够决定是否响应事件了
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
UIPanGestureRecognizer *recognizer = (UIPanGestureRecognizer *)gestureRecognizer;
if ([self.delegate respondsToSelector:@selector(fetchContainerViewWithStartY)]) {
/*经过代理获取view的当前位置*/
CGFloat startY = [self.baseCollectionViewdelegate fetchContainerViewWithStartY];
CGPoint point = [recognizer translationInView:recognizer.view];//处理方向
/*
1.外层view是否在最顶部即frame的y值是否为0(在中止时,y值只有三种状况:0, 150, ScreenHeight-49)
2.scrollview的偏移值 ( contentOffset.y < 0 偏下 >0 偏上)
3.滑动方向:向上仍是向下 ( point.y > 0:向下, point.y > 0:向上)
*/
if (startY <= 20) {
if (point.y > 0) {//向下
if (self.contentOffset.y > 0) {// <0 偏下(目前的设置,不可能出现) >0 偏上
return YES;
} else {
return NO;
}
} else {
return YES;
}
} else {
return NO;
}
}
}
return YES;
}
2.是否支持多种手势事件共存,这个也是解决问题的关键,这里须要返回YES,容许支持,咱们对UICollectionView添加了自定义的拖动手势以及UICollectionView自己自带了系统的事件
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
复制代码
- (void)moveView:(UIPanGestureRecognizer *)recognizer {
NSLog(@"手势滑动 > recognizer.state : %ld", recognizer.state);
if (CGRectGetMinY(self.frame) > 20) {
CGPoint location = [recognizer translationInView:self.superview];
CGFloat y = location.y + CGRectGetMinY(self.frame);
if (recognizer.state == UIGestureRecognizerStateBegan) {
self.startMoveViewFrameY = CGRectGetMinY(self.frame);
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
if (y < 20) {
y = 20;
} else if (y > SCREEN_HEIGHT - 49.f) {
y = SCREEN_HEIGHT - 49.f;
}
self.frame = CGRectMake(0, y, SCREEN_WIDTH, SCREEN_HEIGHT - 69.f);
if ([self.delegate respondsToSelector:@selector(scrollWithY:panDirection:animations:)]) {
//回调处理,拖动的小图标
[self.delegate scrollWithY:y panDirection:HZPanDirectionNone animations:NO];
}
} else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) {
CGPoint locan = [recognizer translationInView:self.collectionView];
HZPanDirection panDirection = HZPanDirectionNone;
if (self.startMoveViewFrameY < CGRectGetMinY(self.frame)) {//向下
y = SCREEN_HEIGHT - 49.f;
panDirection = HZPanDirectionDown;
} else {
panDirection = HZPanDirectionUp;
if (y < 150) {
y = 20;
} else {
y = 150.f;
}
}
[UIView animateWithDuration:1.f animations:^{
self.frame = CGRectMake(0, y, SCREEN_WIDTH, SCREEN_HEIGHT - 69.f);
} completion:^(BOOL finished) {
}];
if ([self.delegate respondsToSelector:@selector(scrollWithY:panDirection:animations:)]) {
//回调处理,拖动的小图标
[self.delegate scrollWithY:y panDirection:panDirection animations:YES];
}
}
} else if (CGRectGetMinY(self.frame) == 20) {
CGPoint point = [recognizer translationInView:recognizer.view];//处理方向
if (point.y > 0 && self.collectionView.contentOffset.y <= 0) {//向下
[UIView animateWithDuration:1.f animations:^{
self.frame = CGRectMake(0, SCREEN_HEIGHT - 49.f, SCREEN_WIDTH, SCREEN_HEIGHT - 69.f);
} completion:^(BOOL finished) {
}];
if ([self.delegate respondsToSelector:@selector(scrollWithY:panDirection:animations:)]) {
//回调处理,拖动的小图标
[self.delegate scrollWithY:SCREEN_HEIGHT - 49.f panDirection:HZPanDirectionDown animations:YES];
}
}
}
[recognizer setTranslation:CGPointZero inView:self.superview];
}
复制代码
这里是阐述比较核心的几个方法,具体的使用,能够下载demo : 传送门模块化