UIScrollView ScrollRectToVisible - 不使用animate = yes

时间:2011-08-23 23:36:01

标签: objective-c ios uiscrollview animated

我有一个包含按钮的UIScrollView。 按下按钮时,我想使用scrollRectToVisible滚动到视图的底部。

例如:

CGRect r = CGRectMake(0, myUIScrollView.contentSize.height - 1, 1, 1);
[myUIScrollView scrollRectToVisible:r animated:YES];

如果我将动画设置为NO,则一切都按预期工作, 但如果我把它设置为YES,我会看到非常奇怪的行为:

  • 基本上没有任何反应。
  • 如果我反复点击按钮,它可能会滚动几个像素, 或者可以一直滚动。
  • 但是如果我在按下按钮之前用手指手动滚动视图, 它有可能按预期滚动到底部,但这不是一个确定的事情。

我已经打印了_geScroll_Settings.contentSize,这是预期的。

我也尝试通过启动计时器来延迟调用scrollRectToVisible,但结果几乎相同。

scrollView非常香草。 我在界面构建器中创建它。 我在启动时动态添加scrollView的内容,并适当地调整它的contentSize,但所有这些似乎都正常工作。

有什么想法吗?

2 个答案:

答案 0 :(得分:6)

我敢打赌,scrollRectToVisible因为可见区域无效(1x1)或 y offset 刚好超出界限而被淘汰,你试过用可见的大小设置它吗?而不是scrollView的区域?

CGRect rectBottom = CGRectZero;
rectBottom.size = myUIScrollView.frame.size;
rectBottom.origin.y = myUIScrollView.contentSize.height - rectBottom.size.height;
rectBottom.origin.x = 0;

[myUIScrollView scrollRectToVisible:rectBottom animated:YES];

抱歉,我无法帮助你,但我现在不在我的Mac上,所以我无法进行测试。上面的代码将创建一个CGRect,其大小适合scrollView可见部分,并且偏移量将是其中最后一个可见部分。

答案 1 :(得分:0)

我遇到了类似的问题,包括“如果我将动画设置为NO,一切都按预期工作”部分。

事实证明,在iOS 6上,UITextView会自动滚动其最近的父UIScrollView,使光标成为第一响应者时可见。在iOS 7上没有这样的行为。 UIScrollView似乎对两次调用scrollRectToVisible几乎同时感到困惑。

在iOS 6上,我大部分时间忽略对scrollRectToVisible的显式调用。它只会滚动以使UITextView的第一行可见(自动滚动),而不是像在iOS 7上那样。

要测试它,在Xcode 5中创建一个新的单一视图应用程序,将其部署目标设置为6.0,并使用下面的代码作为ViewController.m。在iOS 6.1模拟器中运行它,滚动以隐藏UITextView并点击屏幕上的任意位置。您可能需要重试几次,但在大多数情况下,它只会使第一行可见。如果重新启用WORKAROUD定义,UITextView将嵌入其自己的UIScrollView中,并且对scrollRectToVisible的调用将按预期工作。

#import "ViewController.h"

//#define WORKAROUND

@interface ViewController ()
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UITextView *textView;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewTap)]];

    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 240)];
    self.scrollView.contentSize = CGSizeMake(320, 400);
    self.scrollView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:self.scrollView];

#ifdef WORKAROUND
    UIScrollView* dummyScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(20, 280, 280, 100)];
    self.textView = [[UITextView alloc] initWithFrame:dummyScrollView.bounds];
    [dummyScrollView addSubview:self.textView];
    [self.scrollView addSubview:dummyScrollView];
#else
    self.textView = [[UITextView alloc] initWithFrame:CGRectMake(20, 280, 280, 100)];
    [self.scrollView addSubview:self.textView];
#endif

    self.textView.backgroundColor = [UIColor grayColor];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)viewTap
{
    if (self.textView.isFirstResponder) {
        [self.textView resignFirstResponder];
    }
    else {
        [self.textView becomeFirstResponder];
    }
}

- (void)keyboardWasShown:(NSNotification*)aNotification
{
#ifdef WORKAROUND
    [self.scrollView scrollRectToVisible:CGRectInset(self.textView.superview.frame, 0, -10) animated:YES];
#else
    [self.scrollView scrollRectToVisible:CGRectInset(self.textView.frame, 0, -10) animated:YES];
#endif
}

@end