当UITextField成为第一响应者时,禁用UIScrollView滚动

时间:2011-01-03 15:26:38

标签: iphone uiscrollview uitextfield

当嵌入UITextField的{​​{1}}成为第一响应者时,通过让用户输入某个字符,UIScrollView自动滚动到该字段,有没有办法禁用它?

Duplicate rdar://16538222 over

11 个答案:

答案 0 :(得分:61)

以Moshe的回答为基础......

子类UIScrollView并覆盖以下方法:

- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated

留空。完成工作!

答案 1 :(得分:55)

我一直在努力解决同样的问题,最后我找到了解决方案。

我已经调查了如何通过跟踪调用跟踪来完成自动滚动,并发现在[UIFieldEditor scrollSelectionToVisible]中输入字母时会调用内部UITextField。此方法似乎作用于UIScrollView最近祖先的UITextField

因此,在textFieldDidBeginEditing上,将UITextField与新UIScrollView包装在一起,使其大小相同(即将视图插入UITextFieldtextFieldDidEndEditing之间这是超级视图),这将阻止自动滚动。最后在- (void)textFieldDidBeginEditing:(UITextField*)textField { UIScrollView *wrap = [[[UIScrollView alloc] initWithFrame:textField.frame] autorelease]; [textField.superview addSubview:wrap]; [textField setFrame:CGRectMake(0, 0, textField.frame.size.width, textField.frame.size.height)]; [wrap addSubview: textField]; } - (void)textFieldDidEndEditing:(UITextField*)textField { UIScrollView *wrap = (UIScrollView *)textField.superview; [textField setFrame:CGRectMake(wrap.frame.origin.x, wrap.frame.origin.y, wrap.frame.size.width, textField.frame.size.height)]; [wrap.superview addSubview:textField]; [wrap removeFromSuperview]; } 上删除此包装器。

代码如下:

{{1}}

希望这有帮助!

答案 2 :(得分:8)

我遇到同样的问题,即禁用UITextView自动滚动为UITableView的单元格。我能够使用以下方法解决它:

@interface MyTableViewController : UITableViewController<UITextViewDelegate>

@implementation MyTableViewController {
    BOOL preventScrolling;
    // ...
}

// ... set self as the delegate of the text view

- (void)textViewDidBeginEditing:(UITextView *)textView {
    preventScrolling = YES;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (preventScrolling) {
        [self.tableView setContentOffset:CGPointMake(0, -self.tableView.contentInset.top) animated:NO];
    }
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    preventScrolling = NO;
}

当用户自己开始滚动时,定义scrollViewWillBeginDragging用于恢复默认滚动行为。

答案 3 :(得分:6)

正如Taketo所提到的,当UITextField成为第一响应者时,它的第一个父类型视图UIScrollView(如果存在)被滚动以使UITextField可见。最简单的方法是简单地将每个UITextField包装在UIScrollView中(或者理想情况下,将所有UITextField包装在一个虚拟UIScrollView中)。这与Taketo的解决方案非常相似,但是它应该会给你带来更好的性能,并且它会使我的代码(或Interface Builder中的界面)更加清晰。

答案 4 :(得分:3)

根据Luke的回答,为了解决他的解决方案完全禁用自动滚动的问题,您可以选择性地禁用它,如下所示:

var commitDate = item.commitMetaData.commitDate;
var dat = $filter('createDate')(commitDate);

通过这种方式,您可以在Interface Builder中完全设置它以禁用自动滚动,但可以随时完全控制以重新启用它(不过为什么您想要超出我的范围)。

答案 5 :(得分:2)

看起来像UIScrollview包含UITextfield,自动调整其内容偏移量;当textfield成为第一响应者时。 这可以通过首先在相同大小的滚动视图中添加文本字段,然后添加到主滚动视图来解决。而不是直接添加到主scrollview

    // Swift

    let rect = CGRect(x: 0, y: 0, width: 200, height: 50)

    let txtfld = UITextField()
    txtfld.frame = CGRect(x: 0, y: 0, width: rect.width, height: rect.height)

    let txtFieldContainerScrollView = UIScrollView()
    txtFieldContainerScrollView.frame = rect
    txtFieldContainerScrollView.addSubview(txtfld)
    // Now add this txtFieldContainerScrollView in desired UITableViewCell, UISCrollView.. etc
    self.mainScrollView.addSubview(txtFieldContainerScrollView)

    // Am33T

