UITableViewCell पूरी तरह से दिखाई दे रहा है या नहीं यह जांचने का सबसे अच्छा तरीका है


100

मेरे पास अलग-अलग ऊंचाइयों की कोशिकाओं के साथ एक यूआईटेबल व्यू है और मुझे यह जानना होगा कि वे पूरी तरह से दिखाई देते हैं या नहीं।

फिलहाल मैं यह देखने के लिए दिखाई देने वाली कोशिकाओं की सूची में प्रत्येक सेल के माध्यम से लूपिंग कर रहा हूं कि क्या यह हर बार दृश्य स्क्रॉल होने पर पूरी तरह से दिखाई देता है। क्या यह सबसे अच्छा तरीका है?

यहाँ मेरा कोड है:

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {

    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;    
    NSArray* cells = myTableView.visibleCells;

    for (MyCustomUITableViewCell* cell in cells) {

        if (cell.frame.origin.y > offset.y &&
            cell.frame.origin.y + cell.frame.size.height < offset.y + bounds.size.height) {

            [cell notifyCompletelyVisible];
        }
        else {

            [cell notifyNotCompletelyVisible];
        }
    }
}

संपादित करें:

कृपया ध्यान दें कि * - (NSArray ) दृश्यमान कोशिकाएं दृश्यमान कोशिकाएं देती हैं जो पूरी तरह से और आंशिक रूप से दृश्यमान होती हैं।

2 संपादित करें:

यह दोनों lnafziger और वादिम येलगिन से समाधान के संयोजन के बाद संशोधित कोड है :

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
    NSArray* cells = myTableView.visibleCells;
    NSArray* indexPaths = myTableView.indexPathsForVisibleRows;

    NSUInteger cellCount = [cells count];

    if (cellCount == 0) return;

    // Check the visibility of the first cell
    [self checkVisibilityOfCell:[cells objectAtIndex:0] forIndexPath:[indexPaths objectAtIndex:0]];

    if (cellCount == 1) return;

    // Check the visibility of the last cell
    [self checkVisibilityOfCell:[cells lastObject] forIndexPath:[indexPaths lastObject]];

    if (cellCount == 2) return;

    // All of the rest of the cells are visible: Loop through the 2nd through n-1 cells
    for (NSUInteger i = 1; i < cellCount - 1; i++)
        [[cells objectAtIndex:i] notifyCellVisibleWithIsCompletelyVisible:YES];
}

- (void)checkVisibilityOfCell:(MultiQuestionTableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
    CGRect cellRect = [myTableView rectForRowAtIndexPath:indexPath];
    cellRect = [myTableView convertRect:cellRect toView:myTableView.superview];
    BOOL completelyVisible = CGRectContainsRect(myTableView.frame, cellRect);

    [cell notifyCellVisibleWithIsCompletelyVisible:completelyVisible];
}

3
एक साइड नोट के रूप में, आपको अपने सभी पिछले प्रश्नों पर जाना चाहिए और उन लोगों के उत्तरों को स्वीकार करना चाहिए जिन्होंने आपकी मदद की।
बाब

4
मुझे बताने के लिए धन्यवाद! मैंने उन्हें पहले ही +1 दे दिया था, लेकिन सेट स्वीकृत उत्तर सुविधा के बारे में भूल गया था।
रोहिनजैन

आपका कोड मेरे लिए सही लगता है, और यद्यपि यह जटिल है, यह काम करता है। ठीक नहीं है क्या टूट नहीं है, एह?
कोडाफाई

जवाबों:


125

आप rectForRowAtIndexPath:विधि के साथ एक सेल की परिभाषा प्राप्त कर सकते हैं और इसे CGRectContainsRectफ़ंक्शन का उपयोग करके टेबलव्यू की सीमा के साथ तुलना कर सकते हैं।

ध्यान दें कि यदि यह दिखाई नहीं दे रहा है, तो यह सेल को तुरंत नहीं करेगा, और इस तरह तेजी से होगा।

तीव्र

let cellRect = tableView.rectForRowAtIndexPath(indexPath)
let completelyVisible = tableView.bounds.contains(cellRect)

