如何在输入时阻止UITextView向上滚动

时间:2009-07-24 14:20:19

标签: iphone uitableview uitextview

UITextView中包含UITableViewCell。最初显示视图时,布局是正确的,但是一旦我点击UITextView,它会自动向上滚动一下,第一行上的字符的上半部分变为不可见。

此图片是UITextView未激活时的图像:
UITextView not active http://gerodt.homeip.net/uitextview-notactive.png

当我点击UITextView使其激活时,这个是: UITextView active http://gerodt.homeip.net/uitextview-active.png

我根本不向上滚动UITextView,它应该简单地保持固定。我怎样才能做到这一点?我已经在Interface Builder尝试了几个设置,但到目前为止没有运气。

任何建议都表示赞赏。

格罗

6 个答案:

答案 0 :(得分:61)

UITextView是UIScrollView的子类,因此它具有可配置的contentInset属性。不幸的是,如果你尝试在UITextView实例上更改contentInset,那么底边插入总是被重置为32.我之前使用简短的UITextView框架遇到了这个问题,并发现这是一个问题。我怀疑这是导致问题的原因,但您应该在调试器中检查textview的contentInset以确定。

变通方法/解决方案很简单:子类UITextView并覆盖contentInset方法,以便它始终返回UIEdgeInsetZero。试试这个:

//
// BCTextView
//
// UITextView seems to automatically be resetting the contentInset
// bottom margin to 32.0f, causing strange scroll behavior in our small
// textView.  Maybe there is a setting for this, but it seems like odd behavior.
// override contentInset to always be zero.
//
@interface BCZeroEdgeTextView : UITextView
@end

@implementation BCZeroEdgeTextView

- (UIEdgeInsets) contentInset { return UIEdgeInsetsZero; }

@end 

答案 1 :(得分:16)

这就是UITextView根据Apple工程师的行为,UITextView适用于高度至少为几行的文本。没有解决方法,使用UITextField代替或将UITextView增加到至少3行高。

答案 2 :(得分:6)

您也可以这样做:

textView.contentInset=UIEdgeInsetsZero;

在您的委托文件中。

答案 3 :(得分:2)

UITextViewUIScrollView的子类,因此答案涉及contentOffset属性,即正在更改的属性,而不是插入内容或内容大小。如果首次出现视图时滚动位置正确,则可以存储内容偏移以供以后调用。

YourViewController.h剪断

@interface YourViewController : UIViewController <UITextViewDelegate, UIScrollViewDelegate>

@property(nonatomic, weak) IBOutlet UITextView *textView;

@end

YourViewController.m代码段

@implementation YourViewController {
@private
    BOOL _freezeScrolling;
    CGFloat _lastContentOffsetY;
}

// UITextViewDelegate
- (void)textViewDidBeginEditing:(UITextView *)textView {
    // tell the view to hold the scrolling
    _freezeScrolling = YES;
    _lastContentOffsetY = self.textView.contentOffset.y;
}

// UITextViewDelegate
- (void)textViewDidEndEditing:(UITextView *)textView {
    _freezeScrolling = NO;
}

// UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (_freezeScrolling) {
        // prevent the scroll view from actually scrolling when we don't want it to
        [self repositionScrollView:scrollView newOffset:CGPointMake(scrollView.contentOffset.x, _lastContentOffsetY)];
    }
}

// UIScrollViewDelegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    // scroll prevention should only be a given scroll event and turned back off afterward
    _freezeScrolling = NO;
}

// UIScrollViewDelegate
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    // when the layout is redrawn, scrolling animates. this ensures that we are freeing the view to scroll
    _freezeScrolling = NO;
}

/**
 This method allows for changing of the content offset for a UIScrollView without triggering the scrollViewDidScroll: delegate method.
 */
- (void)repositionScrollView:(UIScrollView *)scrollView newOffset:(CGPoint)offset {
    CGRect scrollBounds = scrollView.bounds;
    scrollBounds.origin = offset;
    scrollView.bounds = scrollBounds;
}

在上面的代码示例中,最重要的是最后一种方法。调用任何类型的setContentOffset:实际上会触发滚动,从而调用scrollViewDidScroll:。因此调用setContentOffset:会导致无限循环。设置滚动边界是解决此问题的方法。

简而言之,当我们检测到用户选择了要编辑的文本时,我们告诉视图控制器阻止UITextView滚动。我们还存储当前内容偏移量(因为我们知道位置是我们想要的)。如果UITextView尝试滚动,那么我们会保留内容偏移量,直到滚动停止(触发scrollViewDidEndDecelerating:scrollViewDidEndScrollingAnimation:)。当用户完成编辑时,我们也解冻​​了滚动。

请记住,这是一个基本示例,因此您需要根据所需的确切行为调整代码。

答案 4 :(得分:1)

我遇到了与不受欢迎的UITextView滚动相似的问题。我终于通过在keyboardDidShow:

的末尾重置contentSize来设法修复它
- (void)keyboardDidShow:(NSNotification *)notification {
  textView.contentSize = CGSizeZero;
}

您还需要注册键盘通知,如下所示:

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

在我的情况下,我不希望任何滚动,因为我在contentSizetextViewDidChange内增长textview时)将帧重置为textView的UIScrollView的高度。

答案 5 :(得分:0)

尝试在textview上放置Redraw而不是Scale to Fill。您仍然可能必须捕获委托并保持内容偏移,但它至少应该阻止跳转到点(0,0)。还必须关闭自动调整子视图。它每次都在我身上跳到textview的顶部,这解决了这个问题。

enter image description here