簡體   English   中英

每次更改文本時,如何強制UITextView滾動到頂部?

[英]How do I force a UITextView to scroll to the top every time I change the text?

好的,我在使用UITextView遇到了一些問題。 這是問題所在:

我在UITextView添加了一些文本。 然后用戶雙擊以選擇某些內容。 然后我更改UITextView的文本(以編程方式如上), UITextView滾動到頁面底部有光標。

但是,這不是用戶點擊的地方。 無論用戶點擊何處,它始終滾動到UITextView的底部。

所以這是我的問題:每次更改文本時,如何強制UITextView滾動到頂部? 我已經嘗試過contentOffsetscrollRangeToVisible 都沒有工作。

任何建議,將不勝感激。

UITextView*note;
[note setContentOffset:CGPointZero animated:YES];

這對我來說。

Swift版本(Xcode 9.3上帶有iOS 11的Swift 4.1):

note.setContentOffset(.zero, animated: true)

如果有人在iOS 8中scrollRangeToVisible此問題,我發現只需設置UITextView's文本屬性,然后使用location:0length:0NSRange調用scrollRangeToVisible 我的文本視圖不可編輯,我測試了可選擇的和不可選擇的(兩個設置都沒有影響結果)。 這是一個Swift示例:

myTextView.text = "Text that is long enough to scroll"
myTextView.scrollRangeToVisible(NSRange(location:0, length:0))

這是我的解決方案......

    override func viewDidLoad() {
        textView.scrollEnabled = false
        textView.text = "your text"
    }

    override func viewDidAppear(animated: Bool) {
        textView.scrollEnabled = true
    }

調用

scrollRangeToVisible(NSMakeRange(0, 0))

可以工作,但稱之為

override func viewDidAppear(animated: Bool)

我在HTML中使用了attributionString,文本視圖不可編輯。 設置內容偏移對我來說也不起作用。 這對我有用:禁用啟用滾動,設置文本然后再次啟用滾動

[yourTextView setScrollEnabled:NO];
yourTextView.text = yourtext;
[yourTextView setScrollEnabled:YES];

由於這些解決方案都不適合我,而且浪費了太多時間拼湊解決方案,這最終為我解決了這個問題。

override func viewWillAppear(animated: Bool) {
    dispatch_async(dispatch_get_main_queue(), {
        let desiredOffset = CGPoint(x: 0, y: -self.textView.contentInset.top)
        self.textView.setContentOffset(desiredOffset, animated: false)
    })
}

這非常愚蠢,這不是此控件的默認行為。

我希望這有助於其他人。

我不確定我是否理解你的問題,但你是否只是想將視圖滾動到頂部? 如果是這樣你應該這樣做

[textview scrollRectToVisible:CGRectMake(0,0,1,1) animated:YES];

對於iOS 10和Swift 3,我做了:

override func viewDidLoad() {
    super.viewDidLoad()
    textview.isScrollEnabled = false
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    textView.isScrollEnabled = true
}

為我工作,不確定你是否遇到了最新版本的Swift和iOS的問題。

我有一個更新的答案,它將使textview正確顯示,並且沒有用戶體驗滾動動畫。

override func viewWillAppear(animated: Bool) {
    dispatch_async(dispatch_get_main_queue(), {
        self.introductionText.scrollRangeToVisible(NSMakeRange(0, 0))
    })

這就是它在iOS 9 Release上的工作方式,因為textView在屏幕上顯示之前會滾動到頂部

- (void)viewDidLoad
{
    [super viewDidLoad];
    textView.scrollEnabled = NO;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    textView.scrollEnabled = YES;
}

這就是我做到的

斯威夫特4:

extension UITextView {

    override open func draw(_ rect: CGRect)
    {
        super.draw(rect)
        setContentOffset(CGPoint.zero, animated: false)
    }

 }

嘗試此操作將光標移動到文本的頂部。

NSRange r  = {0,0};
[yourTextView setSelectedRange:r];

看看情況如何。 確保在所有事件都被觸發后或者您正在做的事情完成之后調用此函數。

結合以前的答案,現在它應該工作:

talePageText.scrollEnabled = false
talePageText.textColor = UIColor.blackColor()
talePageText.font = UIFont(name: "Bradley Hand", size: 24.0)
talePageText.contentOffset = CGPointZero
talePageText.scrollRangeToVisible(NSRange(location:0, length:0))
talePageText.scrollEnabled = true

我的問題是在視圖出現時將textView設置為滾動到頂部。 適用於iOS 10.3.2和Swift 3。

解決方案1:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // It doesn't work. Very strange.
    self.textView.setContentOffset(CGPoint.zero, animated: false)
}
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    // It works, but with an animation effection.
    self.textView.setContentOffset(CGPoint.zero, animated: false)
}

解決方案2:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // It works.       
    self.textView.contentOffset = CGPoint.zero
}
[txtView setContentOffset:CGPointMake(0.0, 0.0) animated:YES];

這行代碼適合我。

Swift 2答案:

textView.scrollEnabled = false

/* Set the content of your textView here */

textView.scrollEnabled = true

這可以防止textView在設置后滾動到文本末尾。

在Swift 3中:

  • viewWillLayoutSubviews是進行更改的地方。 viewWillAppear應該也可以工作,但從邏輯上講 ,應該在viewWillLayoutSubviews中執行布局

  • 關於方法, scrollRangeToVisiblesetContentOffset都可以工作。 但是, setContentOffset允許關閉或打開動畫。