Obj सी

CGRect cellRect = [tableView rectForRowAtIndexPath:indexPath];
BOOL completelyVisible = CGRectContainsRect(tableView.bounds, cellRect);

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


धन्यवाद! मैंने इस कोड को lnafziger के समाधान के साथ जोड़ दिया है।
रोहिनजैन

11
दूसरे विचार में यह सिर्फ हो सकता हैCGRectContainsRect(tableView.bounds, [tableView rectForRowAtIndexPath:indexPath])
वादिम येलागिन

1
ऐसा क्यों है कि मेरी कोशिका की उत्पत्ति। x = 0, मूल .y = 0, चौड़ाई = 0, ऊंचाई = 0 है? हालांकि UI पर वे सभी 0s नहीं हैं, मैं ऑटो लेआउट, किसी भी विचार का उपयोग कर रहा हूं?
रेनकास्ट

7
स्विफ्ट 3:let completelyVisible = tableView.bounds.contains(tableView.rectForRow(at: indexPath))
cbartel

हम UICollectionView के लिए समान कार्यक्षमता कैसे संभाल सकते हैं?
सत्यम

64

मैं इसे इस तरह से बदलूंगा:

- (void)checkVisibilityOfCell:(MyCustomUITableViewCell *)cell inScrollView:(UIScrollView *)aScrollView {
    CGRect cellRect = [aScrollView convertRect:cell.frame toView:aScrollView.superview];

    if (CGRectContainsRect(aScrollView.frame, cellRect))
        [cell notifyCompletelyVisible];
    else
        [cell notifyNotCompletelyVisible];
}

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView { 
    NSArray* cells = myTableView.visibleCells;

    NSUInteger cellCount = [cells count];
    if (cellCount == 0)
        return;

    // Check the visibility of the first cell
    [self checkVisibilityOfCell:[cells firstObject] inScrollView:aScrollView];
    if (cellCount == 1)
        return;

    // Check the visibility of the last cell
    [self checkVisibilityOfCell:[cells lastObject] inScrollView:aScrollView];
    if (cellCount == 2)
        return;

    // All of the rest of the cells are visible: Loop through the 2nd through n-1 cells
    for (NSUInteger i = 1; i < cellCount - 1; i++)
        [[cells objectAtIndex:i] notifyCompletelyVisible];
}

<और> अगर स्टेटमेंट में होना चाहिए <= या> =, तो मैं उत्तर में इसे सही करूंगा ...
Aardvark

12

आप कुछ इस तरह से देख सकते हैं कि कितना प्रतिशत दिखाई देता है:

-(void)scrollViewDidScroll:(UIScrollView *)sender
{
    [self checkWhichVideoToEnable];
}

-(void)checkWhichVideoToEnable
{
    for(UITableViewCell *cell in [tblMessages visibleCells])
    {
        if([cell isKindOfClass:[VideoMessageCell class]])
        {
            NSIndexPath *indexPath = [tblMessages indexPathForCell:cell];
            CGRect cellRect = [tblMessages rectForRowAtIndexPath:indexPath];
            UIView *superview = tblMessages.superview;

            CGRect convertedRect=[tblMessages convertRect:cellRect toView:superview];
            CGRect intersect = CGRectIntersection(tblMessages.frame, convertedRect);
            float visibleHeight = CGRectGetHeight(intersect);

            if(visibleHeight>VIDEO_CELL_SIZE*0.6) // only if 60% of the cell is visible
            {
                // unmute the video if we can see at least half of the cell
                [((VideoMessageCell*)cell) muteVideo:!btnMuteVideos.selected];
            }
            else
            {
                // mute the other video cells that are not visible
                [((VideoMessageCell*)cell) muteVideo:YES];
            }
        }
    }
}

यदि तालिका दृश्य वीडियो के साथ 2 कोशिकाओं को प्रदर्शित करने में सक्षम है (उदाहरण के लिए iPad पर), दोनों वीडियो उपरोक्त कोड के साथ खेलेंगे?
जेरोम

