UIScrollView प्रोग्रामेटिक रूप से नीचे स्क्रॉल करें


298

मैं UIScrollViewअपने कोड के नीचे से नीचे स्क्रॉल कैसे कर सकता हूं ? या अधिक सामान्य तरीके से, किसी सबव्यू के किसी भी बिंदु पर?

जवाबों:


626

आप setContentOffset:animated:सामग्री दृश्य के किसी भी भाग को स्क्रॉल करने के लिए UIScrollView के फ़ंक्शन का उपयोग कर सकते हैं । यहाँ कुछ कोड है जो नीचे स्क्रॉल करेगा, मान लें कि आपका स्क्रॉल दृश्य है 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
आप शायद स्क्रोलव्यू से बाहर निकलने के बजाय नीचे स्क्रॉल करना चाहते हैं: CGPoint निचलाऑफ़सेट = CGPointMake (0, [self.scrollView contentSize] .height - self.scrollView.frame.ize.height);
ग्रांटलैंड चबाने

70
आप इनसेट्स को ध्यान में नहीं रख रहे हैं। मुझे लगता है कि आपको इस बॉटम को पसंद करना चाहिए:CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
मार्टिन

1
यह लैंडस्केप मोड में काम नहीं करता है! पूरी तरह से नीचे तक नहीं स्क्रॉल करें
Mo Farhand

1
अगर contentSizeसही से कम है तो यह ठीक से काम नहीं करता है bounds। तो यह इस तरह से होना चाहिए:scrollView.setContentOffset(CGPointMake(0, max(scrollView.contentSize.height - scrollView.bounds.size.height, 0) ), animated: true)
बार्टोलोमिएज सेमेकोज़ी

1
यह नीचे के इनसेट को संभालता है, और 0 से आगे जाता है:let bottomOffsetY = max(collectionView.contentSize.height - collectionView.bounds.height + collectionView.contentInset.bottom, 0)
सेंसफुल

136

आसान कॉपी पेस्टिंग के लिए स्वीकृत उत्तर का स्विफ्ट संस्करण:

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

3
bottomOffset होना चाहिए और आपके उदाहरण में var नहीं होना चाहिए।
होब्स

सच है, इसे बदल दिया है। स्विफ्ट 2 स्टफ :)
एस्कोरॉर्थ

9
आपको यह जांचने की आवश्यकता है कि
स्क्रॉलव्यू.कॉन्स्टेंटसाइज़.शीट

2
जब आपके पास नया नेविगेशन बार हो तो यह समाधान सही नहीं है।
स्विफ्ट

@ जोश, अभी भी उस दिन का इंतज़ार कर रहे हैं जब एसओ को इस बारे में पता चलता है
एलेक्जेंडर जी

53

सबसे सरल समाधान:

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

धन्यवाद। मैं भूल गया कि मैंने अपने स्क्रॉलव्यू को UITableView में बदल दिया है और इस कोड ने UITableView के लिए भी काम किया है, FYI करें।
लेविंसन टेक्नोलोजीज

1
सिर्फ क्यों नहीं: [स्क्रॉलव्यू स्क्रॉलटेक्टोविजुअल: CGRectMake (0, scrollview.contentSize.height, 1, 1) एनिमेटेड: YES];
जोहान्स

29

मौजूदा उत्तर के लिए सिर्फ एक वृद्धि।

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

यह नीचे के इनसेट का भी ख्याल रखता है (यदि आप इसका उपयोग कर रहे हैं कि कीबोर्ड दिखाई देने पर अपने स्क्रॉल दृश्य को समायोजित करने के लिए)


यह सही उत्तर होना चाहिए ... यदि वे कभी कीबोर्ड पॉप अप करते हैं, तो वे दूसरे को नहीं तोड़ेंगे।
बेन गिल्ड

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 18

@ जैफामफोन - पूछने के लिए धन्यवाद। वास्तव में इस बिंदु पर मुझे यह भी पता नहीं है कि हालत किस उद्देश्य से सेवा करने की थी! यह setContentOffset:कमांड है जो महत्वपूर्ण है।
मैट

अगर यह कुछ भी करने के लिए नहीं जा रहा है तो मैं setContentOffset कॉल से बचने के लिए मान लेता हूं?
I_am_jorf

@ जेफामफोन - ऐसा होता था कि डिवाइस के घूमने के बाद एक स्क्रॉल दृश्य फ्रेम के नीचे की तुलना में इसकी सामग्री के नीचे के साथ समाप्त हो सकता था (क्योंकि अगर हम एक स्क्रॉल दृश्य को घुमाते हैं तो इसकी सामग्री निरंतर बनी रहती है, लेकिन स्क्रॉल दृश्य की ऊँचाई के कारण हो सकता है करने के लिए) स्थिति कहती है: यदि ऐसा होता है, तो सामग्री को नीचे फ्रेम के नीचे नीचे रखें। लेकिन यह मेरे लिए मूर्खतापूर्ण था कि जब मैं कोड में चिपकाऊंगा तो उस शर्त को शामिल करूंगा। हालत है सही ढंग से, हालांकि यह क्या के लिए परीक्षण किया गया था के लिए परीक्षण।
मैट

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

एक स्विफ्ट 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स्क्रॉल करने से पहले जांचना चाहते हैं



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

मुझे इस मामले में ऐसा करने का एक और उपयोगी तरीका मिला जो आप यूआईटेबलव्यू का उपयोग कर रहे हैं (जो UIScrollView का एक उपवर्ग है):

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

FYI करें, यह केवल UITableView क्षमता है
OhadM

7

setContentOffset:animated:स्विफ्ट में नीचे स्क्रॉल करने के लिए UIScrollView के फ़ंक्शन का उपयोग करना ।

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 एक सुरक्षित क्षेत्र था। यह स्क्रॉल दृश्य को प्रभावित कर सकता है contentInset

IOS 11 और इसके बाद के संस्करण के लिए, सामग्री इनसेट के साथ नीचे तक ठीक से स्क्रॉल करना। आपको adjustedContentInsetइसके बजाय उपयोग करना चाहिए contentInset। इस कोड की जाँच करें:

  • स्विफ्ट:
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.height + scrollView.adjustedContentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
  • उद्देश्य सी
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

क्षैतिज स्क्रॉल दृश्य के लिए

यदि आप मुझे पसंद करते हैं, तो आपके पास एक क्षैतिज स्क्रॉल दृश्य है और इसे समाप्त करने के लिए स्क्रॉल करना चाहते हैं (मेरे मामले में इसके सबसे दाईं ओर), आपको स्वीकृत उत्तर के कुछ हिस्सों को बदलने की आवश्यकता है:

उद्देश्य सी

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 को बदलते हैं contentSize (उदा। 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 = 0। यह उपयोगकर्ता के लिए बहुत अजीब लग रहा है।

इसे लागू करने का कोड है:

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

यदि 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 बढ़ाएँ:

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

UICollectionViewनकल और चिपकाने में आसानी के लिए स्वीकृत उत्तर के लिए Xamarin.iOS संस्करण

var bottomOffset = new CGPoint (0, CollectionView.ContentSize.Height - CollectionView.Frame.Size.Height + CollectionView.ContentInset.Bottom);          
CollectionView.SetContentOffset (bottomOffset, false);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.