सवाल UICollectionView सेल चयन और सेल पुन: उपयोग करें


सेल चयन पर, मैं सेल उपस्थिति को बदलने में संभालना चाहता हूं। मैंने प्रतिनिधि विधि की कल्पना की collectionView:didSelectItemAtIndexPath: और collectionView:didDeselectItemAtIndexPath: वह जगह है जहां मुझे सेल संपादित करना चाहिए।

-(void)collectionView:(UICollectionView *)collectionView 
       didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

    DatasetCell *datasetCell = 
      (DatasetCell *)[collectionView cellForItemAtIndexPath:indexPath];

    [datasetCell replaceHeaderGradientWith:[UIColor skyBlueHeaderGradient]];
    datasetCell.backgroundColor = [UIColor skyBlueColor];
}

तथा

-(void)collectionView:(UICollectionView *)collectionView 
       didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {

    DatasetCell *datasetCell = 
      (DatasetCell *)[collectionView cellForItemAtIndexPath:indexPath];

    [datasetCell replaceHeaderGradientWith:[UIColor grayGradient]];
    datasetCell.backgroundColor = [UIColor myDarkGrayColor];
}

यह ठीक काम करता है, सिवाय इसके कि जब सेल का पुन: उपयोग किया जाता है। अगर मैं इंडेक्स (0, 0) पर सेल का चयन करता हूं, तो यह उपस्थिति को बदलता है लेकिन जब मैं स्क्रॉल करता हूं, तो चयनित स्थिति में एक और सेल होता है।

मुझे विश्वास है कि मुझे इसका उपयोग करना चाहिए UICollectionViewCell तरीका -(void)prepareForReuse पुनर्विक्रय के लिए सेल तैयार करने के लिए (यानी, गैर चयनित राज्य में सेल उपस्थिति सेट करें) लेकिन यह मुझे कठिनाइयों को दे रहा है।

-(void)prepareForReuse {
    if ( self.selected ) {
        [self replaceHeaderGradientWith:[UIColor skyBlueHeaderGradient]];
        self.backgroundColor = [UIColor skyBlueColor];
    } else {
        [self replaceHeaderGradientWith:[UIColor grayGradient]];
        self.backgroundColor = [UIColor myDarkGrayColor];
    }
}

जब मैं शीर्ष पर वापस स्क्रॉल करता हूं, तो सूचकांक (0, 0) पर कक्ष अचयनित स्थिति में होता है।

जब मैंने अभी सेल का उपयोग किया था। बैकग्राउंड देखें, इसे रोकने से रोकने के लिए:

-(void)prepareForReuse {
    self.selected = FALSE;
}

और चयन राज्य इरादे के रूप में काम किया।

कोई विचार?


44
2018-03-27 17:15


मूल


यह अनुशंसा की जाती है कि आप उद्देश्य सी में सत्य / गलत के बजाय हाँ / NO का उपयोग करें - rounak
दस्तावेज़ीकरण के अनुसार, आपको कॉल करना चाहिए [super prepareForReuse]; कॉल के भीतर से prepareForReuse। - Streeter
आपने इस मुद्दे को कैसे हल किया? मुझे भी यही समस्या हुई - Anish 웃
मुझे भी मुझे एक ही समस्या मिली, और मैं इसे हल नहीं कर सकता - Rawan


जवाब:


आपका अवलोकन सही है। कोशिकाओं के पुन: उपयोग के कारण यह व्यवहार हो रहा है। लेकिन आपको इसके साथ कुछ भी करने की ज़रूरत नहीं है prepareForReuse। इसके बजाय अपनी जांच करें cellForItem और तदनुसार गुणों को सेट करें। कुछ इस तरह..

 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cvCell" forIndexPath:indexPath];