假設UITextView被命名為yourUITextView 這是代碼:

// Connects to the TextView in the interface builder.
@IBOutlet weak var yourUITextView: UITextView!

/// Overrides the viewWillLayoutSubviews of the super class.
override func viewWillLayoutSubviews() {

    // Ensures the super class is happy.
    super.viewWillLayoutSubviews()

    // Option 1:
    // Scrolls to a range of text, (0,0) in this very case, animated.
    yourUITextView.scrollRangeToVisible(NSRange(location: 0, length: 0))

    // Option 2:
    // Sets the offset directly, optional animation.
    yourUITextView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
}

這對我有用。 它基於RyanTCBs的答案,但它是同一解決方案的Objective-C變體:

- (void) viewWillAppear:(BOOL)animated {
    // For some reason the text view, which is a scroll view, did scroll to the end of the text which seems to hide the imprint etc at the beginning of the text.
    // On some devices it is not obvious that there is more text when the user scrolls up.
    // Therefore we need to scroll textView to the top.
    [self.textView scrollRangeToVisible:NSMakeRange(0, 0)];
}
-(void) viewDidAppear:(BOOL)animated{
[mytextView scrollRangeToVisible:NSMakeRange(0,0)];}

- (void)viewWillAppear:(BOOL)animated{
[mytextView scrollRangeToVisible:NSMakeRange(0,0)];}
  • ViewWillappear會在用戶注意到之前立即執行此操作,但ViewDidDisappear部分會ViewDidDisappear設置懶惰動畫。
  • [mytextView setContentOffset:CGPointZero animated:YES]; 有時不起作用(我不知道為什么),所以請使用scrollrangetovisible。

問題解決了:iOS = 10.2 Swift 3 UITextView

我只是使用了以下行:

displayText.contentOffset.y = 0

只是你可以使用這段代碼

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    textView.scrollRangeToVisible(NSMakeRange(0, 0))
}

這對我有用

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    DispatchQueue.main.async {
      self.textView.scrollRangeToVisible(NSRange(location: 0, length: 0))
    }
  }
[self.textView scrollRectToVisible:CGRectMake(0, 0, 320, self.textView.frame.size.height) animated:NO];
-(void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];

    [textview setContentOffset:CGPointZero animated:NO];
}

我有問題,但在我的情況下textview是一些自定義視圖的子視圖,並將其添加到ViewController。 這個解決方案都不適合我。 要解決問題,請加0.1秒延遲,然后啟用滾動。 它對我有用。

textView.isScrollEnabled = false
..
textView.text = // set your text here

let dispatchTime = DispatchTime.now() + 0.1
DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
   self.textView.isScrollEnabled = true
}

對我來說,這段代碼很好用:

    textView.attributedText = newText //or textView.text = ...

    //this part of code scrolls to top
    textView.contentOffset.y = -64
    textView.scrollEnabled = false
    textView.layoutIfNeeded() //if don't work, try to delete this line
    textView.scrollEnabled = true

要滾動到確切位置並將其顯示在屏幕頂部,我使用以下代碼:

    var scrollToLocation = 50 //<needed position>
    textView.contentOffset.y = textView.contentSize.height
    textView.scrollRangeToVisible(NSRange.init(location: scrollToLocation, length: 1))

設置contentOffset.y滾動到文本末尾,然后scrollRangeToVisible向上滾動到scrollToLocation的值。 因此,所需位置出現在scrollView的第一行。

對於我來說,iOS 9停止為我工作,使用方法scrollRangeToVisible的屬性字符串(1行是粗體字,其他行是普通字體)

所以我不得不使用:

textViewMain.attributedText = attributedString
textViewMain.scrollRangeToVisible(NSRange(location:0, length:0))
delay(0.0, closure: { 
                self.textViewMain.scrollRectToVisible(CGRectMake(0, 0, 10, 10), animated: false)
            })

延遲是:

func delay(delay:Double, closure:()->Void) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}

嘗試使用這2行解決方案:

view.layoutIfNeeded()
textView.contentOffset = CGPointMake(textView.contentInset.left, textView.contentInset.top)

這是我的代碼。 它工作正常。

class MyViewController: ... 
{
  private offsetY: CGFloat = 0
  @IBOutlet weak var textView: UITextView!
  ...

  override viewWillAppear(...) 
  {
      ...
      offsetY = self.textView.contentOffset.y
      ...
  }
  ...
  func refreshView() {
      let offSetY = textView.contentOffset.y
      self.textView.setContentOffset(CGPoint(x:0, y:0), animated: true)
      DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
        [unowned self] in
        self.textView.setContentOffset(CGPoint(x:0, y:self.offSetY), 
           animated: true)
        self.textView.setNeedsDisplay()
      }
  }

Swift 3版本的drew_s回答較早,這是我在嘗試了大部分其他答案后唯一有用的東西。

    override func viewWillAppear(_ animated: Bool) {
    DispatchQueue.main.async{
        let desiredOffset = CGPoint(x: 0, y: -self.person_description.contentInset.top)
        self.person_description.setContentOffset(desiredOffset, animated: false)
    }
}

這是工作代碼的剪切和粘貼。 將person_description替換為textview變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM