UICollectionView वर्तमान दृश्यमान सेल इंडेक्स


115

मैं UICollectionViewअपने iPad एप्लिकेशन में पहली बार उपयोग कर रहा हूं । मैंने ऐसा सेट किया है UICollectionViewकि इसका आकार और सेल आकार समान है, इसका मतलब है कि केवल एक बार सेल को एक बार में प्रदर्शित किया जाता है।

समस्या: अब जब उपयोगकर्ता UICollectionView को स्क्रॉल करता है तो मुझे यह जानना होगा कि कौन सी सेल दिखाई दे रही है मुझे परिवर्तन पर अन्य UI तत्वों को अपडेट करना होगा। मुझे इसके लिए कोई प्रतिनिधि विधि नहीं मिली। इसे कैसे प्राप्त किया जा सकता है?

कोड:

[self.mainImageCollection setTag:MAIN_IMAGE_COLLECTION_VIEW];
[self.mainImageCollection registerClass:[InspirationMainImageCollectionCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
[self.mainImageFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.mainImageFlowLayout setMinimumInteritemSpacing:0.0f];
[self.mainImageFlowLayout setMinimumLineSpacing:0.0f];
self.mainImageFlowLayout.minimumLineSpacing = 0;
[self.mainImageCollection setPagingEnabled:YES];
[self.mainImageCollection setShowsHorizontalScrollIndicator:NO];
[self.mainImageCollection setCollectionViewLayout:self.mainImageFlowLayout];

मैंने क्या कोशिश की है:

के UICollectionViewअनुरूप होने पर UIScrollView, मुझे तब मिला जब उपयोगकर्ता स्क्रॉल UIScrollViewDelegateविधि के साथ समाप्त होता है

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

लेकिन उपरोक्त कार्य के अंदर मैं वर्तमान दृश्यमान सेल इंडेक्स कैसे प्राप्त कर सकता हूं UICollectionView???


self.collectionViewFloors.indexPathsForVisibleItems
Aznix

जवाबों:


130

विधि [collectionView viewCells] आपको वह सभी दृश्य प्रदान करती है जो आप चाहते हैं। जब आप प्राप्त करना चाहते हैं तो इसका उपयोग करें

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    for (UICollectionViewCell *cell in [self.mainImageCollection visibleCells]) {
        NSIndexPath *indexPath = [self.mainImageCollection indexPathForCell:cell];
        NSLog(@"%@",indexPath);
    }
}

5 स्विफ्ट के लिए अद्यतन:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    for cell in yourCollectionView.visibleCells {
        let indexPath = yourCollectionView.indexPath(for: cell)
        print(indexPath)
    }
}

क्या आप कृपया विस्तार से बता सकते हैं कि self.mainImageCollection कहाँ से आता है? अपने आगे के विवरण के लिए अग्रिम में कई thanx।
बेंजामिन मैकफेरेन

@BenjaminMcFerren यह आपके द्वारा उपयोग किया जाने वाला संग्रह है।
LE SANG

10
scrollViewDidScroll:प्रतिनिधि विधि पुस्तक अपडेट देख जब भी कोई पुस्तक खत्म (और शायद यहाँ एक बेहतर विकल्प है) प्रदान करता है। scrollViewDidEndDecelerating:प्रतिनिधि पद्धति के विपरीत, जिसे केवल तब ही कहा जाता है जब स्क्रॉल दृश्य " एक बड़े स्क्रॉल से रुकता है" (UIScrollView हेडर देखें)।
सैम स्पेन्सर

1
IIRC, ..DidScrollछोटी स्क्रॉल के दौरान भी कई बार कॉल किया जाता है। कोई क्या करना चाहता है, इस पर निर्भर रहना अच्छी बात हो सकती है या नहीं भी।
टूलमेकरसैट

4
IOS 10 के बाद से अब indexPathsForVoubleItems को सीधे इस्तेमाल करना भी संभव हो गया है :)
Ben

174

indexPathsForVisibleItemsज्यादातर स्थितियों के लिए काम कर सकते हैं, लेकिन कभी-कभी यह एक सरणी को एक से अधिक सूचकांक पथ के साथ लौटाता है और यह मुश्किल हो सकता है जिसे आप चाहते हैं। उन स्थितियों में, आप ऐसा कुछ कर सकते हैं:

CGRect visibleRect = (CGRect){.origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];

यह विशेष रूप से अच्छी तरह से काम करता है जब आपके संग्रह के दृश्य में प्रत्येक आइटम पूरी स्क्रीन को लेता है।

स्विफ्ट संस्करण