if (cell.selected) {
     cell.backgroundColor = [UIColor blueColor]; // highlight selection 
}
else
{
     cell.backgroundColor = [UIColor redColor]; // Default color
}
return cell;
}

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath  {

    UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
    datasetCell.backgroundColor = [UIColor blueColor]; // highlight selection
 }  

 -(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {

UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath]; 
datasetCell.backgroundColor = [UIColor redColor]; // Default color
}

69
2018-04-02 07:26



@iPhoneProgrammatically क्यों? क्या हुआ? - Anil Varghese
चयनित कक्ष छवि परिवर्तन, लेकिन जब चयन स्क्रॉल करता है। - iPhone Programmatically
यदि आपके कोई प्रश्न हैं तो आप इसे एक अलग प्रश्न के रूप में पूछ सकते हैं .. मैंने एक संभावित तरीका सुझाया .. किसी विशेष स्थिति के लिए काम कर सकता है या नहीं भी .. मैं कुछ भी गारंटी नहीं दे सकता! - Anil Varghese
@ अनिल हां कृपया यहां समझाएं। - iPhone Programmatically
धन्यवाद कि पूरी तरह से काम किया! - Plot


फ्रेमवर्क आपके लिए विचारों को बदलने में संभाल लेगा एक बार जब आप अपने सेल की स्थापना करते हैं backgroundView तथा selectedBackgroundView, उदाहरण देखें चयन और हाइलाइट्स के लिए दृश्य राज्य का प्रबंधन:

UIView* backgroundView = [[UIView alloc] initWithFrame:self.bounds];
backgroundView.backgroundColor = [UIColor redColor];
self.backgroundView = backgroundView;

UIView* selectedBGView = [[UIView alloc] initWithFrame:self.bounds];
selectedBGView.backgroundColor = [UIColor whiteColor];
self.selectedBackgroundView = selectedBGView;

आपको केवल अपनी कक्षा में आवश्यकता है जो लागू करता है UICollectionViewDelegate कोशिकाओं को हाइलाइट करने और इस तरह चयनित करने में सक्षम करें:

- (BOOL)collectionView:(UICollectionView *)collectionView
        shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (BOOL)collectionView:(UICollectionView *)collectionView
        shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;
{
    return YES;
}

यह मुझे काम करता है।


23
2017-10-03 11:58



इन दो विधियों (चाहिए हाइलाइट ItemAtIndexPath / shouldSelectItemAtIndexPath) UICollectionViewDelegate में हैं डेटासोर्स नहीं - JakubKnejzlik
बहुत बहुत धन्यवाद, यह केवल मेरे लिए समाधान समाधान है - swiftBoy


यूआईसीओलेक्शन व्यू आईओएस 10 में बदल गया है जो उपरोक्त समाधानों में कुछ समस्याएं पेश करता है।

यहां एक अच्छी मार्गदर्शिका है: https://littlebitesofcocoa.com/241-uicollectionview-cell-pre-fetching

ऑफ-स्क्रीन जाने के बाद सेल अब थोड़ी देर के लिए रहते हैं। जिसका अर्थ है कि कभी-कभी हम एक सेल को पकड़ने में सक्षम नहीं हो सकते हैं didDeselectItemAt indexPath इसे समायोजित करने के लिए। यह स्क्रीन पर अन-अपडेट और अन-रीसाइक्लिंग पर दिखाई दे सकता है। prepareForReuse इस कोने के मामले में मदद नहीं करता है।

सबसे आसान समाधान सेटिंग द्वारा नई स्क्रॉलिंग को अक्षम कर रहा है isPrefetchingEnabled झूठी इसके साथ, सेल के प्रदर्शन के साथ प्रबंधन      cellForItemAt  didSelect  didDeselect काम करता है के रूप में काम करता है।

हालांकि, अगर आप नए चिकनी स्क्रॉलिंग व्यवहार को रखना चाहते हैं तो इसका उपयोग करना बेहतर होगा willDisplay :

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    let customCell = cell as! CustomCell
    if customCell.isSelected {
        customCell.select()
    } else {
        customCell.unselect()
    }
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
    //Don't even need to set selection-specific things here as recycled cells will also go through willDisplay
    return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath) as? CustomCell
    cell?.select()
}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath) as? CustomCell
    cell?.unselect() // <----- this can be null here, and the cell can still come back on screen!
}

