简体   繁体   English

Obj-C- 更新 UICollectionView 数据而不重新加载整个 collectionView?

[英]Obj-C- Update UICollectionView data without reloading entire collectionView?

I have a UICollectionView where when cells are selected, they change to a color selected by the user.我有一个UICollectionView,其中选择了单元格时,它们会更改为用户选择的颜色。 To paint the full picture: The color is selected by the user from a color wheel (UIImageView) with a tap gesture attached to it.绘制完整图片:用户从色轮 (UIImageView) 中选择颜色,并附加一个点击手势。

That said, when the user taps a new color, say purple (and resets the defined rString, bString & gString...) after selecting 3 cells and making them green, I want to reload the color they're using without wiping the initial 3 selected green cells from the Collection View.也就是说,当用户在选择 3 个单元格并将它们设置为绿色后点击一种新颜色时,比如紫色(并重置定义的 rString、bString 和 gString...),我想重新加载他们正在使用的颜色而不擦除初始颜色3 个从集合视图中选择的绿色单元格。 How can I accomplish this?我怎样才能做到这一点?

See code below.请参阅下面的代码。

ViewController.m视图控制器.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];
        
    }

You need to track your user-selected colors in your data model.您需要在数据模型中跟踪用户选择的颜色。

In cellForItemAtIndexPath you want to set the cell's background color (or whatever element you're using) to the data element color.cellForItemAtIndexPath您希望将单元格的背景颜色(或您使用的任何元素)设置为数据元素颜色。

When the user has one or more cells selected, and taps your "colorWheel," update your data model and then either set the cell elements directly or reload those cells.当用户选择了一个或多个单元格并点击您的“colorWheel”时,更新您的数据模型,然后直接设置单元格元素或重新加载这些单元格。

Here is a very simple example...这是一个非常简单的例子......

MyDataObject.h我的数据对象.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我的数据对象.m

//
//  MyDataObject.m
//

#import "MyDataObject.h"

@implementation MyDataObject

@end

MyCollectionViewCell.h 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

//
//  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

//
//  MyTestViewController.h
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface MyTestViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate>

@end

NS_ASSUME_NONNULL_END

MyTestViewController.m 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

So,所以,

  • our data object has just a single property: userColor我们的数据对象只有一个属性: userColor
  • our cell class has a centered label我们的细胞类有一个居中的标签
  • our controller我们的控制器
    • creates a horizontal scrolling collection view创建一个水平滚动的集合视图
    • creates an array of 50 data objects, with default userColor of red创建一个包含 50 个数据对象的数组,默认userColor为红色
    • adds 5 color views to select from添加了 5 种颜色视图可供选择

When a cell is selected, it will be outlined in yellow.当一个单元格被选中时,它将以黄色勾勒出来。 When a color view is tapped, we:当点击颜色视图时,我们:

  • update the data model for the currently selected cells更新当前选定单元格的数据模型
  • set the background color of the contentView of the currently selected cells设置当前选中单元格的contentView的背景色
  • deselect the currently selected cells取消选择当前选中的单元格

It looks like this:它看起来像这样:

在此处输入图片说明

then we select cells 5, 9, 14:然后我们选择单元格 5、9、14:

在此处输入图片说明

tap on the Green view:点击绿色视图:

在此处输入图片说明

then we select cells 16, 17, 18:然后我们选择单元格 16、17、18:

在此处输入图片说明

tap on the Blue view:点击蓝色视图:

在此处输入图片说明

then we scroll a little and select cells 17, 21, 24, 25, 26:然后我们滚动一点并选择单元格 17、21、24、25、26:

在此处输入图片说明

tap on the Yellow view:点击黄色视图:

在此处输入图片说明

and so on.等等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM