次のコードは私の問題を表しています:(空のテンプレートで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's rect is partially outside the parent-view's 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]));
}
}
基本的に、コレクション ビューを使用してスプリングボード タイプの UI を作成しています。私のUICollectionViewCellサブクラス ( Cell ) には、部分的にセルのcontentView (つまり、そのスーパービュー) の境界外にあるボタンがあります。
問題は、ボタンのcontentView境界外 (基本的にはボタンの 3/4) の任意の部分をクリックしても、ボタン アクションが呼び出されないことです。contentViewと重なるボタンの部分をクリックした場合にのみ、ボタンのアクション メソッドが呼び出されます。
ボタンのタッチが認識されるように、 Cell-pointInside:withEvent:
のメソッドもオーバーライドしました。しかし、それはボタンクリックの問題には役立たなかった。
collectionViewがタッチを処理する方法と関係があるのではないかと推測していますが、何がわかりません。UICollectionViewがUIScrollViewのサブクラスであることはわかっており、部分的に重なっているボタンを含むビュー (サブビューをスクロール ビューにする) をオーバーライド-pointInside:withEvent:
するとボタン クリックの問題が解決されることを実際にテストしましたが、ここでは機能しませんでした。
何か助けはありますか?
** 追加: 記録として、問題に対する私の現在の解決策は、セルに外観を与えるcontentViewに小さなサブビューを挿入することです。削除ボタンはcontentViewに追加され、その rect は実際には contentView の境界内にありますが、セルの表示部分 (つまり、挿入サブビュー) と部分的にしか重なりません。それで、私が望んでいた効果が得られ、ボタンは適切に機能しています. しかし、上記の元の実装の問題についてはまだ興味があります。