let visibleRect = CGRect(origin: collectionView.contentOffset, size: collectionView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
let visibleIndexPath = collectionView.indexPathForItem(at: visiblePoint)

9
मैं सहमत हो सकता हूं, कभी-कभी indexPathsForVanishItems अधिक सेल देता है, भले ही हमें लगता है कि ऐसा मामला नहीं होना चाहिए। आपका समाधान महान काम करता है।
एमपी 23

2
मैं पूरी तरह से इस तरह की स्थिति पर था, बस एक फिक्स जो मेरे लिए काम करता था (लेकिन मेरा मामला टेबलव्यू के साथ था), मुझे CGPointMake (CGRectGetMidX (दृश्यमान), CGRectGetMetY (दृश्यमान)) को बदलने की आवश्यकता थी; CGPointMake (CGRectGetMidX (दृश्यमान), CGRectGetMinY (दृश्यमान)) के लिए;
JRafaelM

1
उत्कृष्ट, लेकिन अगर कोशिकाओं के बीच एक स्थान है, तो visibleIndexPathकभी-कभी शून्य होगा, इसलिएif (visibleIndexPath) == nil { let cells = collectionView.visibleCells() let visibleIndexPath = collectionView.indexPathForCell(cells[0] as! UICollectionViewCell)! as NSIndexPath }
हुसाम

एकमात्र समाधान जिसने मेरी पूर्ण स्क्रीन आकार की कोशिकाओं के लिए काम किया। नीचे दिए गए उत्तर के रूप में स्विफ्ट संस्करण जोड़ा गया।
सैम बिंग

1
काश मैं इसे और बढ़ा पाता। यह समस्या मुझे पागल कर रही है और इस समाधान ने दिन बचा लिया।
सीनटी

77

स्विफ्ट 5 :

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    var visibleRect = CGRect()

    visibleRect.origin = collectionView.contentOffset
    visibleRect.size = collectionView.bounds.size

    let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)

    guard let indexPath = collectionView.indexPathForItem(at: visiblePoint) else { return } 

    print(indexPath)
}

वर्किंग उत्तर संयुक्त स्विफ्ट 2.2 में:

 func scrollViewDidEndDecelerating(scrollView: UIScrollView) {

        var visibleRect = CGRect()

        visibleRect.origin = self.collectionView.contentOffset
        visibleRect.size = self.collectionView.bounds.size

        let visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect))

        let visibleIndexPath: NSIndexPath = self.collectionView.indexPathForItemAtPoint(visiblePoint)

        guard let indexPath = visibleIndexPath else { return } 
        print(indexPath)

    }

दो बार इंडेक्सपथ प्राप्त करना, मुझे केवल एक बार प्राप्त करने की आवश्यकता है
अरशद शैक

18

संपूर्णता के लिए, यह वह विधि है जो मेरे लिए काम करना समाप्त कर देती है। यह @Anthony & @ iAn के तरीकों का एक संयोजन था।

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
      CGRect visibleRect = (CGRect){.origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
      CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
      NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];
      NSLog(@"%@",visibleIndexPath);
}

11

यह शायद UICollectionViewDelegate तरीकों का उपयोग करने के लिए सबसे अच्छा होगा: (स्विफ्ट 3)

// Called before the cell is displayed    
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    print(indexPath.row)
}

// Called when the cell is displayed
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    print(indexPath.row)
}

3
के बारे में didEndDisplaying, डॉक्स से: प्रतिनिधि कि निर्दिष्ट सेल संग्रह दृश्य से निकाल दिया गया था बताता है। यह पता लगाने के लिए इस पद्धति का उपयोग करें जब एक संग्रह दृश्य से सेल को हटा दिया जाता है, जैसा कि यह देखने के लिए कि यह देखने के लिए कि यह कब गायब हो जाता है, निगरानी के विपरीत है। इसलिए मुझे नहीं लगता didEndDisplayingकि सेल प्रदर्शित होने पर इसे कहा जाता है।
जॉनी

9

बस दूसरों के लिए जोड़ना चाहते हैं: किसी कारण के लिए, मैं उस सेल को नहीं मिला जो उपयोगकर्ता को दिखाई दे रहा था जब मैं पेजिंग में पिछले सेल में स्क्रॉलिंग के साथ स्क्रॉल कर रहा था ।

इसलिए मैं इसे कुछ "हवा" देने के लिए dispatch_async के अंदर कोड सम्मिलित करता हूं और यह मेरे लिए काम करता है।

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    dispatch_async(dispatch_get_main_queue(), ^{
            UICollectionViewCell * visibleCell= [[self.collectionView visibleCells] objectAtIndex:0];


            [visibleCell doSomthing];
        });
}

यह वास्तव में मदद की! मुझे महसूस नहीं हुआ कि मैं इसे बिल्कुल निर्दोष बनाने के लिए डिस्पैच_संकल्प ब्लॉक का उपयोग कर सकता हूं! यह सबसे अच्छा जवाब है!
कलफुन

1
स्विफ्ट 4 के लिए: DispatchQueue.main.async {जब कॉल कुछ इस तरह से शुरू होता हैfunc tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
जॉनी

कुछ स्पष्टीकरण: इससे मुझे भी मदद मिली, और मुझे भी ऐसी ही / समान समस्या थी, जब uicollectionview युक्त uitableviewcell पर वापस स्क्रॉल किया गया। willDisplay cellऊपर बताए अनुसार ताज़ा कॉल आरंभ हुआ । मुझे लगता है कि समस्या, UIKit में कहीं न कहीं, वास्तव में मेरे मामले में भी यही है।
जॉनी

7

स्विफ्ट 3.0 के लिए

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let visibleRect = CGRect(origin: colView.contentOffset, size: colView.bounds.size)
    let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
    let indexPath = colView.indexPathForItem(at: visiblePoint)
}

