【问题标题】:Obj-C- Update UICollectionView data without reloading entire collectionView?Obj-C- 更新 UICollectionView 数据而不重新加载整个 collectionView?
【发布时间】:2021-09-29 18:12:22
【问题描述】:

我有一个UICollectionView,其中选择了单元格时,它们会改为由用户选择的颜色。绘制全图:颜色由用户从带有点击手势的色轮 (UIImageView) 中选择。

也就是说,当用户在选择 3 个单元格并将它们设为绿色后点击一种新颜色,比如紫色(并重置定义的 rString、bString 和 gString...),我想重新加载他们正在使用的颜色而不从集合视图中擦除最初的 3 个选定的绿色单元格。我怎样才能做到这一点?

参见下面的代码。

ViewController.m

  @interface ViewController () {
        
        CGPoint lastPoint;
        NSInteger rString;
        NSInteger bString;
        NSInteger gString;
        UIColor *colour;
        
    }
    
    @property (strong, nonatomic, nullable) NSIndexPath *trackingCellIndexPath;
    
    
    @end
    
    @implementation ViewController
    
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
      
        self.ringCollectionView.allowsMultipleSelection = YES;
    
    UITapGestureRecognizer * tapRecognizer = [[UITapGestureRecognizer alloc] 
     initWithTarget:self action:@selector(tapGesture:)];
     [self.colorWheel addGestureRecognizer:tapRecognizer];
     self.colorWheel.userInteractionEnabled = YES;

    }
    
    - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        
        UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"RingCollectionViewCell" forIndexPath:indexPath];
     
        if (!cell.selectedBackgroundView) {
            cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds];
                   cell.selectedBackgroundView.backgroundColor = [UIColor grayColor];
        } else {
            cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds];
            cell.selectedBackgroundView.backgroundColor = [UIColor colorWithRed:rString/255.0 green:gString/255.0 blue:bString/255.0 alpha:1.0];
            
        }
      
        
        if ((indexPath.row >=9 && indexPath.row <=14) || ((indexPath.row >=17 && indexPath.row < 23) || (indexPath.row >=25 && indexPath.row <=30) ||  (indexPath.row >=33 && indexPath.row <=38))) {
            
            NSLog(@"NOT AVAILABLE SORRY");
            cell.backgroundColor = [UIColor whiteColor];
            
            [cell setUserInteractionEnabled:NO];
            
        }
    
            return cell;
       
    
    }
    
    
    -(void)tapGesture:(UITapGestureRecognizer *)recognizer  {
        
        CGPoint location = [recognizer locationInView:recognizer.view];
        CGPoint p = { round(location.x), round(location.y) };
        _colorView.backgroundColor = [self colorInViewAtPoint:p];
        
       
        UIColor *mylovelycolor = [self colorInViewAtPoint:p];
         
      
           const CGFloat *components = CGColorGetComponents(mylovelycolor.CGColor);
           NSLog(@"Red: %f", components[0]);
           NSLog(@"Green: %f", components[1]);
           NSLog(@"Blue: %f", components[2]);
           NSLog(@"Alpha: %f", CGColorGetAlpha(mylovelycolor.CGColor));
           
    
               int red = components[0] * 255;
               int green = components[1] * 255;
               int blue = components[2] * 255;
           
               NSString *red1 = [@(red) stringValue];
               NSString *green1 = [@(green) stringValue];
               NSString *blue1 = [@(blue) stringValue];
               
               
               NSInteger redInt = [red1 integerValue];
               NSInteger greenInt = [green1 integerValue];
               NSInteger blueInt = [blue1 integerValue];
               
                 rString = [red1 integerValue];
                 bString = [blue1 integerValue];
                 gString =  [green1 integerValue];
        
    
                self.redValue.text = red1;
                self.greenValue.text = green1;
                self.blueValue.text = blue1;
        
                
                        NSMutableString *str1 = [NSMutableString string];
                        for(NSInteger numberCopy = redInt; numberCopy > 0; numberCopy >>= 1)
                        {
                         
                            [str1 insertString:((numberCopy & 1) ? @"1" : @"0") atIndex:0];
                        }
    
                      
                        NSMutableString *str2 = [NSMutableString string];
                        for(NSInteger numberCopy = greenInt; numberCopy > 0; numberCopy >>= 1)
                        {
                         
                            [str2 insertString:((numberCopy & 1) ? @"1" : @"0") atIndex:0];
                        }
    
                     
                        NSMutableString *str3 = [NSMutableString string];
                        for(NSInteger numberCopy = blueInt; numberCopy > 0; numberCopy >>= 1)
                        {
                           
                            [str3 insertString:((numberCopy & 1) ? @"1" : @"0") atIndex:0];
                        }
    
        
                        self.binaryString = [NSString stringWithFormat:@" %@ %@ %@", str1, str2, str3];
        
    }

【问题讨论】:

    标签: ios objective-c uicollectionview


    【解决方案1】:

    您需要在数据模型中跟踪用户选择的颜色。

    cellForItemAtIndexPath 中,您希望将单元格的背景颜色(或您正在使用的任何元素)设置为数据元素颜色。

    当用户选择了一个或多个单元格并点击您的“colorWheel”时,更新您的数据模型,然后直接设置单元格元素或重新加载这些单元格。

    这是一个非常简单的例子...

    MyDataObject.h

    //
    //  MyDataObject.h
    //
    
    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface MyDataObject : NSObject
    @property (strong, nonatomic) UIColor *userColor;
    @end
    
    NS_ASSUME_NONNULL_END
    

    MyDataObject.m

    //
    //  MyDataObject.m
    //
    
    #import "MyDataObject.h"
    
    @implementation MyDataObject
    
    @end
    

    MyCollectionViewCell.h

    //
    //  MyCollectionViewCell.h
    //
    
    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface MyCollectionViewCell : UICollectionViewCell
    @property (strong, nonatomic) UILabel *label;
    @end
    
    NS_ASSUME_NONNULL_END
    

    MyCollectionViewCell.m

    //
    //  MyCollectionViewCell.m
    //
    
    #import "MyCollectionViewCell.h"
    
    @implementation MyCollectionViewCell
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self commonInit];
        }
        return self;
    }
    - (instancetype)initWithCoder:(NSCoder *)coder
    {
        self = [super initWithCoder:coder];
        if (self) {
            [self commonInit];
        }
        return self;
    }
    - (void)commonInit {
        _label = [UILabel new];
        _label.textAlignment = NSTextAlignmentCenter;
        _label.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
        _label.translatesAutoresizingMaskIntoConstraints = NO;
        [self.contentView addSubview:_label];
    
        UILayoutGuide *g = [self.contentView layoutMarginsGuide];
        [NSLayoutConstraint activateConstraints:@[
            [_label.widthAnchor constraintEqualToAnchor:g.widthAnchor multiplier:0.8],
            [_label.heightAnchor constraintEqualToAnchor:g.heightAnchor multiplier:0.8],
            [_label.centerXAnchor constraintEqualToAnchor:g.centerXAnchor],
            [_label.centerYAnchor constraintEqualToAnchor:g.centerYAnchor],
        ]];
        self.contentView.layer.borderColor = [UIColor yellowColor].CGColor;
    }
    - (void)setSelected:(BOOL)selected {
        [super setSelected:selected];
        self.contentView.layer.borderWidth = selected ? 2 : 0;
    }
    @end
    

    MyTestViewController.h

    //
    //  MyTestViewController.h
    //
    
    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface MyTestViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate>
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    MyTestViewController.m

    //
    //  MyTestViewController.m
    //
    
    #import "MyTestViewController.h"
    #import "MyCollectionViewCell.h"
    #import "MyDataObject.h"
    
    @interface MyTestViewController ()
    {
        NSMutableArray <MyDataObject *>*myCellData;
        UICollectionView *collectionView;
    }
    @end
    
    @implementation MyTestViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        UICollectionViewFlowLayout *fl = [UICollectionViewFlowLayout new];
        fl.itemSize = CGSizeMake(50, 50);
        fl.scrollDirection = UICollectionViewScrollDirectionHorizontal;
        
        collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:fl];
        collectionView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:collectionView];
        
        UILayoutGuide *g = [self.view safeAreaLayoutGuide];
        [NSLayoutConstraint activateConstraints:@[
            [collectionView.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:20.0],
            [collectionView.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-20.0],
            [collectionView.heightAnchor constraintEqualToConstant:240.0],
            [collectionView.centerYAnchor constraintEqualToAnchor:g.centerYAnchor],
        ]];
        
        // a few color views to tap, and an
        //  "Instructions" label
        UILabel *label = [UILabel new];
        label.text = @"Tap a color to change the selected cells:";
        
        UIStackView *stack = [UIStackView new];
        
        NSArray *colors = @[
            [UIColor redColor],
            [UIColor greenColor],
            [UIColor blueColor],
            [UIColor systemYellowColor],
            [UIColor systemTealColor],
        ];
        
        for (UIColor *c in colors) {
            UIView *v = [UIView new];
            v.backgroundColor = c;
            UITapGestureRecognizer *t = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gotTap:)];
            [v addGestureRecognizer:t];
            [stack addArrangedSubview:v];
        }
        
        stack.spacing = 20.0;
        stack.distribution = UIStackViewDistributionFillEqually;
        
        label.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:label];
        
        stack.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:stack];
        
        [NSLayoutConstraint activateConstraints:@[
            [stack.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:20.0],
            [stack.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-20.0],
            [stack.bottomAnchor constraintEqualToAnchor:g.bottomAnchor constant:-20.0],
            [stack.heightAnchor constraintEqualToConstant:40.0],
    
            [label.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:20.0],
            [label.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-20.0],
            [label.bottomAnchor constraintEqualToAnchor:stack.topAnchor constant:-4.0],
        ]];
    
        collectionView.dataSource = self;
        collectionView.delegate = self;
        
        collectionView.allowsMultipleSelection = YES;
        
        [collectionView registerClass:MyCollectionViewCell.class forCellWithReuseIdentifier:@"c"];
        
        // create 50 objects for our data
        myCellData = [NSMutableArray new];
        for (int i = 0; i < 50; i++) {
            MyDataObject *obj = [MyDataObject new];
            obj.userColor = [UIColor redColor];
            [myCellData addObject:obj];
        }
        
    }
    
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
        return myCellData.count;
    }
    - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
        
        // dequeue a cell
        MyCollectionViewCell *c = (MyCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"c" forIndexPath:indexPath];
        
        // get the data object
        MyDataObject *obj = (MyDataObject *)[myCellData objectAtIndex:indexPath.item];
        
        // set cell's contentView.backgroundColor to the data object's .userColor
        c.contentView.backgroundColor = obj.userColor;
        
        // set the cell's label text
        c.label.text = [NSString stringWithFormat:@"%ld", indexPath.item];
        
        return c;
    
    }
    
    - (void)gotTap:(UITapGestureRecognizer *)g {
        
        if (collectionView.indexPathsForSelectedItems.count == 0) {
            UIAlertController * alert = [UIAlertController
                                         alertControllerWithTitle:@"Error"
                                         message:@"No cells are selected!"
                                         preferredStyle:UIAlertControllerStyleAlert];
            
            UIAlertAction* okButton = [UIAlertAction
                                       actionWithTitle:@"OK"
                                       style:UIAlertActionStyleDefault
                                       handler:^(UIAlertAction * action) {
            }];
            
            [alert addAction:okButton];
            
            [self presentViewController:alert animated:YES completion:nil];
    
            return;
        }
        
        UIView *v = g.view;
        if (v) {
            // get the background color from the tapped view
            UIColor *color = v.backgroundColor;
            
            // loop through selected cells
            for (NSIndexPath *p in collectionView.indexPathsForSelectedItems) {
                
                // update the object in our data
                [myCellData objectAtIndex:p.item].userColor = color;
                
                // get a reference to the cell
                MyCollectionViewCell *c = (MyCollectionViewCell *)[collectionView cellForItemAtIndexPath:p];
                
                // set its background color
                c.contentView.backgroundColor = color;
                
                // if we want to auto-deselect the cells
                [collectionView deselectItemAtIndexPath:p animated:YES];
            }
        }
    }
    
    @end
    

    所以,

    • 我们的数据对象只有一个属性:userColor
    • 我们的细胞类有一个居中的标签
    • 我们的控制器
      • 创建一个水平滚动的集合视图
      • 创建一个包含 50 个数据对象的数组,默认为红色的 userColor
      • 添加 5 种颜色视图供您选择

    当一个单元格被选中时,它会以黄色勾勒出来。当点击彩色视图时,我们:

    • 更新当前选定单元格的数据模型
    • 设置当前选中单元格的contentView的背景色
    • 取消选择当前选中的单元格

    看起来像这样:

    然后我们选择单元格 5、9、14:

    点击绿色视图:

    然后我们选择单元格 16、17、18:

    点击蓝色视图:

    然后我们滚动一点并选择单元格 17、21、24、25、26:

    点击黄色视图:

    等等。

    【讨论】:

    • 在NSObject中定义UIColor会抛出错误? “未知类型名称 UIColor”?
    • #import &lt;UIKit/UIKit.h&gt;了吗?
    • 啊,漂亮,非常感谢!这正是我所需要的:) 你摇滚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 2014-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多