Aky*_*Aky 23 uiresponder ios uicollectionview
下面的代码表达了我的问题:(它是自包含的,你可以创建一个带有空模板的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]));
}
}
Run Code Online (Sandbox Code Playgroud)
基本上我正在使用集合视图创建一个Springboard类型的UI.我的UICollectionViewCell子类(Cell)有一个按钮,它位于单元格的contentView(即其superview的)边界之外.
问题是单击contentView边界之外的按钮的任何部分(基本上是按钮的3/4)不会调用按钮操作.仅当单击与contentView重叠的按钮部分时,才会调用按钮的操作方法.
我甚至-pointInside:withEvent:在Cell中重写了方法,以便确认按钮中的触摸.但这对按钮点击问题没有帮助.
我猜它可能与collectionView如何处理触摸有关,但我不知道是什么.我知道UICollectionView是一个UIScrollView子类,我实际上已经测试了覆盖-pointInside:withEvent:视图(包含一个滚动视图的子视图),包含一个部分重叠的按钮解决了按钮点击问题,但它在这里没有用.
有帮助吗?
**补充:为了记录,我目前解决问题的方法是将一个较小的子视图嵌入到contentView中,从而为该单元提供外观.删除按钮被添加到contentView,使其rect实际上位于contentView的边界内,但仅部分重叠单元格的可见部分(即插入子视图).所以我得到了我想要的效果,按钮工作正常.但我仍然对上面原始实现的问题感到好奇.
hon*_*nus 25
问题似乎是hitTest/pointInside.我猜测单元格是从pointInside返回NO,如果触摸位于单元格外部的按钮部分,因此按钮不会受到测试.要解决此问题,您必须覆盖UICollectionViewCell子类上的pointInside以将该按钮考虑在内.如果触摸在按钮内,您还需要覆盖hitTest以返回按钮.下面是示例实现,假设您的按钮位于名为deleteButton的UICollectionViewCell子类中的属性中.
-(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];
}
Run Code Online (Sandbox Code Playgroud)
请注意,因为hitTest和pointInside期望该点位于接收器的坐标空间中,所以您必须记住在按钮上调用这些方法之前转换该点.
jer*_*gdm 13
在Interface Builder中,您是否将对象设置为UICollectionViewCell?因为错误的一次我设置了一个UIView并在为它分配了正确的UICollectionViewCell类之后......但是这些东西(按钮,标签,ecc.)没有被添加到contentView中,因此它们不会像它们那样响应......
所以,在IB中提醒在绘制界面时采用UICollectionViewCell对象:)
Swift版本:
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
//From higher z- order to lower except base view;
for (var i = subviews.count-2; i >= 0 ; i--){
let newPoint = subviews[i].convertPoint(point, fromView: self)
let view = subviews[i].hitTest(newPoint, withEvent: event)
if view != nil{
return view
}
}
return super.hitTest(point, withEvent: event)
}
Run Code Online (Sandbox Code Playgroud)
这就是...对于所有子视图
我成功接收对子类 UICollectionViewCell.m 文件中创建的按钮的触摸;
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
// Create button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 100, 100); // position in the parent view and set the size of the button
[button setTitle:@"Title" forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"animage.png"] forState:UIControlStateNormal];
[button addTarget:self action:@selector(button:) forControlEvents:UIControlEventTouchUpInside];
// add to contentView
[self.contentView addSubview:button];
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
在意识到 Storyboard 中添加的按钮不起作用后,我在代码中添加了该按钮,不确定这是否在最新的 Xcode 中得到修复。
希望有帮助。
| 归档时间: |
|
| 查看次数: |
22568 次 |
| 最近记录: |