Следующий код выражает мою проблему: (Это самодостаточно, поскольку вы можете создать проект Xcode с пустым шаблоном, заменить содержимое файла main.m, удалить файлы AppDelegate.h/.m и построить его)
//
// main.m
// CollectionViewProblem
//
#import <UIKit/UIKit.h>
@interface Cell : UICollectionViewCell
@property (nonatomic, strong) UIButton *button;
@property (nonatomic, strong) UILabel *label;
@end
@implementation Cell
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
self.label = [[UILabel alloc] initWithFrame:self.bounds];
self.label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.label.backgroundColor = [UIColor greenColor];
self.label.textAlignment = NSTextAlignmentCenter;
self.button = [UIButton buttonWithType:UIButtonTypeInfoLight];
self.button.frame = CGRectMake(-frame.size.width/4, -frame.size.width/4, frame.size.width/2, frame.size.width/2);
self.button.backgroundColor = [UIColor redColor];
[self.button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:self.label];
[self.contentView addSubview:self.button];
}
return self;
}
// Overriding this because the button rect is partially outside the parent-view bounds:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if ([super pointInside:point withEvent:event])
{
NSLog(@"inside cell");
return YES;
}
if ([self.button
pointInside:[self convertPoint:point
toView:self.button] withEvent:nil])
{
NSLog(@"inside button");
return YES;
}
return NO;
}
- (void)buttonClicked:(UIButton *)sender
{
NSLog(@"button clicked!");
}
@end
@interface ViewController : UICollectionViewController
@end
@implementation ViewController
// (1a) viewdidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:@"ID"];
}
// collection view data source methods ////////////////////////////////////
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 100;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
Cell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ID" forIndexPath:indexPath];
cell.label.text = [NSString stringWithFormat:@"%d", indexPath.row];
return cell;
}
///////////////////////////////////////////////////////////////////////////
// collection view delegate methods ////////////////////////////////////////
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"cell #%d was selected", indexPath.row);
}
////////////////////////////////////////////////////////////////////////////
@end
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
ViewController *vc = [[ViewController alloc] initWithCollectionViewLayout:layout];
layout.itemSize = CGSizeMake(128, 128);
layout.minimumInteritemSpacing = 64;
layout.minimumLineSpacing = 64;
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.sectionInset = UIEdgeInsetsMake(32, 32, 32, 32);
self.window.rootViewController = vc;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
@end
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
В основном я создаю пользовательский интерфейс типа Springboard с использованием представлений коллекции. Мой подкласс UICollectionViewCell (Ячейка) имеет кнопку, которая частично находится за пределами содержимого содержимого cellView (т.е. Его супервизора).
Проблема заключается в том, что нажатие любой части кнопки за пределами границ contentView (в основном 3/4 кнопки) не вызывает действие кнопки. Только при нажатии на часть кнопки, которая перекрывает ContentView, вызывается метод действия кнопки.
Я даже переопределил метод -pointInside:withEvent:
в Ячейке, так что прикосновения к кнопке будут подтверждены. Но это не помогло с проблемой нажатия кнопки.
Я предполагаю, что это может быть связано с тем, как collectionView обрабатывает касания, но я не знаю, что. Я знаю, что UICollectionView - это подкласс UIScrollView, и я действительно протестировал это переопределение -pointInside:withEvent:
в представлении (сделанное subview в виде прокрутки), содержащее частично перекрывающуюся кнопку, проблема с нажатием кнопки, но она не работает здесь.
Любая помощь?
** Добавлено: Для записи мое текущее решение проблемы включает в себя вложение меньшего subview в contentView, который дает ячейке ее внешний вид. Кнопка delete добавляется в contentView таким образом, что ее прямой фактически лежит в пределах contentView, но только частично перекрывает видимую часть ячейки (т.е. Вложенное представление). Итак, у меня есть эффект, который я хотел, и кнопка работает правильно. Но мне все еще интересно узнать о проблеме с первоначальной реализацией выше.