कैसे पता करें कि जब UITableView ने iPhone में नीचे स्क्रॉल किया था


100

मैं जानना चाहूंगा कि किसी UITableViewसामग्री को लोड करने और दिखाने के लिए नीचे की ओर स्क्रॉल करने पर, एक प्रतिनिधि या कुछ और जैसा कि नियंत्रक को यह बताने के लिए कि तालिका को नीचे स्क्रॉल करने के लिए क्या करना है।

क्या किसी को यह पता है, कृपया मेरी मदद करो, अग्रिम धन्यवाद!

जवाबों:


18

सबसे अच्छा तरीका स्क्रीन के नीचे एक बिंदु का परीक्षण करना है और जब उपयोगकर्ता स्क्रॉल करता है तो इस पद्धति कॉल का उपयोग करें scrollViewDidScroll:

- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point

स्क्रीन के निचले भाग के पास एक बिंदु का परीक्षण करें, और फिर indexPath का उपयोग करके यह जांचता है कि क्या IndexPath अंतिम पंक्ति है, यदि यह है, तो पंक्तियों को जोड़ें।


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

247

तालिका में प्रतिनिधि कुछ इस तरह करते हैं

ObjC:

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;
    // NSLog(@"offset: %f", offset.y);   
    // NSLog(@"content.height: %f", size.height);   
    // NSLog(@"bounds.height: %f", bounds.size.height);   
    // NSLog(@"inset.top: %f", inset.top);   
    // NSLog(@"inset.bottom: %f", inset.bottom);   
    // NSLog(@"pos: %f of %f", y, h);

    float reload_distance = 10;
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
    }
}

स्विफ्ट:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let offset = scrollView.contentOffset
    let bounds = scrollView.bounds
    let size = scrollView.contentSize
    let inset = scrollView.contentInset
    let y = offset.y + bounds.size.height - inset.bottom
    let h = size.height
    let reload_distance:CGFloat = 10.0
    if y > (h + reload_distance) {
        print("load more rows")
    }
}

अच्छा! बस का उपयोग करें: y> = h + reload_distance, जो वास्तव में केवल एक चिंता का विषय है जब reload_distance = 0 (उदाहरण के लिए, उछाल नहीं)।
क्रिस प्रिंस

4
"ScrollViewDidScroll" में यह कोड हर समय उपयोगकर्ता द्वारा स्क्रीन पर अपनी उंगली ऊपर / नीचे ले जाने के लिए निष्पादित किया जा रहा है। इसे "स्क्रॉलव्यूडीडइंडएक्लेरेटिंग" के तहत स्थानांतरित करना बेहतर है। इस तरह से इसे तब निष्पादित किया जाएगा जब उपयोगकर्ता अपनी उंगली हिलाना बंद कर देगा।
मीशा

हम्म .. यह कोड अभी भी काम करता है? मेरे लिए UITableView का निचला भाग नहीं मिल रहा है। काश, मुझे पता था कि ऊपर दिए गए सभी कोड के पीछे का तर्क शायद मैं ठीक कर सकता हूं
फ़्लोयूआई। SimpleUITesting.com

ऑफसेट: 237.000000 कंटेंट.हाइट: 855.000000 बाउंड्स .height: 667.000000 inset.top: 64.000000 inset.bottom: 49.000000 पॉज़: 855.000000 का 855.000000 अगर गलत हो रहा है
अभिषेक थपलियाल

62

संशोधित नवजात शिशु थोड़ा जवाब देते हैं।

यह उत्तर उन लोगों को लक्षित करता है जो केवल यह चाहते हैं कि घटना उंगली के जारी होने के बाद शुरू हो जाए ।

कुछ सामग्री प्रदाता (वेब ​​सेवा, कोर डेटा आदि) से अधिक सामग्री लोड करते समय उपयुक्त। ध्यान दें कि यह दृष्टिकोण आपकी वेब सेवा से प्रतिक्रिया समय का सम्मान नहीं करता है।

