cdts/xdts-ios 3/TreeHole/Code/Utility/MTGridSelect/MTGridSelectView.m

326 lines
11 KiB
Mathematica
Raw Normal View History

2023-07-27 09:20:00 +08:00
//
// MTGridSelectView.m
// MTGridSelectDemo
//
// Created by mambaxie on 2019/1/19.
// Copyright © 2019 tencent. All rights reserved.
//
#import "MTGridSelectView.h"
#import "MTGridSelectConfig.h"
#define kItemContentViewCellReuseIdentifier @"kItemContentViewCellReuseIdentifier"
@interface MTGridSelectModel : NSObject
@property (nonatomic, strong) id model;
@property (nonatomic, assign) MTGridItemState state;
@property (nonatomic, strong) UIView *itemView;
@end
@implementation MTGridSelectModel
@end
@interface MTGridSelectView () <UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, strong) MTGridSelectConfig *config;
@property (nonatomic, copy) void (^setupConfigBlock)(MTGridSelectConfig * _Nonnull);
@property (nonatomic, copy) MTGridDidSetupItemContentViewBlock didSetupItemContentViewBlock;
@property (nonatomic, copy) MTGridItemStateChangedBlock itemStateChangedBlock;
@property (nonatomic, copy) void (^selectValueChangedBlock)(NSArray *selectedModels);
@property (nonatomic, copy) NSArray<MTGridSelectModel *> *itemModels;
@property (nonatomic, strong) MTGridSelectModel *previousSelectItemModel;
@property (nonatomic, strong) NSMutableIndexSet *seletedIndexSet;
@end
@implementation MTGridSelectView
- (instancetype)init
{
if (self = [super init]) {
[self setupConfig];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self setupConfig];
}
return self;
}
- (void)setupConfig
{
MTGridSelectConfig *config = [[MTGridSelectConfig alloc] init];
config.contentWidth = [UIScreen mainScreen].bounds.size.width;
config.contentInset = UIEdgeInsetsMake(15, 15, 15, 15);
config.rowSpacing = 10.0;
config.columnSpacing = 10.0;
config.maxColumn = 3;
config.itemRatio = 0.3;
config.itemHeight = 0.0;
config.itemSize = CGSizeZero;
config.multiple = NO;
config.maxSelecteCount = 3;
self.config = config;
}
+ (instancetype)gridSelectViewWithItemModels:(NSArray *)itemModels
setupConfig:(void(^)(MTGridSelectConfig *config))setupConfigBlock
didSetupItemContentView:(MTGridDidSetupItemContentViewBlock)didSetupItemContentViewBlock
itemStateChanged:(MTGridItemStateChangedBlock)itemStateChangedBlock
selectValueChanged:(void(^)(NSArray *selectedModels))selectValueChangedBlock
{
MTGridSelectView *grideSeletView = [[self alloc] init];
grideSeletView.seletedIndexSet = [[NSMutableIndexSet alloc] init];
grideSeletView.originalModels = itemModels;
NSMutableArray *itemModelsM = [NSMutableArray array];
for (id model in itemModels) {
MTGridSelectModel *itemModel = [[MTGridSelectModel alloc] init];
itemModel.state = MTGridItemStateNormal;
itemModel.model = model;
[itemModelsM addObject:itemModel];
}
grideSeletView.itemModels = [itemModelsM copy];
grideSeletView.setupConfigBlock = setupConfigBlock;
grideSeletView.didSetupItemContentViewBlock = didSetupItemContentViewBlock;
grideSeletView.itemStateChangedBlock = itemStateChangedBlock;
grideSeletView.selectValueChangedBlock = selectValueChangedBlock;
grideSeletView.clipsToBounds = NO;
[grideSeletView createAndLayoutItemContentViews];
return grideSeletView;
}
- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
_collectionView.frame = self.bounds;
}
- (NSArray<id> *)selectedItems
{
return [self.originalModels objectsAtIndexes:self.seletedIndexSet];
}
- (NSInteger)itemTotalCount
{
return self.originalModels.count;
}
- (void)reloadDataWithItemModels:(NSArray *)itemModels
{
NSMutableArray *itemModelsM = [NSMutableArray array];
for (id model in itemModels) {
MTGridSelectModel *itemModel = [[MTGridSelectModel alloc] init];
itemModel.state = MTGridItemStateNormal;
itemModel.model = model;
[itemModelsM addObject:itemModel];
}
self.originalModels = itemModels;
self.itemModels = [itemModelsM copy];
[self.collectionView reloadData];
}
/// collectionViewCell
- (void)changeItemViewStateAtIndex:(NSInteger)index
{
MTGridSelectModel *itemModel = self.itemModels[index];
MTGridItemState newState = MTGridItemStateNormal;
if (self.config.multiple) { //
if (itemModel.state == MTGridItemStateNormal) {
//
if (self.selectedItems.count >= self.config.maxSelecteCount) {
if (self.limitBlock) {
self.limitBlock();
}
return;
}
newState = MTGridItemStateSelected;
} else if (itemModel.state == MTGridItemStateSelected) {
newState = MTGridItemStateNormal;
}
} else { //
self.previousSelectItemModel.state = MTGridItemStateNormal;
NSInteger previousIndex = [self.itemModels indexOfObject:self.previousSelectItemModel];
[self.seletedIndexSet removeIndex:previousIndex];
if (self.previousSelectItemModel) {
self.itemStateChangedBlock(self.previousSelectItemModel.itemView, self.previousSelectItemModel.model, self.previousSelectItemModel.state, YES);
}
newState = MTGridItemStateSelected;
self.previousSelectItemModel = itemModel;
}
[self changeItemStateAtIndexs:@[@(index)] state:newState changeByInner:YES];
}
///
- (void)selectItemAtIndex:(NSInteger)index
{
[self selectItemAtIndexs:@[@(index)]];
}
///
- (void)selectItemAtIndexs:(NSArray <NSNumber *>*)indexs
{
[self changeItemStateAtIndexs:indexs state:MTGridItemStateSelected changeByInner:NO];
}
///
- (void)selectAllItem
{
[self changeAllItemViewState:MTGridItemStateSelected];
}
///
- (void)deselectAllItem
{
[self changeAllItemViewState:MTGridItemStateNormal];
}
///
- (void)changeItemStateAtIndex:(NSInteger)index state:(MTGridItemState)state
{
[self changeItemStateAtIndexs:@[@(index)] state:state changeByInner:NO];
}
///
- (void)changeItemStateAtIndexs:(NSArray <NSNumber *>*)indexs state:(MTGridItemState)state changeByInner:(BOOL)changeByInner
{
BOOL isChanged = NO;
for (NSNumber *indexNumber in indexs) {
MTGridSelectModel *itemModel = self.itemModels[[indexNumber integerValue]];
if (itemModel.state != state) {
itemModel.state = state;
if (MTGridItemStateSelected == state) {
[self.seletedIndexSet addIndex:indexNumber.integerValue];
} else {
[self.seletedIndexSet removeIndex:indexNumber.integerValue];
}
if (self.itemStateChangedBlock) {
self.itemStateChangedBlock(itemModel.itemView, itemModel.model, itemModel.state, changeByInner);
}
isChanged = YES;
}
if (!self.config.multiple) { //
self.previousSelectItemModel = itemModel;
}
}
if (self.selectValueChangedBlock && isChanged) {
self.selectValueChangedBlock([self.originalModels objectsAtIndexes:self.seletedIndexSet]);
}
}
- (void)changeAllItemViewState:(MTGridItemState)state
{
NSMutableArray * array = [NSMutableArray array];
[self.itemModels enumerateObjectsUsingBlock:^(MTGridSelectModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[array addObject:@(idx)];
}];
[self changeItemStateAtIndexs:array state:state changeByInner:NO];
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect frame = self.frame;
frame.size = self.collectionView.frame.size;
self.frame = frame;
}
- (void)createAndLayoutItemContentViews
{
MTGridSelectConfig *config = self.config;
if (self.setupConfigBlock) {
self.setupConfigBlock(config);
}
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.minimumLineSpacing = config.rowSpacing;
flowLayout.minimumInteritemSpacing = config.columnSpacing;
CGSize itemSize = config.itemSize;
if (CGSizeEqualToSize(itemSize, CGSizeZero)) {
itemSize.width = (config.contentWidth - config.contentInset.left - config.contentInset.right - config.columnSpacing * (config.maxColumn - 1)) / config.maxColumn;
itemSize.height = config.itemHeight > 0 ? config.itemHeight : itemSize.width * config.itemRatio;
}
flowLayout.itemSize = itemSize;
CGFloat contentHeight = config.contentInset.top + config.contentInset.bottom + (itemSize.height + config.rowSpacing) * (self.itemModels.count / config.maxColumn + 1) - config.rowSpacing;
CGFloat contentWidth = config.contentInset.left + config.contentInset.right + (itemSize.width + config.columnSpacing) * config.maxColumn - config.columnSpacing;
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, config.contentWidth, contentHeight) collectionViewLayout:flowLayout];
[self layoutSubviews];
self.collectionView.showsVerticalScrollIndicator = YES;
self.collectionView.showsHorizontalScrollIndicator = YES;
self.collectionView.contentSize = CGSizeMake(contentWidth, contentHeight);
self.collectionView.backgroundColor = [UIColor clearColor];
self.collectionView.contentInset = config.contentInset;
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:kItemContentViewCellReuseIdentifier];
[self addSubview:self.collectionView];
[self.collectionView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
//
[self selectItemAtIndexs:self.config.defaultSelectIndexs];
});
}
#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[collectionView deselectItemAtIndexPath:indexPath animated:NO];
[self changeItemViewStateAtIndex:indexPath.item];
}
#pragma mark - UICollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.itemModels.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *itemContentViewCell = [collectionView dequeueReusableCellWithReuseIdentifier:kItemContentViewCellReuseIdentifier forIndexPath:indexPath];
MTGridSelectModel *itemModel = self.itemModels[indexPath.item];
if (self.didSetupItemContentViewBlock) {
[itemContentViewCell.contentView removeSubviews];
UIView *itemView = self.didSetupItemContentViewBlock(itemContentViewCell.contentView, itemModel.model);
itemModel.itemView = itemView;
//
itemView.userInteractionEnabled = NO;
[itemContentViewCell.contentView addSubview:itemView];
}
return itemContentViewCell;
}
@end