如图,UITableView中嵌套UICollectionView后无法点击分享.
之前为了解决这个问题,已经放弃了方式(collectionView:didSelectItemAtIndexPath:),选择使用cell中响应按钮点击的方式.
现在适配iOS13发现,上面这种方式也已经无法响应点击,所以现在适配时选择了点击穿透的方式来处理.
例:
解决:
点击穿透
OC
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGPoint bluePoint = [self convertPoint:point toView:self.collectionView];
NSInteger index = -1;
// 这种方式在iphone 7plus会顺序错误
// NSArray *cellArr = self.collectionView.visibleCells;
// for (int i = 0 ; i < cellArr.count ; i ++) {
// WXYZ_ShareItemCell *curCell = [cellArr objectAtIndex:i];
// // 判断给定的点是否被一个CGRect包含,可以用CGRectContainsPoint函数
// BOOL contains = CGRectContainsPoint(curCell.frame, bluePoint);
// if (contains) {
// index = i;
// break;
// }
// }
NSArray<NSIndexPath *> *indexPathsForVisibleItems = self.collectionView.indexPathsForVisibleItems;
for (int i = 0 ; i < indexPathsForVisibleItems.count ; i ++) {
NSIndexPath *indexPath = indexPathsForVisibleItems[i];
WXYZ_ShareItemCell *curCell = (WXYZ_ShareItemCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
// 判断给定的点是否被一个CGRect包含,可以用CGRectContainsPoint函数
BOOL contains = CGRectContainsPoint(curCell.frame, bluePoint);
if (contains) {
index = indexPath.item;
break;
}
}
if ([self.collectionView pointInside:bluePoint withEvent:event]) {
if (index >= 0) {
[self selectCellWithItem:index];
}
return self.collectionView;
} else {
return [super hitTest:point withEvent:event];
}
}
- (void)selectCellWithItem:(NSInteger)index {
}
Swift
extension MineListCell {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let bluePoint: CGPoint = self.convert(point, to: self.collectionView)
var index = -1
let indexPathsForVisibleItems = self.collectionView.indexPathsForVisibleItems
for (ind,obj) in indexPathsForVisibleItems.enumerated() {
let indexPath = obj
if let curCell = self.collectionView.cellForItem(at: indexPath) {
let contains = curCell.frame.contains(bluePoint)
if contains {
index = indexPath.item
break
}
}
}
if self.collectionView.point(inside: bluePoint, with: event) {
if index >= 0 {
self.selectCellWithItem(index: index)
}
return self.collectionView
} else {
return super.hitTest(point, with: event)
}
}
func selectCellWithItem(index: Int) {
print(index)
}
}
经过实际使用体验, 发现上面点击穿透的方式解决得并不完美. 用这种方式, 你会发现,点击动作还未完,但操作就已经响应.
下面对点击穿透方式进行优化:
1.使用点击穿透记录当前点击的位置
class MineListCell: UICollectionViewCell {
// 使用点击穿透记录当前点击的位置
var curTapIndex: Int = -1
......
}
extension MineListCell {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let bluePoint: CGPoint = self.convert(point, to: self.collectionView)
var index = -1
let indexPathsForVisibleItems = self.collectionView.indexPathsForVisibleItems
for (ind,obj) in indexPathsForVisibleItems.enumerated() {
let indexPath = obj
if let curCell = self.collectionView.cellForItem(at: indexPath) {
let contains = curCell.frame.contains(bluePoint)
if contains {
index = indexPath.item
break
}
}
}
curTapIndex = index
if self.collectionView.point(inside: bluePoint, with: event) {
return super.hitTest(point, with: event)
} else {
return super.hitTest(point, with: event)
}
}
}
2.在第一层UITableView或UICollectionView代理方法中接受到回调后进行相应的处理
extension MineVC: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
......
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell: MineListCell = collectionView.cellForItem(at: indexPath) as! MineListCell
if let items = cell.items, cell.curTapIndex >= 0, items.count > cell.curTapIndex {
let obj: MineItemModel = items[cell.curTapIndex]
if let route = obj.route {
if let topVC = ScreenUIManager.topViewController() {
PushWithRoute(vc: topVC, route: route)
}
}
}
}
}