gpt4 book ai didi

ios - Collection View 中单元格中的 UIButton 未接收到内部事件

转载 作者:IT王子 更新时间:2023-10-29 08:02:42 26 4
gpt4 key购买 nike

下面的代码表达了我的问题:(它是独立的,因为您可以使用空模板创建一个 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]));
}
}

基本上,我正在使用 Collection View 创建一个 Springboard 类型的 UI。我的 UICollectionViewCell 子类 (Cell) 有一个按钮,它部分位于单元格的 contentView(即它的父 View )边界之外。

问题是单击 contentView 边界之外的按钮的任何部分(基本上是按钮的 3/4)不会调用按钮操作。仅当单击与 contentView 重叠的按钮部分时,才会调用按钮的操作方法。

我什至覆盖了 Cell 中的 -pointInside:withEvent: 方法,这样按钮中的触摸就会被确认。但这对解决按钮点击问题没有帮助。

我猜这可能与 collectionView 处理触摸的方式有关,但我不知道是什么。我知道 UICollectionView 是一个 UIScrollView 子类,我实际上已经在 View 上测试了重写 -pointInside:withEvent:(将 subview 设为 ScrollView )包含一个部分重叠的按钮解决了按钮点击问题,但它在这里不起作用。

有什么帮助吗?

** 添加:作为记录,我目前解决该问题的方法是将一个较小的 subview 插入到 contentView 中,这为单元格提供了外观。删除按钮被添加到 contentView,这样它的矩形实际上位于 contentView 的边界内,但仅部分重叠单元格的可见部分(即插入 subview )。所以我得到了我想要的效果,并且按钮工作正常。但我仍然对上面的原始实现的问题感到好奇。

最佳答案

问题似乎出在 hitTest/pointInside 上。我猜如果触摸位于单元格外部的按钮部分,则单元格从 pointInside 返回 NO,因此按钮没有经过 HitTest 。要解决此问题,您必须重写 UICollectionViewCell 子类上的 pointInside 以考虑按钮。如果触摸在按钮内部,您还需要覆盖 hitTest 以返回按钮。以下是假设您的按钮位于 UICollectionViewCell 子类中名为 deleteButton 的属性中的示例实现。

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [self.deleteButton hitTest:[self.deleteButton convertPoint:point fromView:self] withEvent:event];
if (view == nil) {
view = [super hitTest:point withEvent:event];
}
return view;
}

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
if ([super pointInside:point withEvent:event]) {
return YES;
}
//Check to see if it is within the delete button
return !self.deleteButton.hidden && [self.deleteButton pointInside:[self.deleteButton convertPoint:point fromView:self] withEvent:event];
}

请注意,因为 hitTest 和 pointInside 期望点位于接收器的坐标空间中,所以您必须记住在对按钮调用这些方法之前转换点。

关于ios - Collection View 中单元格中的 UIButton 未接收到内部事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13218208/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com