- (void)scrollViewDidEndDragging:(UIScrollView *)aScrollView
                  willDecelerate:(BOOL)decelerate
{
    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;

    float reload_distance = 50;
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
    }
}

यह काम नहीं करता है। जब भी उपयोगकर्ता नीचे स्क्रॉल करता है, तो "अधिक पंक्तियों को लोड करें" कहा जाता है। यह तब भी होता है जब उपयोगकर्ता पहले ही नीचे स्क्रॉल कर चुका होता है और डेटा वापस करने के लिए एपीआई की प्रतीक्षा कर रहा होता है।
डीन

2
डीन, यह सवाल जानने के बारे में था कि टेबल व्यू को नीचे तक कैसे स्क्रॉल किया गया। आप एक एपीआई से डेटा प्राप्त कर रहे हैं या नहीं अप्रासंगिक है, यह नहीं है?
आईबॉल

लेकिन अधिक लोड दिखाने वाला कोई संदेश नहीं है .. ताकि उपयोगकर्ता को यह पता चल सके कि दिखाने के लिए अधिक परिणाम हैं।
iPhone 7

मेरे मामले में अच्छा जवाब अगर यह काम कर रहा है: फ्लोट reload_distance = 10; अगर (y> (h - reload_distance)) {NSLog (@ "अधिक पंक्तियाँ लोड करें"); } क्योंकि y = 565 और h भी 565 है
अभिषेक थपलियाल

1
मैंने आईबॉल के दोनों और @neoneye के उत्तर की कोशिश की। मुझे स्क्रॉल करें या नहीं 'ScrollViewDidScroll' को 'ScrollViewDidEndDragging' की तुलना में कई बार कहा गया। इसलिए 'स्क्रॉलव्यूडीडइंड्रैगिंग' का उपयोग करना मेरे लिए बहुत आसान था क्योंकि मेरे पास इस पर एपीआई कॉल है।
विनोद सुपेकर

39

इस विधि को इसमें जोड़ें UITableViewDelegate:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{   
    CGFloat height = scrollView.frame.size.height;

    CGFloat contentYoffset = scrollView.contentOffset.y;

    CGFloat distanceFromBottom = scrollView.contentSize.height - contentYoffset;

    if(distanceFromBottom < height) 
    {
        NSLog(@"end of the table");
    }
}

3
मैं एक छोटे से विस्तार को छोड़कर इस समाधान को पसंद करता हूं। if (दूरीफरमबॉटम <= ऊंचाई)
मार्क मैक्कोरले

इससे मुझे अपनी समस्या का निवारण करने में मदद मिली, धन्यवाद !! एक टैब बार !! यह एक बेवकूफ टैब बार था !!
दिमित्रो

यह एक आकर्षण की तरह काम करता है, और यह सरल भी है, लेकिन मुझे एक छोटी सी समस्या का सामना करना पड़ रहा है जैसे कि यह अंतिम पंक्ति में दो या तीन बार निष्पादित हो रहा है। कैसे यह केवल एक बार निष्पादित करने के लिए जब यह tableview की अंतिम पंक्ति तक पहुँचने?
आर। मोहन

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

20

ऊपर दिए गए किसी भी उत्तर ने मेरी मदद नहीं की, इसलिए मैं इसके साथ आया:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)aScrollView
{   
    NSArray *visibleRows = [self.tableView visibleCells];
    UITableViewCell *lastVisibleCell = [visibleRows lastObject];
    NSIndexPath *path = [self.tableView indexPathForCell:lastVisibleCell];
    if(path.section == lastSection && path.row == lastRow)
    {
        // Do something here
    }
}

क्या आप विस्तार से बता सकते हैं कि "लास्ट सेक्शन" कहाँ से आता है?
अनीसोफ़र

यह स्क्रॉल दृश्य के लिए है न कि टेबल
iosMentalist

19