@ कैटालिन मैंने आपके समाधान की कोशिश की है लेकिन मेरा टेबलव्यू धीमा हो गया है। स्क्रॉलिंग प्रदर्शन को बेहतर बनाने का कोई तरीका?
राहुल व्यास

@RahulVyas क्षमा करें, लेकिन नहीं :( अपने आंतरिक तत्वों की जांच करें, शायद लेआउट को थोड़ा अनुकूलित किया जा सकता है क्योंकि यह परतों / सब्लेयर्स का संबंध रखता है
कैटलिन

5

डॉक्स से:

दृश्यमान कॉल रिसीवर में दिखाई देने वाली तालिका कोशिकाओं को लौटाता है।

- (NSArray *)visibleCells

वापसी मान एक सरणी जिसमें UITableViewCell ऑब्जेक्ट होते हैं, प्रत्येक प्राप्त तालिका दृश्य में एक दृश्य सेल का प्रतिनिधित्व करता है।

उपलब्धता आईओएस 2.0 और बाद में उपलब्ध है।

इसके अलावा देखें - indexPathsForVoubleRows


4
क्षमा करें, शायद मैं पर्याप्त स्पष्ट नहीं था। मुझे केवल उन कोशिकाओं में दिलचस्पी है जो पूरी तरह से दिखाई दे रही हैं। - (NSArray *) दृश्यमानचैनल और इंडेक्सपैथ्सफॉरविजिवल रोवर दोनों उन कोशिकाओं को वापस करते हैं जो पूरी तरह से दिखाई देती हैं और आंशिक रूप से दिखाई देती हैं। जैसा कि आप मेरे कोड में देख सकते हैं कि मैं पहले से ही उपयोग कर रहा हूं - (NSArray *) दृश्यमान हैं जो पूरी तरह से दिखाई दे रहे हैं। वैसे भी धन्यवाद।
रोहिनजैन

4

अगर आप भी कंटेंटइन्सेट को ध्यान में रखना चाहते हैं, और एक पर्यवेक्षण पर भरोसा नहीं करना चाहते हैं (पर्यवेक्षण में टेबल व्यू फ्रेम 0,0 से कुछ और हो सकता है), यहाँ मेरा समाधान है:

extension UITableView {

    public var boundsWithoutInset: CGRect {
        var boundsWithoutInset = bounds
        boundsWithoutInset.origin.y += contentInset.top
        boundsWithoutInset.size.height -= contentInset.top + contentInset.bottom
        return boundsWithoutInset
    }

    public func isRowCompletelyVisible(at indexPath: IndexPath) -> Bool {
        let rect = rectForRow(at: indexPath)
        return boundsWithoutInset.contains(rect)
    }
}


0
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
CGRect frame = cell.frame;
if (CGRectContainsRect(CGRectOffset(self.collectionView.frame, self.collectionView.contentOffset.x, self.collectionView.contentOffset.y), frame))
{
    // is on screen
}

0

यहां तक ​​कि अगर आपने कहा है कि आप इसे हर बार स्क्रॉल करते समय जांचना चाहते हैं, तो आप भी उपयोग कर सकते हैं

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
       CGRect cellRect = [tableView convertRect:cell.frame toView:tableView.superview];
       if (CGRectContainsRect(tableView.frame, cellRect)){
            //Do things in case cell is fully displayed
        }

}

0

हो सकता है कि इस समस्या के लिए UITableViewDelegate से अगले फ़ंक्शन का बेहतर उपयोग किया गया हो

func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath)

यह काम नहीं करेगा। एक डॉक्टर सेtells the delegate that the specified cell was removed from the table.
anatoliy_v

0

नीचे दिया गया कोड आपको यह देखने देगा कि क्या संग्रह दृश्य सेल पूरी तरह से संग्रह दृश्य के लेआउट विशेषताओं के माध्यम से दिखाई दे रहा है।

guard let cellRect = collectionView.layoutAttributesForItem(at: indexPath)?.frame else { return } let isCellCompletelyVisible = collectionView.bounds.contains(cellRect)

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