在UITableView内嵌套UICollectionView,实现联动效果
重写gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:方法
@implementation MyTableView
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]];;
}
@end
监听UICollectionView的滚动
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(imageSelectViewScrolled:) name:@"image_picker_notice" object:nil];
在imageSelectViewScrolled内控制UICollectionView的滚动效果
- (void)imageSelectViewScrolled: (NSNotification *)notification{
self.childVCScrollView = notification.object;
NSLog(@"%lf", kTopHeight);
if ((long long)self.tableView.contentOffset.y < (long long)kTopHeight) {
self.childVCScrollView.contentOffset = CGPointZero;
self.childVCScrollView.showsVerticalScrollIndicator = NO;
} else {
self.childVCScrollView.showsVerticalScrollIndicator = YES;
}
}
在UICollectionView的代理函数scrollViewDidScroll内发送通知
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSLog(@"%@", [scrollView class]);
[[NSNotificationCenter defaultCenter] postNotificationName:@"image_picker_notice" object:scrollView];
}
在tableView的代理函数scrollViewDidScroll控制tableView的滚动效果
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
// NSLog(@"%@", [scrollView class]);
if (self.tableView == scrollView) {
if ((self.childVCScrollView && self.childVCScrollView.contentOffset.y > 0) || (scrollView.contentOffset.y > kTopHeight)) {
//限制self.tableView的滚动
self.tableView.contentOffset = CGPointMake(0, kTopHeight);
}
}
}
最后,滚动效果出现瑕疵,当UICollectionView滚动到底部时,第一次会出现弹簧效果,之后就不会发生滚动效果,只有UITableView的scrollViewDidScroll有效应。
解决方案如下:
1、创建一个UIScrollView,将UIScrollView放在UITableView的cell上
2、将UICollectionView放在UIScrollView上
#import "ImagePickerViewController.h"
#import "ImageSelectViewController.h"
#define kTopHeight (CGRectGetHeight(self.preView.bounds) * 7 / 16)
@interface MyTableView : UITableView
@end
@implementation MyTableView
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]];;
}
@end
@interface ImagePickerViewController ()
@property (nonatomic, strong) MyTableView *tableView;
@property (nonatomic, strong) UIImageView *preView;
@property (nonatomic, strong) UIScrollView * _Nullable childVCScrollView;
@property (nonatomic, strong) UIView * _Nullable selectImageView;
@property (nonatomic, strong) UIScrollView *scrollView;
@end
@implementation ImagePickerViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setupViews];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(imageSelectViewScrolled:) name:@"image_picker_notice" object:nil];
}
#pragma mark - Setup UI
- (void)setupViews{
self.view.backgroundColor = UIColor.whiteColor;
[self.view addSubview:self.tableView];
self.tableView.frame = self.view.bounds;
self.preView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetWidth(self.view.bounds));
self.tableView.tableHeaderView = self.preView;
}
#pragma mark - Methods
- (void)imageSelectViewScrolled: (NSNotification *)notification{
self.childVCScrollView = notification.object;
NSLog(@"%lf", kTopHeight);
if ((long long)self.tableView.contentOffset.y < (long long)kTopHeight) {
self.childVCScrollView.contentOffset = CGPointZero;
self.childVCScrollView.showsVerticalScrollIndicator = NO;
} else {
self.childVCScrollView.showsVerticalScrollIndicator = YES;
}
}
#pragma mark - Getter
- (MyTableView *)tableView{
if (!_tableView) {
_tableView = [[MyTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.showsVerticalScrollIndicator = NO;
}
return _tableView;
}
- (UIImageView *)preView{
if (!_preView) {
_preView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@""]];
_preView.backgroundColor = UIColor.cyanColor;
}
return _preView;
}
- (UIView *)selectImageView{
if (!_selectImageView) {
ImageSelectViewController *selectVC = [[ImageSelectViewController alloc] init];
[self addChildViewController:selectVC];
_selectImageView = selectVC.view;
}
return _selectImageView;
}
- (UIScrollView *)scrollView{
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] init];
_scrollView.delegate = self;
_scrollView.pagingEnabled = YES;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.showsHorizontalScrollIndicator = NO;
}
return _scrollView;
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
// NSLog(@"%@", [scrollView class]);
if (self.tableView == scrollView) {
if ((self.childVCScrollView && self.childVCScrollView.contentOffset.y > 0) || (scrollView.contentOffset.y > kTopHeight)) {
//限制self.tableView的滚动
self.tableView.contentOffset = CGPointMake(0, kTopHeight);
}
}
}
#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return CGRectGetHeight(tableView.frame) - kTopHeight - 44;
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"identifier"];
}
[cell.contentView addSubview:self.scrollView];
self.scrollView.frame = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), CGRectGetHeight(tableView.bounds) - kTopHeight - 44);
[self.scrollView addSubview:self.selectImageView];
self.selectImageView.frame = self.scrollView.bounds;
return cell;
}
#import "ImageSelectViewController.h"
#import
@interface MyCollectionView : UICollectionView
@end
@implementation MyCollectionView
@end
@interface ImageSelectViewController ()
@property (nonatomic, strong) MyCollectionView *collectionView;
@property (nonatomic, strong) NSMutableArray *dataArray;
@end
@implementation ImageSelectViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setupViews];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pageTitleViewToTop) name:@"headerViewToTop" object:nil];
}
- (void)viewWillLayoutSubviews{
self.collectionView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds));
}
#pragma mark - Setup UI
- (void)setupViews{
self.view.backgroundColor = UIColor.whiteColor;
[self.view addSubview:self.collectionView];
}
#pragma mark - Methods
- (void)pageTitleViewToTop{
}
/// 获取相册中的视频和图片
- (void)startFetchTheImage {
if (![[TZImageManager manager] authorizationStatusAuthorized]) {
NSLog(@"未授访问相册的权利");
}
[self didGetAuth];
}
/// 获取到权限
- (void)didGetAuth {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[TZImagePickerConfig sharedInstance].allowPickingImage = YES;
[TZImagePickerConfig sharedInstance].allowPickingVideo = YES;
[TZImageManager manager].sortAscendingByModificationDate = NO;
[[TZImageManager manager] getCameraRollAlbum:YES allowPickingImage:YES needFetchAssets:YES completion:^(TZAlbumModel *model) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.dataArray removeAllObjects];
// 拍摄按钮 占位的model
[self.dataArray addObject:[[TZAssetModel alloc] init]];
for (TZAssetModel * assetModel in model.models) {
if ((assetModel.type == TZAssetModelMediaTypeVideo && assetModel.asset.duration <= 61) || assetModel.type == TZAssetModelMediaTypePhoto) {
[self.dataArray addObject:assetModel];
}
}
// 第一次加载
[self.collectionView reloadData];
});
}];
});
}
#pragma mark - Getter
- (MyCollectionView *)collectionView{
if (!_collectionView) {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
_collectionView = [[MyCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_collectionView.delegate = self;
_collectionView.dataSource = self;
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:NSStringFromClass([UICollectionViewCell class])];
}
return _collectionView;
}
- (NSMutableArray *)dataArray{
if (!_dataArray) {
_dataArray = [NSMutableArray array];
}
return _dataArray;
}
#pragma mark - UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
CGFloat width = CGRectGetWidth(self.view.frame);
CGFloat itemWidth = (width - 3 * 5) * 1.0 / 4;
return CGSizeMake(itemWidth, itemWidth);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{
return 5;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
return 5;
}
#pragma mark - UICollectionViewDelegate、UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 30;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([UICollectionViewCell class]) forIndexPath:indexPath];
cell.contentView.backgroundColor = UIColor.lightGrayColor;
return cell;;
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSLog(@"%@", [scrollView class]);
[[NSNotificationCenter defaultCenter] postNotificationName:@"image_picker_notice" object:scrollView];
}
@end