答案 6 :(得分:1)

这就是我这样做的方式:

这非常简单,您可以为任何scrollRectToVisible返回自己的contentOffset。

通过这种方式,您不会损害正常的行为和流程 - 只需在同一个频道中提供相同的功能,并进行自己的改进。

#import <UIKit/UIKit.h>

@protocol ExtendedScrollViewDelegate <NSObject>

- (CGPoint)scrollView:(UIScrollView*)scrollView offsetForScrollingToVisibleRect:(CGRect)rect;

@end

@interface ExtendedScrollView : UIScrollView

@property (nonatomic, unsafe_unretained) id<ExtendedScrollViewDelegate> scrollToVisibleDelegate;

@end

#import "ExtendedScrollView.h"

@implementation ExtendedScrollView

- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
{
    if (_scrollToVisibleDelegate && [_scrollToVisibleDelegate respondsToSelector:@selector(scrollView:offsetForScrollingToVisibleRect:)])
    {
        [self setContentOffset:[_scrollToVisibleDelegate scrollView:self offsetForScrollingToVisibleRect:rect] animated:animated];
    }
    else
    {
        [super scrollRectToVisible:rect animated:animated];
    }
}

@end

答案 7 :(得分:0)

我不知道UIScrollView允许的任何属性。能够禁用它的用户体验很差,恕我直言。

也就是说,有可能继承UIScrollView并覆盖它的一些方法来检查UITextfield在滚动之前不是第一响应者。

答案 8 :(得分:0)

我已经尝试了@ TaketoSano的答案,但似乎不行。我的情况是我没有滚动视图,只有一个包含多个文本字段的视图。

最后,我得到了一个解决方法。我需要两个键盘默认通知名称:

    当键盘显示时,
  • UIKeyboardDidShowNotification;
  • 当键盘隐藏时,
  • UIKeyboardWillHideNotification

以下是我使用的示例代码:

- (void)viewDidLoad {
  [super viewDidLoad];

  ...

  NSNotificationCenter * notificationCetner = [NSNotificationCenter defaultCenter];
  [notificationCetner addObserver:self
                         selector:@selector(_keyboardWasShown:)
                             name:UIKeyboardDidShowNotification
                           object:nil];
  [notificationCetner addObserver:self
                         selector:@selector(_keyboardWillHide:)
                             name:UIKeyboardWillHideNotification
                           object:nil];
}

- (void)_keyboardWasShown:(NSNotification *)note {
  [self.view setFrame:(CGRect){{272.f, 55.f}, {480.f, 315.f}}];
}

- (void)_keyboardWillHide:(NSNotification *)note {
  [self.view setFrame:(CGRect){{272.f, 226.5f}, {480.f, 315.f}}];
}

此处,(CGRect){{272.f, 226.5f}, {480.f, 315.f}}是隐藏键盘时视图的默认框架。当键盘显示时,(CGRect){{272.f, 55.f}, {480.f, 315.f}}是视图的框架。

而且b.t.w.,视图的帧变化将自动应用动画,这真的很完美!

答案 9 :(得分:0)

我有一个集合视图,顶部有一个文本字段,模仿UITableView.tableHeaderView。此文本字段位于负内容偏移空间中,因此它不会干扰集合视图的其余部分。我基本上检测用户是否在滚动视图中执行滚动以及文本字段是否是第一响应者以及滚动视图是否滚动超出滚动视图的内容插入的顶部。这个确切的代码不一定会帮助任何人,但他们可以操纵它以适应他们的情况。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    // This is solving the issue where making the text field first responder
    // automatically scrolls the scrollview down by the height of the search bar.
    if (!scrollView.isDragging && !scrollView.isDecelerating &&
        self.searchField.isFirstResponder &&
        (scrollView.contentOffset.y < -scrollView.contentInset.top)) {

        [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, -scrollView.contentInset.top) animated:NO];
    }
}

答案 10 :(得分:-6)

在viewController :: viewWillAppear()中选择textField时停止滚动视图滚动的更简单方法不要调用[super viewWillAppear];

然后您可以根据需要控制滚动。