首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在iOS中使用滑动手势的滚动效果

在iOS中使用滑动手势的滚动效果
EN

Stack Overflow用户
提问于 2012-06-16 04:18:46
回答 2查看 11.9K关注 0票数 6

我有一个有两个标签的视图。当我向左滑动时,我填充下一个内容来标记文本。类似地,向右滑动会加载之前的内容。我想给标签一个效果,就像它们是从左边或右边滚动一样。我以前使用过滚动视图,但它有一个内存问题。所以我使用一个视图,滑动手势加载下一个或上一个内容。我想给标签添加滚动视图的滑动效果。我该怎么做呢?

EN

Stack Overflow用户

发布于 2012-06-17 03:36:58

如果您更喜欢行为更像滚动视图的动画(即,在手势上具有连续反馈),则可能如下所示:

代码语言:javascript
复制
- (void)viewDidLoad
{
    [super viewDidLoad];

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panHandler:)];
    [self.view addGestureRecognizer:pan];

    self.label1.text = @"Mo";
}

- (void)panHandler:(UIPanGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateBegan)
    {
        _panLabel = [[UILabel alloc] init];

        // in my example, I'm just going to toggle the value between Mo and Curly
        // you'll presumably set the label contents based upon the direction of the
        // pan (if positive, swiping to the right, grab the "previous" label, if negative
        // pan, grab the "next" label)

        if ([self.label1.text isEqualToString:@"Curly"])
            _newText = @"Mo";
        else
            _newText = @"Curly";

        // set the text

        _panLabel.text = _newText;

        // set the frame to just be off screen

        _panLabel.frame = CGRectMake(self.label1.frame.origin.x + self.containerView.frame.size.width,
                                     self.label1.frame.origin.y, 
                                     self.label1.frame.size.width, 
                                     self.label1.frame.size.height);

        [self.containerView addSubview:_panLabel];

        _originalCenter = self.label1.center; // save where the original label originally was
    }
    else if (sender.state == UIGestureRecognizerStateChanged)
    {
        CGPoint translate = [sender translationInView:self.containerView];

        if (translate.x > 0)
        {
            _panLabel.center = CGPointMake(_originalCenter.x - self.containerView.frame.size.width + translate.x, _originalCenter.y);
            self.label1.center = CGPointMake(_originalCenter.x + translate.x, _originalCenter.y);
        }
        else 
        {
            _panLabel.center = CGPointMake(_originalCenter.x + self.containerView.frame.size.width + translate.x, _originalCenter.y);
            self.label1.center = CGPointMake(_originalCenter.x + translate.x, _originalCenter.y);
        }
    }
    else if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled)
    {
        CGPoint translate = [sender translationInView:self.containerView];
        CGPoint finalNewFieldLocation;
        CGPoint finalOriginalFieldLocation;
        BOOL panSucceeded;

        if (sender.state == UIGestureRecognizerStateFailed ||
            sender.state == UIGestureRecognizerStateCancelled)
        {
            panSucceeded = NO;
        }
        else 
        {
            // by factoring in the velocity, we can capture a flick more accurately
            //
            // (by the way, I don't like iOS's velocity, because if you stop moving, it records the velocity
            // prior to stopping the move rather than noting that you actually stopped, so I usually calculate my own, 
            // but I'll leave this as is for purposes of this example)

            CGPoint velocity  = [sender velocityInView:self.containerView];

            if (translate.x < 0)
                panSucceeded = ((translate.x + velocity.x * 0.5) < -(self.containerView.frame.size.width / 2));
            else
                panSucceeded = ((translate.x + velocity.x * 0.5) > (self.containerView.frame.size.width / 2));
        }

        if (panSucceeded)
        {
            // if we succeeded, finish moving the stuff

            finalNewFieldLocation = _originalCenter;
            if (translate.x < 0)
                finalOriginalFieldLocation = CGPointMake(_originalCenter.x - self.containerView.frame.size.width, _originalCenter.y);
            else
                finalOriginalFieldLocation = CGPointMake(_originalCenter.x + self.containerView.frame.size.width, _originalCenter.y);
        }
        else
        {
            // if we didn't, then just return everything to where it was

            finalOriginalFieldLocation = _originalCenter;

            if (translate.x < 0)
                finalNewFieldLocation = CGPointMake(_originalCenter.x + self.containerView.frame.size.width, _originalCenter.y);
            else
                finalNewFieldLocation = CGPointMake(_originalCenter.x - self.containerView.frame.size.width, _originalCenter.y);
        }

        // animate the moving of stuff to their final locations, and on completion, clean everything up

        [UIView animateWithDuration:0.3
                              delay:0.0 
                            options:UIViewAnimationOptionCurveEaseOut
                         animations:^{
                             _panLabel.center = finalNewFieldLocation;
                             self.label1.center = finalOriginalFieldLocation;
                         }
                         completion:^(BOOL finished) {
                             if (panSucceeded)
                                 self.label1.text = _newText;
                             self.label1.center = _originalCenter;
                             [_panLabel removeFromSuperview];
                             _panLabel = nil; // in non-ARC, release instead
                         }
         ];
    }
}   

请注意,我已经将原始标签以及正在平移的新标签都放在一个容器UIView (名为containerView,令人惊讶)中,这样我就可以将动画剪辑到该容器中。

票数 6
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11057657

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档