उपयोग – tableView:willDisplayCell:forRowAtIndexPath:( UITableViewDelegateविधि)

indexPathयदि अंतिम तत्व प्रदर्शित किया जा रहा है, तो यह पता लगाने के लिए कि आपके डेटा ऐरे (या आपके टेबल व्यू के लिए आप जो भी डेटा स्रोत का उपयोग करते हैं) की वस्तुओं के साथ तुलना करें ।

डॉक्स: http://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDelegate/tableView:willDisplayCell:forRowAtIndexPath :


फिर, यदि आप तालिका दृश्य डेटा पुनः लोड करते हैं, तो आप एक अनंत लूप में फंस जाएंगे।
डायल्सन सेल्स

14

UITableViewका उपवर्ग है UIScrollView, और इसके UITableViewDelegateअनुरूप है UIScrollViewDelegate। तो आपके द्वारा टेबल दृश्य से जुड़े प्रतिनिधि को इस तरह की घटनाएँ मिलेंगी scrollViewDidScroll:, और आप contentOffsetस्क्रॉल स्थिति को खोजने के लिए टेबल व्यू जैसे तरीकों को कॉल कर सकते हैं ।


हां, वही है जो मैं देख रहा हूं, उस प्रतिनिधि को कार्यान्वित करके और जांचें कि क्या स्क्रॉल स्थिति UITableViewScrollPositionBottom है, मुझे पता चल जाएगा कि तालिका नीचे से स्क्रॉल कब है, धन्यवाद इतना
सोन गुयेन

8
NSLog(@"%f / %f",tableView.contentOffset.y, tableView.contentSize.height - tableView.frame.size.height);

if (tableView.contentOffset.y == tableView.contentSize.height - tableView.frame.size.height)
        [self doSomething];

अच्छा और सरल


8

Swiftआप में कुछ ऐसा हो सकता है। हर बार जब आप तालिका के अंत तक पहुँचते हैं, तो निम्नलिखित शर्त सही होगी

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        if indexPath.row+1 == postArray.count {
            println("came to last row")
        }
}

1
समस्या यह है कि जब टेबलव्यू में केवल 3 सेल होते हैं उदाहरण के लिए println("came to last row")यह कोड चलता है!
McLover

@ Mc.Lover जो मेरे लिए सटीक समस्या थी जिसके लिए CPU उपयोग 92% हो रहा था। मेरे लिए नीनी का जवाब काम कर गया। अगर आपको जरूरत है तो मैंने इसके लिए स्विफ्ट वर्जन भी जोड़ा है।
अनुराग बर्मन

7

@ माय मेयू के उत्तर पर निर्माण, जो मुझे लगा कि बेहतर समाधानों में से एक है:

उद्देश्य सी

// UITableViewDelegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

// Need to call the service & update the array
if(indexPath.row + 1 == self.sourceArray.count) {
    DLog(@"Displayed the last row!");
  }
}

स्विफ्ट 2.x

// UITableViewDelegate
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    if (indexPath.row + 1) == sourceArray.count {
        print("Displayed the last row!")
    }
}

5

मैं आमतौर पर इसका उपयोग अधिक डेटा लोड करने के लिए करता हूं, जब अंतिम सेल डिस्प्ले शुरू होता है

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   if (indexPath.row ==  myDataArray.count-1) {
        NSLog(@"load more");
    }
}

1
ये गलत है। हर बार जब आप पुनः लोड करते हैं तो एक अनुरोध किया जाएगा। और कभी-कभी आपको केवल टेबल को फिर से लोड करने की आवश्यकता होती है।
पैट्रिक बासुत

आप यह कहना चाहते हैं, यदि आपका अंतिम सेल है और फिर पुनः लोड डेटा बनाया है तो यह होगा?
शैक रियाज़

5

Neoneye उत्कृष्ट उत्तर ले रहा है, लेकिन तेजी से, और चर का नाम बदलने में ..

