最近做項目接觸了一些需要實現多選的功能,但總結起來方法類似;實現此功能的方法有很多,接下來介紹一種方法,利用UICollectionView實現。
我們都知道,UICollectionView可以被認為更高級的UITableView,因此UITableView里面可以實現的在UICollectionView都可以實現,尤其針對類似瀑布流那樣的界面,UICollectionView功能更強大,更方便。
本文沒有介紹UICollectionView的Cell定制,代理的設置,數據模型,userView的封裝等,如有興趣可參照下面我做的簡易Demo。
對于多選功能,顯然我們會用到UICollectionView的兩個方法:
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath; // called when the user taps on an already-selected item in multi-select mode
同時用戶可能會多次選擇、取消操作,也就是說我們允許多次點擊(multiple touch),為了更好處理這樣操作,UICollectionView提供方法:
- (void)performBatchUpdates:(void (^ __nullable)(void))updates completion:(void (^ __nullable)(BOOL finished))completion; // allows multiple insert/delete/reload/move calls to be animated simultaneously. Nestable.
注意:在建立UICollectionView時,它的allowsMultipleSelection屬性一定設置成YES。
在Demo中創建了一個Button,點擊全選,按鈕title改變,再次點擊全部取消,此時需要對UICollectionView中的indexPath.item進行遍歷,則創建了一個NSMutableIndexSet來增加和刪除:
@property (nonatomic, strong) NSMutableIndexSet* selectedIndexSet;
當前沒有選擇時,我們會把它加入進去;選擇后再次選擇,會刪除它。部分代碼如下:
if ([self collectionView:self.contactsPickerView shouldSelectItemAtIndexPath:indexPath]) {
[self.contactsPickerView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
[self.selectedIndexSet addIndex:indexPath.item];
}
if ([self collectionView:self.contactsPickerView shouldDeselectItemAtIndexPath:indexPath]) {
[self.contactsPickerView deselectItemAtIndexPath:indexPath animated:YES];
[self.selectedIndexSet removeIndex:indexPath.item];
}
到此為止,讀者也許已經想到,針對全選和全不選,只要遍歷即可,下面為本人用的方法:
全選:for (NSUInteger index = 0; index < count; ++index) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
if ([self collectionView:self.contactsPickerView shouldSelectItemAtIndexPath:indexPath]) {
[self.contactsPickerView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
[self.selectedIndexSet addIndex:indexPath.item];
}
}
全不選:[self.selectedIndexSet enumerateIndexesUsingBlock:^(NSUInteger index, BOOL * _Nonnull stop) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
if ([self collectionView:self.contactsPickerView shouldDeselectItemAtIndexPath:indexPath]) {
[self.contactsPickerView deselectItemAtIndexPath:indexPath animated:YES];
[self.selectedIndexSet removeIndex:indexPath.item];
}
}];
按鈕標題也要隨之改變,因此綜上所述按鈕的實現方法為:
- (IBAction)handleToggleSelectionBtn:(id)sender {
NSUInteger count = [self.contacts count];
BOOL allEnabledContactsSelected = [self allEnabledContactsSelected];
if (!allEnabledContactsSelected) {
[self.contactsPickerView performBatchUpdates:^{
for (NSUInteger index = 0; index < count; ++index) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
if ([self collectionView:self.contactsPickerView shouldSelectItemAtIndexPath:indexPath]) {
[self.contactsPickerView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
[self.selectedIndexSet addIndex:indexPath.item];
}}} completion:^(BOOL finished) {
[self updateToggleSelectionButton];
}];} else {
[self.contactsPickerView performBatchUpdates:^{
[self.selectedIndexSet enumerateIndexesUsingBlock:^(NSUInteger index, BOOL * _Nonnull stop) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
if ([self collectionView:self.contactsPickerView shouldDeselectItemAtIndexPath:indexPath]) {
[self.contactsPickerView deselectItemAtIndexPath:indexPath animated:YES];
[self.selectedIndexSet removeIndex:indexPath.item];
}}];} completion:^(BOOL finished) {
[self updateToggleSelectionButton];
}];}}
在此基本功能已經實現,但詳細具體細節本文沒有給出,只是給出一種思路;如果現在你的感覺是:
不要著急:請看Demo