我有8个自定义单元格的tableview。在第8个单元格中,我添加了一个启用了分页的scrollView,这样我就可以显示第1页和第2页(或3,4 ... 10)而不会有非常高的单元格。
问题在于scrollView我不能使用didSelectRowAtIndexPath,因为单元格在scrollView后面,所以我试图检测scrollView点击(不刷卡)。
我玩touchesBegan和touchesEnded,但他们从未被调用过(我知道触摸仅适用于UIView,但也许.....)
非常感谢任何帮助。
谢谢, 最大
答案 0 :(得分:77)
Apple建议在这种情况下使用技巧,在他们的WWDC 2014 session"高级滚动视图" (参见从8:10开始的演示):
[cell.contentView addSubview:_scrollView];
[_scrollView setUserInteractionEnabled:NO];
[cell.contentView addGestureRecognizer:_scrollView.panGestureRecognizer];
所有需要做的事情,无需覆盖touchesBegan:
,touchesMoved:
和其他人。
我之前使用基于覆盖touchesBegan:
,touchesMoved:
,touchesEnded:
和touchesCancelled:
的解决方案,但有时它会导致一种奇怪的行为:当选择某个单元格时,方法{/ 1}}被调用了具有不同indexPath的单元格。
Apple的解决方案到目前为止没有任何副作用,看起来更优雅。
答案 1 :(得分:14)
还有一个优雅的解决方案:
从UIScrollView创建一个SubClass并覆盖以下方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self superview]touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self superview]touchesMoved:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self superview]touchesCancelled:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self superview]touchesEnded:touches withEvent:event];
}
将每次触摸传递到滚动视图的超级视图,然后调用didSelectRowAtIndexPath。
答案 2 :(得分:5)
解决了子类化uitableviewcell和uiscrollview的问题。
它符合我的需要。希望它可以提供帮助。
最高
myScrollView.h
#import <UIKit/UIKit.h>
@interface myScrollView : UIScrollView {
}
@end
myScrollView.m
#import "myScrollView.h"
@implementation myScrollView
- (id)initWithFrame:(CGRect)frame {
return [super initWithFrame:frame];
}
- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event
{
NSLog(@"touch scroll");
// If not dragging, send event to next responder
if (!self.dragging)
[self.nextResponder touchesEnded: touches withEvent:event];
else
[super touchesEnded: touches withEvent: event];
}
myCell.h
#import <UIKit/UIKit.h>
@interface myCell : UITableViewCell {
}
@end
myCell.m
#import "myCell.h"
@implementation myCell
- (id)initWithFrame:(CGRect)frame {
return [super initWithFrame:frame];
}
- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event
{
NSLog(@"touch cell");
// If not dragging, send event to next responder
[super touchesEnded: touches withEvent: event];
}
RootViewController.h
#import <UIKit/UIKit.h>
@class myCell;
@class myScrollView;
@interface RootViewController : UITableViewController {
myCell *cell;
myScrollView *scrollView;
}
@end
RootViewController.m
#pragma mark -
#pragma mark Table view data source
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
// my custom cell
cell = [[myCell alloc] init];
if (cell == nil) {
cell = [[[myCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// the custom scroll view
scrollView = [[myScrollView alloc] initWithFrame:cell.frame];
scrollView.contentSize = CGSizeMake(640, 40);
[cell.contentView addSubview:scrollView];
//something to add in scrollView
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 20)];
label.text = @"some text";
[scrollView addSubview:label];
// Configure the cell.
return cell;
}
答案 3 :(得分:4)
所选答案是正确的,但我根据我遇到的错误更新了代码。
在子类滚动视图中添加以下代码。
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (self.dragging) {
[super touchesMoved:touches withEvent:event];
} else {
if ([self.delegate isKindOfClass:[UITableViewCell class]]) {
[(UITableViewCell *)self.delegate touchesCancelled:touches withEvent:event];
}
[self.superview touchesMoved:touches withEvent:event];
}
}
如果您的self.delegate
不是UITableViewCell
,请将该属性替换为您的单元格。
单元需要在移动期间检索取消触摸事件以防止不期望的结果。它可以很容易地重现如下。
didSelectCell
州另一点需要提及的是订单很重要!如果在self.delegate
之前未调用self.superview
,则突出显示的状态不会发生。
答案 4 :(得分:0)
我找到了满足我需求的最简单的解决方案:
子类UIScrollView touchesEnded方法并发布通知。
在UITableview中,在viewdidAppear中添加一个观察者(在viewdiddisappear中删除它)以调用一个调用tableview didSelectRowForIndexPath的函数。
像这样的东西(快速版)
// myScrollView.swift
import UIKit
class myScrollView: UIScrollView {
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
NSNotificationCenter.defaultCenter().postNotificationName("selectTVRow", object: nil)
}
}
在你的tableView中:
// ItemsList.swift
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "selectFourthRow", name: "selectTVRow", object: nil)
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self, name: "selectfourthrow", object: nil)
}
func selectFourthRow() {
let rowToSelect:NSIndexPath = NSIndexPath(forRow: 4, inSection: 0);
self.tableView(self.tableView, didSelectRowAtIndexPath: rowToSelect);
}
/*
.... rest of your tableview Datasource and Delegate methods...
numberOfSectionsInTableView, numberOfRowsInSection, cellForRowAtIndexPath
*/