UIScrollView เลื่อนไปด้านล่างโดยทางโปรแกรม


298

ฉันจะUIScrollViewเลื่อนไปที่ด้านล่างภายในรหัสของฉันได้อย่างไร หรือในทางที่ทั่วไปมากขึ้นไปยังมุมมองย่อยหรือไม่?

คำตอบ:


626

คุณสามารถใช้setContentOffset:animated:ฟังก์ชันของ UIScrollView เพื่อเลื่อนไปยังส่วนใด ๆ ของมุมมองเนื้อหา นี่คือรหัสบางส่วนที่จะเลื่อนไปด้านล่างโดยสมมติว่า scrollView ของคุณคือself.scrollView:

CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];

หวังว่าจะช่วย!


25
คุณอาจต้องการเลื่อนไปที่ด้านล่างแทนที่จะออกจาก scrollview: CGPoint bottomOffset = CGPointMake (0, [self.scrollView contentSize] .height - self.scrollView.frame.size.height);
Grantland Chew

70
คุณไม่ได้คำนึงถึงสิ่งที่ใส่เข้าไป ฉันคิดว่าคุณควรจะชอบด้านล่างออฟเซ็ต:CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
มาร์ติน

1
ไม่สามารถใช้งานได้ในโหมดแนวนอน! ไม่เลื่อนลงไปด้านล่างอย่างสมบูรณ์
Mo Farhand

1
มัน wil ไม่ทำงานอย่างถูกต้องหากต่ำกว่าcontentSize boundsดังนั้นควรเป็นเช่นนี้:scrollView.setContentOffset(CGPointMake(0, max(scrollView.contentSize.height - scrollView.bounds.size.height, 0) ), animated: true)
BartłomiejSemańczyk

1
นี้จัดการภาพประกอบด้านล่างและจะเกิน 0:let bottomOffsetY = max(collectionView.contentSize.height - collectionView.bounds.height + collectionView.contentInset.bottom, 0)
Senseful

136

คำตอบที่ได้รับการยอมรับอย่างรวดเร็วเพื่อให้ง่ายต่อการวางสำเนา

let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height)
scrollView.setContentOffset(bottomOffset, animated: true)

3
bottomOffset ควรได้รับอนุญาตและไม่ใช่ var ในตัวอย่างของคุณ
Hobbes the Tige

จริงเปลี่ยนมัน swift2 stuff :)
Esqarrouth

9
คุณต้องตรวจสอบว่า scrollView.contentSize.height - scrollView.bounds.size.height> 0 มิฉะนั้นคุณจะได้ผลลัพธ์ที่แปลกกว่านี้
iluvatar_GR

2
วิธีนี้ไม่สมบูรณ์เมื่อคุณมีแถบนำทางใหม่
Swift Rabbit

@ จอช, ยังคงรอวันเพื่อค้นหาเกี่ยวกับเรื่องนี้
Alexandre G

53

วิธีที่ง่ายที่สุด:

[scrollview scrollRectToVisible:CGRectMake(scrollview.contentSize.width - 1,scrollview.contentSize.height - 1, 1, 1) animated:YES];

ขอบคุณ ฉันลืมฉันเปลี่ยน scrollview เป็น UITableView และรหัสนี้ใช้ได้กับ UITableView ด้วยเช่นกัน FYI
Levinson เทคโนโลยี

1
ทำไมไม่เพียง: [เลื่อนดู scrollRectToVisible: CGRectMake (0, scrollview.contentSize.height, 1, 1) ภาพเคลื่อนไหว: ใช่];
โยฮันเนส

29

เป็นเพียงการปรับปรุงคำตอบที่มีอยู่

CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];

ดูแลส่วนล่างของปุ่มด้วยเช่นกัน (ในกรณีที่คุณใช้เพื่อปรับมุมมองเลื่อนของคุณเมื่อมองเห็นแป้นพิมพ์)


นี่ควรเป็นคำตอบที่ถูกต้อง ... ไม่ใช่คำตอบอื่นที่จะทำลายหากพวกเขามีแป้นพิมพ์โผล่ขึ้นมา
Ben Guild

19

การตั้งค่าเนื้อหาให้ตรงกับความสูงของขนาดเนื้อหาไม่ถูกต้อง: มันเลื่อนด้านล่างของเนื้อหาไปที่ด้านบนของมุมมองเลื่อนและทำให้มองไม่เห็น

ทางออกที่ถูกต้องคือการเลื่อนด้านล่างของเนื้อหาไปที่ด้านล่างของมุมมองเลื่อนเช่นนี้ ( svคือ UIScrollView):

CGSize csz = sv.contentSize;
CGSize bsz = sv.bounds.size;
if (sv.contentOffset.y + bsz.height > csz.height) {
    [sv setContentOffset:CGPointMake(sv.contentOffset.x, 
                                     csz.height - bsz.height) 
                animated:YES];
}

1
ไม่ควรif (sv.contentOffset.y + csz.height > bsz.height) {หรือ
i_am_jorf

@jeffamaphone - ขอบคุณที่ถาม จริง ๆ แล้ว ณ จุดนี้ฉันไม่แน่ใจด้วยซ้ำว่าจุดประสงค์อะไรที่เป็นเงื่อนไขที่ควรให้บริการ! มันเป็นsetContentOffset:คำสั่งที่สำคัญ
แมตต์

ฉันคิดว่ามันจะหลีกเลี่ยงการโทร setContentOffset ถ้ามันจะไม่ทำอะไร?
i_am_jorf

@jeffamaphone - มันเคยเป็นหลังจากที่หมุนอุปกรณ์มุมมองเลื่อนอาจจบลงด้วยเนื้อหาด้านล่างสูงกว่าด้านล่างของเฟรม (เพราะถ้าเราหมุนดูเลื่อนเนื้อหาชดเชยของมันยังคงที่ แต่ความสูงมุมมองเลื่อนอาจจะครบกำหนด เพื่อเปลี่ยนขนาดอัตโนมัติ) เงื่อนไขแจ้งว่า: หากเป็นเช่นนั้นให้วางเนื้อหาด้านล่างลงที่ด้านล่างของเฟรม แต่มันเป็นความงี่เง่าของฉันที่จะรวมเงื่อนไขเมื่อฉันวางในรหัส เงื่อนไขคือการทดสอบอย่างถูกต้องสำหรับสิ่งที่ทดสอบ
แมตต์

19

การใช้งานที่รวดเร็ว:

extension UIScrollView {
   func scrollToBottom(animated: Bool) {
     if self.contentSize.height < self.bounds.size.height { return }
     let bottomOffset = CGPoint(x: 0, y: self.contentSize.height - self.bounds.size.height)
     self.setContentOffset(bottomOffset, animated: animated)
  }
}

ใช้มัน:

yourScrollview.scrollToBottom(animated: true)

15

โซลูชัน Swift 2.2 โดยคำนึงcontentInsetถึง

let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)

สิ่งนี้ควรอยู่ในส่วนขยาย

extension UIScrollView {

  func scrollToBottom() {
    let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height + contentInset.bottom)
    setContentOffset(bottomOffset, animated: true)
  }
}

โปรดทราบว่าคุณอาจต้องการตรวจสอบว่าbottomOffset.y > 0ก่อนที่จะเลื่อน


14

เกิดอะไรขึ้นถ้าcontentSizeต่ำกว่าbounds?

สำหรับ Swift มันคือ:

scrollView.setContentOffset(CGPointMake(0, max(scrollView.contentSize.height - scrollView.bounds.size.height, 0) ), animated: true)

13

เลื่อนไปด้านบน

- CGPoint topOffset = CGPointMake(0, 0);
- [scrollView setContentOffset:topOffset animated:YES];

เลื่อนลงล่าง

- CGPoint bottomOffset = CGPointMake(0, scrollView.contentSize.height - self.scrollView.bounds.size.height);
 - [scrollView setContentOffset:bottomOffset animated:YES];