मूल रूप से हम जानते हैं कि यदि हम yOffsetAtBottomतालिका सामग्री ऊंचाई से परे हैं, तो हम तालिका दृश्य के निचले भाग पर पहुंच गए हैं ।

func isTableViewScrolledToBottom() -> Bool {
    let tableHeight = tableView.bounds.size.height
    let contentHeight = tableView.contentSize.height
    let insetHeight = tableView.contentInset.bottom

    let yOffset = tableView.contentOffset.y
    let yOffsetAtBottom = yOffset + tableHeight - insetHeight

    return yOffsetAtBottom > contentHeight
}

5

यहां स्विफ्ट 3.0 संस्करण कोड है।

   func scrollViewDidScroll(_ scrollView: UIScrollView) {

        let offset = scrollView.contentOffset
        let bounds = scrollView.bounds
        let size = scrollView.contentSize
        let inset = scrollView.contentInset
        let y: Float = Float(offset.y) + Float(bounds.size.height) + Float(inset.bottom)
        let height: Float = Float(size.height)
        let distance: Float = 10

        if y > height + distance {
            // load more data
        }
    }

3

मेरा समाधान यह है कि अनुमानित ऑफसेट पर सारणी को कम करने से पहले कोशिकाओं को जोड़ना है। यह वेग से अनुमानित है।

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)offset {

    NSLog(@"offset: %f", offset->y+scrollView.frame.size.height);
    NSLog(@"Scroll view content size: %f", scrollView.contentSize.height);

    if (offset->y+scrollView.frame.size.height > scrollView.contentSize.height - 300) {
        NSLog(@"Load new rows when reaches 300px before end of content");
        [[DataManager shared] fetchRecordsNextPage];
    }
}

3

स्विफ्ट 3 के लिए अपडेट

नीनी के उत्तर ने मेरे लिए उद्देश्य सी में सबसे अच्छा काम किया, यह स्विफ्ट 3 में उत्तर के बराबर है:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    let offset: CGPoint = scrollView.contentOffset
    let bounds: CGRect = scrollView.bounds
    let size: CGSize = scrollView.contentSize
    let inset: UIEdgeInsets = scrollView.contentInset
    let y: CGFloat = offset.y + bounds.size.height - inset.bottom
    let h: CGFloat = size.height
//        print("offset: %f", offset.y)
//        print("content.height: %f", size.height)
//        print("bounds.height: %f", bounds.size.height)
//        print("inset.top: %f", inset.top)
//        print("inset.bottom: %f", inset.bottom)
//        print("position: %f of %f", y, h)

    let reloadDistance: CGFloat = 10

    if (y > h + reloadDistance) {
            print("load more rows")
    }
}

2

मैं अपने किसी भी 1 पूर्ण टेबलव्यू पर कुछ कार्रवाई करना चाहता हूं।

तो कोड लिंक है:

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSArray* cells = self.tableView.visibleCells;
    NSIndexPath *indexPath = nil ;

    for (int aIntCount = 0; aIntCount < [cells count]; aIntCount++)
    {

        UITableViewCell *cell = [cells objectAtIndex:aIntCount];
CGRect cellRect = [self.tableView convertRect:cell.frame toView:self.tableView.superview];

        if (CGRectContainsRect(self.tableView.frame, cellRect))
        {
            indexPath = [self.tableView indexPathForCell:cell];

    //  remain logic
        }
     }
}

यह किसी एक को मदद कर सकता है।


0

@ नीनी के जवाब ने मेरे लिए काम किया। यहां इसका स्विफ्ट 4 संस्करण है

    let offset = scrollView.contentOffset
    let bounds = scrollView.bounds
    let size = scrollView.contentSize
    let insets = scrollView.contentInset
    let y = offset.y + bounds.size.height - insets.bottom
    let h = size.height
    let reloadDistance = CGFloat(10)
    if y > h + reloadDistance {
        //load more rows
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.