उपरोक्त के साथ आप सेल को तब चुनते हैं जब इसे चुना जाता है, स्क्रीन पर अचयनित किया जाता है, पुनर्नवीनीकरण किया जाता है, और फिर पुनः प्रदर्शित होता है।


15
2017-11-22 18:26



आईओएस 10 के लिए होने वाले बदलावों के कारण यह स्वीकार्य उत्तर होना चाहिए - jarrodparkes


अनिल सही रास्ते पर था (उसका समाधान ऐसा लगता है कि इसे काम करना चाहिए, मैंने इस समाधान को स्वतंत्र रूप से विकसित किया)। मैंने अभी भी इस्तेमाल किया है prepareForReuse: सेल सेट करने के लिए विधि selected सेवा मेरे FALSE, फिर में cellForItemAtIndexPath मैं यह देखने के लिए जांच करता हूं कि सेल की अनुक्रमणिका 'संग्रहView.indexPathsForSelectedItems' में है, यदि हां, तो इसे हाइलाइट करें।

कस्टम सेल में:

-(void)prepareForReuse {
    self.selected = FALSE;
}

में cellForItemAtIndexPath: हाइलाइटिंग और dehighlighting पुन: उपयोग कोशिकाओं को संभालने के लिए:

if ([collectionView.indexPathsForSelectedItems containsObject:indexPath]) {
    [collectionView selectItemAtIndexPath:indexPath animated:FALSE scrollPosition:UICollectionViewScrollPositionNone];
    // Select Cell
}
else {
    // Set cell to non-highlight
}

और उसके बाद कक्ष हाइलाइटिंग और dehighlighting संभाल लें didDeselectItemAtIndexPath: तथा didSelectItemAtIndexPath:

यह मेरे लिए एक आकर्षण की तरह काम करता है।


10
2018-06-07 19:08



एकमात्र और सबसे अच्छा तरीका - orkenstein
पुन: उपयोग के लिए तैयार में सुपर कॉल मत भूलना! - NYC Tech Engineer
ReadyForReuse का उपयोग करना काम किया! लेकिन जैसा कि @NYCTechEngineer कहता है, सुपर को कॉल न भूलें। धन्यवाद! - Crashalot


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

चरण 1:

चयनित इंडेक्स को स्टोर करने के लिए संग्रह दृश्य में एक चर बनाएँ, यहां मैंने चयनित क्लाइंट स्तरीय चर का उपयोग किया है जिसे चयनित इंडेक्स कहा जाता है

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

{

    MyCVCell *cell = (MyCVCell*)[collectionView dequeueReusableCellWithReuseIdentifier:@"MyCVCell" forIndexPath:indexPath];    

// When scrolling happens, set the selection status only if the index matches the selected Index

if (selectedIndex == indexPath.row) {

        cell.layer.borderWidth = 1.0;

        cell.layer.borderColor = [[UIColor redColor] CGColor];

    }
    else
    {
        // Turn off the selection
        cell.layer.borderWidth = 0.0;

    }
    return cell;

}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

{
    MyCVCell *cell = (MyCVCell *)[collectionView cellForItemAtIndexPath:indexPath];
    // Set the index once user taps on a cell
    selectedIndex = indexPath.row;
    // Set the selection here so that selection of cell is shown to ur user immediately
    cell.layer.borderWidth = 1.0;
    cell.layer.borderColor = [[UIColor redColor] CGColor];
    [cell setNeedsDisplay];
}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath

{

    MyCVCell *cell = (MyCVCell *)[collectionView cellForItemAtIndexPath:indexPath];

    // Set the index to an invalid value so that the cells get deselected
    selectedIndex = -1;
    cell.layer.borderWidth = 0.0;
    [cell setNeedsDisplay];

}