7

ฉันยังพบวิธีที่มีประโยชน์อีกวิธีหนึ่งในการทำเช่นนี้ในกรณีที่คุณใช้ UITableview (ซึ่งเป็นประเภทย่อยของ UIScrollView):

[(UITableView *)self.view scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

FYI นั่นเป็นความสามารถของ UITableView เท่านั้น
OhadM

7

ใช้setContentOffset:animated:ฟังก์ชันของ UIScrollView เพื่อเลื่อนไปด้านล่างใน Swift

let bottomOffset : CGPoint = CGPointMake(0, scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)

5

ดูเหมือนว่าคำตอบทั้งหมดที่นี่ไม่ได้คำนึงถึงพื้นที่ปลอดภัย ตั้งแต่ iOS 11, iPhone X ได้เปิดตัวพื้นที่ปลอดภัย ซึ่งอาจส่งผลกระทบต่อของ contentInsetscrollview

สำหรับ iOS 11 ขึ้นไปเลื่อนไปที่ด้านล่างอย่างถูกต้องโดยมีส่วนแทรกเนื้อหา คุณควรใช้แทนadjustedContentInset contentInsetตรวจสอบรหัสนี้:

  • สวิฟท์:
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.height + scrollView.adjustedContentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
  • Objective-C
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.adjustedContentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];
  • ส่วนขยายที่รวดเร็ว (ซึ่งจะเก็บต้นฉบับไว้contentOffset.x):
extension UIScrollView {
    func scrollsToBottom(animated: Bool) {
        let bottomOffset = CGPoint(x: contentOffset.x,
                                   y: contentSize.height - bounds.height + adjustedContentInset.bottom)
        setContentOffset(bottomOffset, animated: animated)
    }
}

อ้างอิง:


5

ด้วย (เป็นทางเลือก) footerViewและcontentInsetวิธีแก้ไขคือ:

CGPoint bottomOffset = CGPointMake(0, _tableView.contentSize.height - tableView.frame.size.height + _tableView.contentInset.bottom);
if (bottomOffset.y > 0) [_tableView setContentOffset: bottomOffset animated: YES];

4

สวิฟท์:

คุณสามารถใช้ส่วนขยายแบบนี้:

extension UIScrollView {
    func scrollsToBottom(animated: Bool) {
        let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height)
        setContentOffset(bottomOffset, animated: animated)
    }
}

ใช้:

scrollView.scrollsToBottom(animated: true)

3

valdyr หวังว่านี่จะช่วยคุณ:

CGPoint bottomOffset = CGPointMake(0, [textView contentSize].height - textView.frame.size.height);

if (bottomOffset.y > 0)
 [textView setContentOffset: bottomOffset animated: YES];

2

หมวดหมู่เพื่อช่วยเหลือ!

เพิ่มลงในส่วนหัวยูทิลิตี้ที่ใช้ร่วมกันบางแห่ง:

@interface UIScrollView (ScrollToBottom)
- (void)scrollToBottomAnimated:(BOOL)animated;
@end

และจากนั้นไปที่การใช้งานยูทิลิตี้ที่:

@implementation UIScrollView(ScrollToBottom)
- (void)scrollToBottomAnimated:(BOOL)animated
{
     CGPoint bottomOffset = CGPointMake(0, self.contentSize.height - self.bounds.size.height);
     [self setContentOffset:bottomOffset animated:animated];
}
@end

จากนั้นปรับใช้ทุกที่ที่คุณต้องการตัวอย่างเช่น

[[myWebView scrollView] scrollToBottomAnimated:YES];

ใช้เสมอทุกครั้งเสมอใช้ประเภทเสมอ! สมบูรณ์แบบ :)
Fattie

2

สำหรับ ScrollView แนวนอน

หากคุณชอบฉันมี Horizontal ScrollView และต้องการเลื่อนไปยังจุดสิ้นสุด (ในกรณีของฉันไปทางขวาสุด) คุณต้องเปลี่ยนบางส่วนของคำตอบที่ยอมรับ:

Objective-C

CGPoint rightOffset = CGPointMake(self.scrollView.contentSize.width - self.scrollView.bounds.size.width + self.scrollView.contentInset.right, 0 );
[self.scrollView setContentOffset:rightOffset animated:YES];

รวดเร็ว

let rightOffset: CGPoint = CGPoint(x: self.scrollView.contentSize.width - self.scrollView.bounds.size.width + self.scrollView.contentInset.right, y: 0)
self.scrollView.setContentOffset(rightOffset, animated: true)

2

หากคุณเปลี่ยน scrollView เนื้อหาขนาด (เช่นเพิ่มบางอย่างใน stackView ซึ่งอยู่ใน scrollView) คุณต้องโทรscrollView.layoutIfNeeded()ก่อนเลื่อนมิฉะนั้นจะไม่ทำอะไรเลย

ตัวอย่าง:

scrollView.layoutIfNeeded()
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
if(bottomOffset.y > 0) {
    scrollView.setContentOffset(bottomOffset, animated: true)
}

1

วิธีที่ดีในการตรวจสอบให้แน่ใจว่าเนื้อหาของคุณปรากฏอยู่ด้านล่างคือใช้สูตร:

contentOffsetY = MIN(0, contentHeight - boundsHeight)

สิ่งนี้ทำให้มั่นใจได้ว่าขอบด้านล่างของเนื้อหาของคุณจะอยู่ที่หรือสูงกว่าขอบด้านล่างของมุมมองเสมอ MIN(0, ...)ถูกต้องเนื่องจากUITableView(และอาจจะUIScrollView) เพื่อให้แน่ใจว่าcontentOffsetY >= 0เมื่อผู้ใช้พยายามที่จะเลื่อนโดยเห็นได้ชัด contentOffsetY = 0snapping มันดูแปลกสำหรับผู้ใช้

รหัสที่จะใช้นี้คือ:

UIScrollView scrollView = ...;
CGSize contentSize = scrollView.contentSize;
CGSize boundsSize = scrollView.bounds.size;
if (contentSize.height > boundsSize.height)
{
    CGPoint contentOffset = scrollView.contentOffset;
    contentOffset.y = contentSize.height - boundsSize.height;
    [scrollView setContentOffset:contentOffset animated:YES];
}

1

หากคุณไม่ต้องการภาพเคลื่อนไหวการทำงานนี้:

[self.scrollView setContentOffset:CGPointMake(0, CGFLOAT_MAX) animated:NO];

1

ในขณะที่Mattวิธีการแก้ปัญหาดูเหมือนว่าถูกต้องสำหรับคุณคุณต้องคำนึงถึงยังมุมมองการเก็บรวบรวมถ้ามีสิ่งที่ได้รับการตั้งค่า

รหัสที่ดัดแปลงจะเป็น:

CGSize csz = sv.contentSize;
CGSize bsz = sv.bounds.size;
NSInteger bottomInset = sv.contentInset.bottom;
if (sv.contentOffset.y + bsz.height + bottomInset > csz.height) {
    [sv setContentOffset:CGPointMake(sv.contentOffset.x, 
                                     csz.height - bsz.height + bottomInset) 
                animated:YES];
}

1

อย่างรวดเร็ว:

   if self.mainScroll.contentSize.height > self.mainScroll.bounds.size.height {
        let bottomOffset = CGPointMake(0, self.mainScroll.contentSize.height - self.mainScroll.bounds.size.height);
        self.mainScroll.setContentOffset(bottomOffset, animated: true)
    }

1

โซลูชันเพื่อเลื่อนไปยังรายการสุดท้ายของมุมมองตาราง:

สวิฟท์ 3:

if self.items.count > 0 {
        self.tableView.scrollToRow(at:  IndexPath.init(row: self.items.count - 1, section: 0), at: UITableViewScrollPosition.bottom, animated: true)
}

0

