簡體   English   中英

如何以編程方式強制停止 UIScrollView 中的滾動?

[英]How can I programmatically force-stop scrolling in a UIScrollView?

注意: 這里給出的答案對我不起作用。

我有一個 UIScrollView (不是表格視圖,只是一個自定義的東西),當用戶采取某些操作時,我想終止視圖內的任何滾動(拖動或減速)。 我試過這樣做:

[scrollView scrollRectToVisible:CGRectInset([scrollView bounds], 10, 10) animated:NO];

理論上,給定一個已知可見的矩形,滾動將停止在它所在的位置,但事實證明這沒有任何影響——顯然滾動視圖看到給定的矩形在邊界內並需要沒有動作。 如果我給出一個絕對超出當前可見邊界但在視圖的 contentSize 范圍內的矩形,我可以讓滾動停止。 這似乎按預期停止了視圖......但也導致它跳轉到其他位置。 我可能可以在邊緣做一些玩弄以使其正常工作,但是有沒有人知道一種干凈的方法來停止正在執行它的滾動視圖?

謝謝。

我玩了一下你原來的解決方案,這似乎工作得很好。 我認為您幾乎擁有它,但是您只是抵消了您使用過多的矩形,而忘記了您可以將矩形直接滾動回原始矩形。

任何滾動動作的通用解決方案是這樣的:

- (void)killScroll 
{
    CGPoint offset = scrollView.contentOffset;
    offset.x -= 1.0;
    offset.y -= 1.0;
    [scrollView setContentOffset:offset animated:NO];
    offset.x += 1.0;
    offset.y += 1.0;
    [scrollView setContentOffset:offset animated:NO];
}

[編輯] 從 iOS 4.3(可能更早)開始,這似乎也有效

- (void)killScroll 
{
    CGPoint offset = scrollView.contentOffset;
    [scrollView setContentOffset:offset animated:NO];
}

通用的答案是, [scrollView setContentOffset:offset animated:NO][scrollView setContentOffset:offset]

  • [scrollView setContentOffset:offset animated:NO]實際上會停止任何正在運行的動畫。
  • [scrollView setContentOffset:offset]不會停止任何正在運行的動畫。
  • scrollView.contentOffset = offset相同:不會停止任何正在運行的動畫。

這在任何地方都沒有記錄,但這是在 iOS 6.1 和 iOS 7.1 上測試過的行為——可能之前也是如此。

所以停止正在運行的動畫/減速的解決方案很簡單:

// Objective-C
[scrollView setContentOffset:scrollView.contentOffset animated:NO];
// Swift
scrollView.setContentOffset(scrollView.contentOffset, animated:false)

基本上是大衛劉在他編輯的答案中所說的。 但我想澄清一下,這兩個 API並不相同。

對我來說, David Lui 上面接受的答案對我不起作用。 這就是我最終做的事情:

- (void)killScroll {
    self.scrollView.scrollEnabled = NO;
    self.scrollView.scrollEnabled = YES;
}

對於它的價值,我使用的是 iOS 6.0 iPhone 模擬器。

這就是我為滾動視圖和所有其他相關子類所做的:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
 {
    *targetContentOffset = scrollView.contentOffset;
 }

這會將targetContentOffset設置為scrollView的當前偏移量,從而使滾動停止,因為它已到達目標。 使用目的是用戶可以設置目標contentOffset的方法實際上是有意義的。

迅速

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    targetContentOffset.pointee = scrollView.contentOffset
}

快速停止滾動:

scrollView.setContentOffset(scrollView.contentOffset, animated: false)

實際上......最“現代”的方式是-->

scrollview.panGestureRecognizer.enabled = false;
scrollview.panGestureRecognizer.enabled = true;

這會停用負責滾動片刻的手勢識別器,這將終止當前的觸摸。 用戶需要抬起手指並將其放回以再次開始滾動。

編輯:這實際上只是殺死了用戶的當前拖動,但如果滾動視圖當前處於此狀態,則不會立即停止減速。 為此,接受的答案編輯幾乎是最好的方法 xD

[scrollview setContentOffset: scrollview.contentOffset animated:false];

最干凈的方法是繼承 UIScrollView 並提供您自己的 setContentOffset 方法。 當您尚未打開freeze布爾屬性時,這才應該傳遞消息。

像這樣:

BOOL freeze; // and the @property, @synthesize lines..

-(void)setContentOffset:(CGPoint)offset
{
    if ( !freeze ) [super setContentOffset:offset];
}

然后,凍結:

scrollView.freeze = YES;

這個答案對我有用: 停用 UIScrollView 減速

-(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{
    [scrollView setContentOffset:scrollView.contentOffset animated:YES];
}

禁用僅滾動用戶交互。 (迅速)

scrollView.isScrollEnabled = false

拖動后在滾動動畫期間禁用。 (迅速)

var scrollingByVelocity = false

func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
    if !scrollingByVelocity {
        scrollView.setContentOffset(scrollView.contentOffset, animated: false)
    }
}

斯威夫特 5+

通過使用擴展

extension UIScrollView  {
    
    func stopDecelerating() {
        let contentOffset = self.contentOffset
        self.setContentOffset(contentOffset, animated: false)
    }
}

利用

    myScrollView.stopDecelerating()
    // your stuff

這在Swift 4.2中對我有用:

   func killScroll() {
    self.scrollView.isScrollEnabled = false;
    self.scrollView.isScrollEnabled = true;
}

...作為擴展:

extension UIScrollView {
    func killScroll() {
        self.isScrollEnabled = false;
        self.isScrollEnabled = true;

    }
}

我在collectionview中嘗試過這種方法:

self.collectionView.collectionViewLayout.finalizeCollectionViewUpdates()

我只想在滾動視圖中的某個 UIView 是滑動期間的觸摸源時禁用滾動。 將 UIView 移到 UIScrollView 之外需要進行相當多的重構,因為我們有一個復雜的視圖層次結構。

作為一種解決方法,我向要防止滾動的子視圖添加了一個 UIPanGestureRecognizer。 此 UIPanGestureRecognizer 將cancelsTouchesInView ,從而阻止 UIScrollView 的 panGesture 激活。

這有點像“hack”,但它是一個超級簡單的改變,如果你使用的是 XIB 或 Storyboard,你需要做的就是將平移手勢拖到相關的子視圖上。

斯威夫特 5,Xcode 13

在我的示例中,我遇到了用戶內部有滾動視圖和圖像的情況,當用戶開始縮放圖像時需要防止內部自由滾動,我使用滾動視圖和內容偏移的委托功能。 不要忘記scrollView.delegate = self ,如果需要完整代碼不要害羞通知我的我的代碼:

private var contentOffsetHolder: CGPoint = CGPoint(x: 0, y: 0)
    
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        contentOffsetHolder = scrollView.contentOffset
        
    }
    
    func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
        scrollView.setContentOffset(contentOffsetHolder, animated:false)
    }

暫無
暫無

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

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