-anoop


6
2018-05-08 05:42





अपने कस्टम सेल में सार्वजनिक विधि बनाएं:

- (void)showSelection:(BOOL)selection
{
    self.contentView.backgroundColor = selection ? [UIColor blueColor] : [UIColor white];
}

इसके अलावा -prepareForReuse सेल विधि का पुनर्वितरण लिखें:

- (void)prepareForReuse
{
    [self showSelection:NO];
    [super prepareForReuse];
}

और आपके व्यू कंट्रोलर में आपके पास _selectedIndexPath चर होना चाहिए, जो -didSelectItemAtIndexPath में परिभाषित किया गया है और didDeselectItemAtIndexPath में nullified

NSIndexPath *_selectedIndexPath;

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];

    if (_selectedIndexPath) {
        [cell showSelection:[indexPath isEqual:_selectedIndexPath]];
    }
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
    [cell showSelection:![indexPath isEqual:_selectedIndexPath]];// on/off selection
    _selectedIndexPath = [indexPath isEqual:_selectedIndexPath] ? nil : indexPath;
}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
    [cell showSelection:NO];
    _selectedIndexPath = nil;
}

2
2017-07-11 09:34





केवल @stefanB समाधान आईओएस 9.3 पर मेरे लिए काम किया

यहां मुझे क्या बदलना है स्विफ्ट 2 के लिए

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        //prepare your cell here..

        //Add background view for normal cell
        let backgroundView: UIView = UIView(frame: cell!.bounds)
        backgroundView.backgroundColor = UIColor.lightGrayColor()
        cell!.backgroundView = backgroundView

        //Add background view for selected cell
        let selectedBGView: UIView = UIView(frame: cell!.bounds)
        selectedBGView.backgroundColor = UIColor.redColor()
        cell!.selectedBackgroundView = selectedBGView

        return cell!
 }

 func collectionView(collectionView: UICollectionView, shouldHighlightItemAtIndexPath indexPath: NSIndexPath) -> Bool {
        return true
 }

 func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
        return true
 }

1
2018-04-26 08:48



क्यों उपयोग नहीं कर रहा है collectionView(_:willDisplayCell:forItemAtIndexPath:) बजाय? - eMdOS


मैंने इसे हल करने के लिए क्या किया था अनुकूलित सेल में बदलाव करना। आपके पास एक कस्टम सेल है DataSetCell अपनी कक्षा में आप निम्नलिखित कर सकते हैं (कोड तेजी से है)

override var isSelected: Bool {
    didSet {
        if isSelected {
            changeStuff
        } else {
            changeOtherStuff
        }
    }
}

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


1
2018-05-16 15:53





आप बस पृष्ठभूमि के चयनित बैकग्राउंड व्यू को पृष्ठभूमि रंग = x सेट कर सकते हैं।

अब जब भी आप सेल पर टैप करते हैं तो उसका चयनित मोड स्वचालित रूप से बदल जाएगा और एक्स में बदलने के लिए पृष्ठभूमि रंग को couse करेगा।


0
2017-07-20 16:00





आपके उत्तर के लिए धन्यवाद @आरडीसी

निम्नलिखित कोड के साथ काम करता है स्विफ्ट 3

// MARK: - UICollectionViewDataSource protocol
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    //prepare your cell here..
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MyCell
    cell.myLabel.text =  "my text"

    //Add background view for normal cell
    let backgroundView: UIView = UIView(frame: cell.bounds)
    backgroundView.backgroundColor = UIColor.lightGray
    cell.backgroundView = backgroundView

    //Add background view for selected cell
    let selectedBGView: UIView = UIView(frame: cell.bounds)
    selectedBGView.backgroundColor = UIColor.green
    cell.selectedBackgroundView = selectedBGView

    return cell
}

// MARK: - UICollectionViewDelegate protocol
func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool {
    return true
}

func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
    return true
}

0
2017-10-18 13:35