在iOS 5中下拉UIView

4
我在我的iPhone应用程序中看到,在状态栏上有一个手势可以访问通知中心。我如何在我的应用程序中实现这种转换呢?我认为这可以通过滑动手势识别器来完成,但是如何包含从上往下的滑动手势(就像你可以拖动通知中心进行完整的转换一样)?有没有示例代码或其他东西可以帮助我做到这一点?
谢谢您的帮助!

3
那是通知中心。由于这是系统范围内的手势,如果您在您的应用程序中实现类似的功能,我怀疑要么a)苹果会拒绝它,因为它与通知中心冲突,要么b)您的用户将看不到它,因为通知中心将出现。 - Tomas McGuinness
2
@tomasmcguinness 这个问题不是关于实现第二个通知中心,而是关于实现像这样的用户交互。 - Kai Huppmann
@tomasmcguinness,不不,我只是想展示一个像那样的UI视图控制器,就这样... - stackiphone
@Kai 是的,正确的,如何从上往下获取滑动手势?左右滑动是可用的... - stackiphone
@stackiphone 我根本不会使用滑动手势识别器,请查看我的下面的回答。 - Kai Huppmann
3个回答

11
很容易实现。假设您有一个UIView(mainView),您希望从中触发下拉事件:
  1. 在mainView的顶部区域之外放置一个子视图(pulldownView)。
  2. 实现mainView上的touchesBegan,并检查触摸是否在前30像素(或点)内。
  3. 实现touchesMoved,检查移动方向是否向下且pulldownView不可见,如果是,则将pulldownView向下拖入主视图的可见区域;或者检查移动方向是否向上且pulldownView可见,如果是,则将其向上推出可见区域。
  4. 实现touchesEnd,在此根据pulldownView的移动方向结束拖动或推动运动。

编辑:

这里是一些示例代码。未经测试,可能包含拼写错误,可能无法编译,但应该包含所需的基本部分。

//... inside mainView impl:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  UITouch *touch = (UITouch *)[touches anyObject];
  start = [touch locationInView:self.superview].y;
  if(start > 30 && pulldownView.center.y < 0)//touch was not in upper area of view AND pulldownView not visible
  {
    start = -1; //start is a CGFloat member of this view
  }
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
  if(start < 0)
  {
    return;
  }
  UITouch *touch = (UITouch *)[touches anyObject];
  CGFloat now = [touch locationInView:self.superview].y;
  CGFloat diff = now - start;
  directionUp = diff < 0;//directionUp is a BOOL member of this view
  float nuCenterY = pulldownView.center.y + diff;
  pulldownView.center = CGPointMake(pulldownView.center.x, nuCenterY);
  start = now;
}


-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
  if (directionUp)
  {
    //animate pulldownView out of visibel area
    [UIView animateWithDuration:.3 animations:^{pulldownView.center = CGPointMake(pulldownView.center.x, -roundf(pulldownView.bounds.size.height/2.));}];
  }
  else if(start>=0)
  {
    //animate pulldownView with top to mainviews top
    [UIView animateWithDuration:.3 animations:^{pulldownView.center = CGPointMake(pulldownView.center.x, roundf(pulldownView.bounds.size.height/2.));}];
  }
}

谢谢你的回答,但我对iOS非常陌生,所以我认为这对我来说不容易。让我们试试看...如果你知道任何示例代码或其他东西,那会更容易些...谢谢。 - stackiphone
@Kai的解决方案应该可以工作。我鼓励你考虑一下在你的应用程序中通知中心的功能如何工作,以及它是否对用户不直观或难以使用。例如,Android具有类似的通知中心功能;此外,在浏览器中稍微向下拉动屏幕即可到达地址栏。在没有意识到的情况下,很难进入浏览器的地址栏而不是通知中心。这可能在您的应用程序中运行良好,只是需要考虑一下。 - strings42
1
@stackiphone添加了一些示例代码,可能需要进行一些调整。 - Kai Huppmann

1

在您的应用程序中,您可以实现UISwipeGestureRecognizer来处理滑动手势,并指定要检测的滑动方向为UISwipeGestureRecognizerDirectionDown。

这里有一个Apple示例。还有一些值得一看的WWDC10会话。我建议从那个页面中选择“使用手势识别器简化触摸事件处理”和“高级手势识别”。


是的,没错,谢谢你的回答。我知道如何实现滑动手势,但是我该怎样像这样展示那个视图呢? - stackiphone

0
我通过在一个全尺寸的UIScrollView中使用一个子类化的UIView来解决了这个问题。如果用户触摸到不可拖动的点,UIView会将触摸事件传递给其下层视图。
@implementation MyCustomUIView

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    // Check whether we are on the overlay
    if
    (
        point.y < 460.0f
        // Maybe some more restrictions here
    )
    {
        // Block the event, pass to parent
        return NO;
    }

    // Everything okay
    return YES;
}

@end

这段代码使得 UIScrollView 只在 460 像素以下的触摸事件才会响应。如果你的 UIScrollView 高度为 800 像素,那么你可以从 460 像素到 800 像素之间进行触摸操作。足以打开、关闭和使用它。因此,如果你有一个全尺寸的 UIScrollView,你可以将其拖动到打开它,同时仍然能够“触摸”底层视图。这种方法的好处是所有动画都依赖于默认行为,而不需要自己实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接