ไม่ได้ทำงานสำหรับฉันเมื่อฉันพยายามที่จะใช้ในUITableViewControllerในหลังจากบวกself.tableView (iOS 4.1) footerViewมันเลื่อนออกจากเส้นขอบแสดงหน้าจอสีดำ

ทางเลือกอื่น ๆ :

 CGFloat height = self.tableView.contentSize.height; 

 [self.tableView setTableFooterView: myFooterView];
 [self.tableView reloadData];

 CGFloat delta = self.tableView.contentSize.height - height;
 CGPoint offset = [self.tableView contentOffset];
 offset.y += delta;

 [self.tableView setContentOffset: offset animated: YES];

0
CGFloat yOffset = scrollView.contentOffset.y;

CGFloat height = scrollView.frame.size.height;

CGFloat contentHeight = scrollView.contentSize.height;

CGFloat distance = (contentHeight  - height) - yOffset;

if(distance < 0)
{
    return ;
}

CGPoint offset = scrollView.contentOffset;

offset.y += distance;

[scrollView setContentOffset:offset animated:YES];

0

ฉันพบcontentSizeว่าไม่ได้สะท้อนขนาดจริงของข้อความจริง ๆ ดังนั้นเมื่อพยายามเลื่อนไปที่ด้านล่างสุดจะเป็นการปิดเล็กน้อย วิธีที่ดีที่สุดในการกำหนดขนาดเนื้อหาจริงเป็นจริงที่จะใช้NSLayoutManager's usedRectForTextContainer:วิธีการ:

UITextView *textView;
CGSize textSize = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size;

เมื่อต้องการกำหนดจำนวนข้อความที่แสดงจริงในUITextViewคุณสามารถคำนวณได้โดยการลบการแทรกคอนเทนเนอร์ข้อความจากความสูงของเฟรม

UITextView *textView;
UIEdgeInsets textInsets = textView.textContainerInset;
CGFloat textViewHeight = textView.frame.size.height - textInsets.top - textInsets.bottom;

จากนั้นมันจะง่ายต่อการเลื่อน:

// if you want scroll animation, use contentOffset
UITextView *textView;
textView.contentOffset = CGPointMake(textView.contentOffset.x, textSize - textViewHeight);

// if you don't want scroll animation
CGRect scrollBounds = textView.bounds;
scrollBounds.origin = CGPointMake(textView.contentOffset.x, textSize - textViewHeight);
textView.bounds = scrollBounds;

UITextViewบางตัวเลขสำหรับการอ้างอิงในสิ่งที่ขนาดที่แตกต่างกันสำหรับตัวแทนที่ว่างเปล่า

textView.frame.size = (width=246, height=50)
textSize = (width=10, height=16.701999999999998)
textView.contentSize = (width=246, height=33)
textView.textContainerInset = (top=8, left=0, bottom=8, right=0)

0

ขยาย UIScrollView เพื่อเพิ่มเมธอด scrollToBottom:

extension UIScrollView {
    func scrollToBottom(animated:Bool) {
        let offset = self.contentSize.height - self.visibleSize.height
        if offset > self.contentOffset.y {
            self.setContentOffset(CGPoint(x: 0, y: offset), animated: animated)
        }
    }
}

สิ่งนี้จะเพิ่มคำตอบที่มีอยู่?
สีเทา

-1

คำตอบที่ยอมรับในเวอร์ชันXamarin.iOS

var bottomOffset = new CGPoint (0,
     scrollView.ContentSize.Height - scrollView.Frame.Size.Height
     + scrollView.ContentInset.Bottom);

scrollView.SetContentOffset (bottomOffset, false);

-1

รุ่นXamarin.iOSสำหรับUICollectionViewคำตอบที่ยอมรับเพื่อความสะดวกในการคัดลอกและวาง

var bottomOffset = new CGPoint (0, CollectionView.ContentSize.Height - CollectionView.Frame.Size.Height + CollectionView.ContentInset.Bottom);          
CollectionView.SetContentOffset (bottomOffset, false);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.