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

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

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

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-16 05:02:38

我不太确定你到底想要什么效果,但你可以像这样做,创建一个新的临时标签,将它从屏幕上移出,动画移动到屏幕上的标签上,然后完成后,重置旧标签并删除临时标签。下面是非自动布局实现可能的样子:

代码语言:javascript
复制
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    UISwipeGestureRecognizer *left = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(leftSwipe:)];
    [left setDirection:UISwipeGestureRecognizerDirectionLeft];
    [self.view addGestureRecognizer:left];
    // if non-ARC, release it
    // [release left];

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

- (void)leftSwipe:(UISwipeGestureRecognizer *)gesture
{
    NSString *newText;
    UILabel  *existingLabel = self.label1;

    // in my example, I'm just going to toggle the value between Mo and Curly

    if ([existingLabel.text isEqualToString:@"Curly"])
        newText = @"Mo";
    else
        newText = @"Curly";

    // create new label

    UILabel *tempLabel = [[UILabel alloc] initWithFrame:existingLabel.frame];
    [existingLabel.superview addSubview:tempLabel];
    tempLabel.text = newText;

    // move the new label off-frame to the right

    tempLabel.transform = CGAffineTransformMakeTranslation(tempLabel.superview.bounds.size.width, 0);

    // animate the sliding of them into place

    [UIView animateWithDuration:0.5
                     animations:^{
                         tempLabel.transform = CGAffineTransformIdentity;
                         existingLabel.transform = CGAffineTransformMakeTranslation(-existingLabel.superview.bounds.size.width, 0);
                     }
                     completion:^(BOOL finished) {
                         existingLabel.text = newText;
                         existingLabel.transform = CGAffineTransformIdentity;
                         [tempLabel removeFromSuperview];
                     }];

    // if non-ARC, release it
    // [release tempLabel];
}

此动画相对于其superview对标签进行动画处理。您可能希望确保将superview设置为“剪贴子视图”。这样,动画将被约束到该superview的边界,从而产生稍微更精致的外观。

注意,如果使用自动布局,想法是相同的(尽管执行更复杂)。基本上配置您的约束,使新视图在右侧,然后,在动画块中更新/替换约束,使原始标签在左侧,新标签在原始标签的点上,最后,在完成块中,重置原始标签的约束并删除临时标签。

顺便说一句,如果你对其中一个内置的转换感到满意,这一切都会变得非常容易:

代码语言:javascript
复制
- (void)leftSwipe:(UISwipeGestureRecognizer *)gesture
{
    NSString *newText;
    UILabel  *existingLabel = self.label1;

    // in my example, I'm just going to toggle the value between Mo and Curly

    if ([existingLabel.text isEqualToString:@"Curly"])
        newText = @"Mo";
    else
        newText = @"Curly";

    [UIView transitionWithView:existingLabel  // or try `existingLabel.superview`
                      duration:0.5
                       options:UIViewAnimationOptionTransitionFlipFromRight
                    animations:^{
                        existingLabel.text = newText;
                    }
                    completion:nil];
}
票数 15
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
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11057657

复制
相关文章

相似问题

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