6

स्विफ्ट 3.0

सबसे सरल समाधान जो आपको दृश्य कोशिकाओं के लिए इंडेक्सपैथ देगा।

yourCollectionView.indexPathsForVisibleItems 

इंडेक्सपाथ के सरणी को वापस करेगा।

बस इस तरह से सरणी से पहली वस्तु ले लो।

yourCollectionView.indexPathsForVisibleItems.first

मुझे लगता है कि यह उद्देश्य - सी के साथ ठीक काम करना चाहिए।


6

UICollectionView वर्तमान दृश्यमान सेल इंडेक्स: स्विफ्ट 3

var visibleCurrentCellIndexPath: IndexPath? {
    for cell in self.collectionView.visibleCells {
        let indexPath = self.collectionView.indexPath(for: cell)
        return indexPath
     }

     return nil
}

सबसे बढ़िया उत्तर। साफ और कुछ लाइनों।
गरदा

1
बिल्कुल सही जवाब .. धन्यवाद
हार्दिक ठक्कर

3

धर्मान्तरित @ एंथनी के स्विफ्ट 3.0 के जवाब ने मेरे लिए पूरी तरह से काम किया:

func scrollViewDidScroll(_ scrollView: UIScrollView) {

    var visibleRect = CGRect()
    visibleRect.origin = yourCollectionView.contentOffset
    visibleRect.size = yourCollectionView.bounds.size
    let visiblePoint = CGPoint(x: CGFloat(visibleRect.midX), y: CGFloat(visibleRect.midY))
    let visibleIndexPath: IndexPath? = yourCollectionView.indexPathForItem(at: visiblePoint)
    print("Visible cell's index is : \(visibleIndexPath?.row)!")
}

2

आप इसके लिए उपयोग कर सकते हैं scrollViewDidEndDecelerating:

//@property (strong, nonatomic) IBOutlet UICollectionView *collectionView;

   - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{

        for (UICollectionViewCell *cell in [self.collectionView visibleCells]) {
            NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
            NSUInteger lastIndex = [indexPath indexAtPosition:[indexPath length] - 1];
            NSLog(@"visible cell value %d",lastIndex);
        }

    }

0

यह पुराना सवाल है लेकिन मेरे मामले में ...

- (void) scrollViewWillBeginDragging:(UIScrollView *)scrollView {

    _m_offsetIdx = [m_cv indexPathForCell:m_cv.visibleCells.firstObject].row;
}

- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    _m_offsetIdx = [m_cv indexPathForCell:m_cv.visibleCells.lastObject].row;
}

0

इस स्निपेट को भी देखें

let isCellVisible = collectionView.visibleCells.map { collectionView.indexPath(for: $0) }.contains(inspectingIndexPath)

0

इस थ्रेड में, बहुत सारे समाधान हैं जो ठीक काम करते हैं यदि सेल पूरी स्क्रीन लेती है लेकिन वे संग्रहणीय दृश्य सीमा और दृश्यमान आयत के मध्यबिंदु का उपयोग करते हैं हालांकि इस समस्या का एक सरल समाधान है

    DispatchQueue.main.async {
        let visibleCell = self.collImages.visibleCells.first
        print(self.collImages.indexPath(for: visibleCell))
    }

इसके द्वारा, आप दृश्यमान सेल का इंडेक्सपाथ प्राप्त कर सकते हैं। मैंने DispatchQueue जोड़ा है क्योंकि जब आप तेजी से स्वाइप करते हैं और यदि एक संक्षिप्त क्षण के लिए अगले सेल को दिखाया जाता है तो बिना dispactchQueue के आपको संक्षिप्त रूप से दिखाए गए सेल का IndexPath मिल जाएगा न कि स्क्रीन पर प्रदर्शित होने वाला सेल।


-1

यह कोशिश करो, यह काम करता है। (नीचे दिए गए उदाहरण में मेरे पास उदाहरण के लिए 3 सेल हैं।)

    func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    let visibleRect = CGRect(origin: self.collectionView.contentOffset, size: self.collectionView.bounds.size)
    let visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect))
    let visibleIndexPath = self.collectionView.indexPathForItemAtPoint(visiblePoint)
    if let v = visibleIndexPath {
        switch v.item {
        case 0: setImageDescription()
            break
        case 1: setImageConditions()
            break
        case 2: setImageResults()
            break
        default: break
        }
    }

-2

स्विफ्ट 3 और स्विफ्ट 4:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
   var visibleRect = CGRect()

   visibleRect.origin = collectionView.contentOffset
   visibleRect.size = collectionView.bounds.size

   let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)

   guard let indexPath = collectionView.indexPathForItem(at: visiblePoint) else { return } 

   print(indexPath[1])
}

यदि आप वास्तविक संख्या दिखाना चाहते हैं तो आप +1 जोड़ सकते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.