【问题标题】:How to stop UITextView from scrolling up when entering it输入时如何阻止UITextView向上滚动
【发布时间】:2010-11-13 18:17:39
【问题描述】:

我有一个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 中尝试了几种设置,但到目前为止都没有运气。

欢迎提出任何建议。

格罗

【问题讨论】:

  • 您使用的是什么版本的 SDK? 3.0?

标签: iphone uitableview uitextview


【解决方案1】:

UITextView 是UIScrollView 的子类,因此答案涉及contentOffset 属性,这是正在更改的内容,而不是插入或内容大小。如果第一次出现视图时滚动位置是正确的,那么您可以存储内容偏移量以供以后调用。

YourViewController.h 被剪断

@interface YourViewController : UIViewController <UITextViewDelegate, UIScrollViewDelegate>

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

@end

YourViewController.m sn-p

@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:)。当用户完成编辑时,我们也会解冻滚动。

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      我遇到了与不受欢迎的UITextView 滚动类似的问题。我终于设法通过在 keyboardDidShow: 末尾重置 contentSize 来解决它

      - (void)keyboardDidShow:(NSNotification *)notification {
        textView.contentSize = CGSizeZero;
      }
      

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

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

      在我的情况下,我不想要任何滚动,因为我在 textViewDidChange 时将框架重置为 textView 的 contentSize 的高度(在 UIScrollView 内增长 textview)。

      【讨论】:

        【解决方案4】:

        你也可以这样做:

        textView.contentInset=UIEdgeInsetsZero;
        

        在您的委托文件中。

        【讨论】:

          【解决方案5】:

          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 
          

          【讨论】:

          • 还有我,正是我想要的。
          • 当您这样做时,在第一行输入时,自动更正气泡将不可见。
          • 很好的答案!顺便说一句,你也可以只做 textView.contentInset = UIEdgeInsetsZero;如果您不想子类化。 :)
          • @Chintan Patel AS 在此答案中指出,即使您将其设置为其他值,底部边缘也会设置为 32
          • 非常感谢 - 您的代码现在是 MobileNotifier 的一部分 :)
          【解决方案6】:

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

          【讨论】:

          • 谢谢。我将高位增加到 55,字体大小为 12,现在可以按我的意愿工作。
          猜你喜欢
          • 2011-03-11
          • 1970-01-01
          • 1970-01-01
          • 2017-11-24
          • 1970-01-01
          • 2021-11-30
          • 2011-05-05
          • 1970-01-01
          • 2012-03-23
          相关资源
          最近更新 更多