我希望获得与谷歌地图(iOS)非常接近的东西,我有一些疑问。
但首先,要考虑更好的解释和事项:
-------------- ANSWER --------------
感谢Jugale的贡献,这里有一个存储库,所以每个人都可以下载并测试所有内容。
https://github.com/vCrespoP/VCSlidingView
--------------原始问题-----------
这里有效:
疑惑:
那么,任何人都知道任何框架,已经完成了,或者知道如何以一种好的方式做到这一点?
感谢您的时间:D
答案 0 :(得分:3)
通过我的实现看来,以下情况似乎如下:
UIViewController
的子类,它是视图控制器UIView
的子类,它是叠加层(以后称为"叠加层")(实际上对我来说这是UIScrollView
,因为它需要我也会侧身,但我会尝试过滤掉不必要的代码)UIView
的子类加载了叠加层的内容("内容包装器")UIScrollView
属性,其中加载了所有其他视图("内容视图")视图控制器负责初始化叠加层,设置它的初始帧(其中高度是屏幕的高度)并将内容传递给它,仅此而已。
通过它的-initWithFrame
方法,叠加层设置为UIDynamicItemBehavior
。它还会创建一些UICollisionBehavior
个对象:一个位于屏幕顶部,一个位于屏幕底部,位于右侧y位置,覆盖顶部部分可见(如第一帧中所示)你的GIF)。还设置了UIGravityBehavior
以使叠加层保持在下部碰撞边界。当然,_animator = [[UIDynamicAnimator alloc...
也已设置。
最后:
_pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan)];
_pan.delegate = self;
_pan.cancelsTouchesInView = FALSE;
叠加层还有一些其他有用的方法,例如更改重力方向,以便叠加层可以显示为捕捉到屏幕的顶部或底部。
_pan
处理程序使用UISnapBehavior
来保持叠加层在用户手指下方的屏幕上上下移动:
- (void)handlePan
{
[self handlePanFromPanGestureRecogniser:_pan];
}
- (void)handlePanFromPanGestureRecogniser:(UIPanGestureRecognizer *)pan
{
CGFloat d = [pan velocityInView:self.superview.superview].y;
CGRect r = self.frame;
r.origin.y = r.origin.y + (d*0.057);
if (r.origin.y < 20)
{
r.origin.y = 20;
}
else if (r.origin.y > [UIScreen mainScreen].bounds.size.height - PEEKING_HEIGHT)
{
r.origin.y = [UIScreen mainScreen].bounds.size.height - PEEKING_HEIGHT;
}
if (pan.state == UIGestureRecognizerStateEnded)
{
[self panGestureEnded];
}
else if (pan.state == UIGestureRecognizerStateBegan)
{
[self snapToBottom];
[self removeGestureRecognizer:_tap];
}
else
{
[_animator removeBehavior:_findersnap];
_findersnap = [[UISnapBehavior alloc] initWithItem:self snapToPoint:CGPointMake(CGRectGetMidX(r), CGRectGetMidY(r))];
[_animator addBehavior:_findersnap];
}
}
- (void)panGestureEnded
{
[_animator removeBehavior:_findersnap];
CGPoint vel = [_dynamicSelf linearVelocityForItem:self];
if (fabsf(vel.y) > 250.0)
{
if (vel.y < 0)
{
[self snapToTop];
}
else
{
[self snapToBottom];
}
}
else
{
if (self.frame.origin.y > (self.superview.bounds.size.height/2))
{
[self snapToBottom];
}
else
{
[self snapToTop];
}
}
}
内容包装器侦听内容视图生成的滚动事件:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//this is our fancy way of getting the pan to work when the scrollview is in the way
if (scrollView.contentOffset.y <= 0 && _dragging)
{
_shouldForwardScrollEvents = TRUE;
}
if (_shouldForwardScrollEvents)
{
if ([_delegate respondsToSelector:@selector(theContentWrapper:isForwardingGestureRecogniserTouches:)])
{
[_delegate theContentWrapper:self isForwardingGestureRecogniserTouches:scrollView.panGestureRecognizer];
}
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
_dragging = FALSE;//scrollviewdidscroll must not be called after this
if (scrollView.contentOffset.y <= 0 || _shouldForwardScrollEvents)
{
if ([_delegate respondsToSelector:@selector(theContentWrapperStoppedBeingDragged:)])
{
[_delegate theContentWrapperStoppedBeingDragged:self];
}
}
_shouldForwardScrollEvents = FALSE;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
_dragging = TRUE;
}
正如您所看到的,当bool shouldForwardScrollEvents
为TRUE
时,我们会将scrollView.panGestureRecognizer
发送给内容包装器的代理(覆盖)。 overlay实现了如下的委托方法:
- (void)theContentWrapper:(TheContentWrapper *)contentWrapper isForwardingGestureRecogniserTouches:(UIPanGestureRecognizer *)contentViewPan
{
[self handlePanFromPanGestureRecogniser:contentViewPan];
}
- (void)theContentWrapperStoppedBeingDragged:(TheContentWrapper *)contentWrapper
{
//because the scrollview internal pan doesn't tell use when it's state == ENDED
[self panGestureEnded];
}
希望至少其中一些对某人有用!