这是设置:我在表格单元格中有UIControls,允许从右向左滑动以获取删除功能(如清除)
表格单元格位于UITableView内。
TableView位于另一个UIControl中,允许从左到右或从右到左滑动以更改天数。当发生这种情况时,新的TableView被创建到主要的一个右侧或左侧,并且新的一个从左或右拉入,直到满足阈值并且动画接管然后将旧的替换为新的。
在某些情况下,所有这些互动实际上都能正常运作。问题是,经过几次互动(表格幻灯片似乎有问题)后,滚动表格变得困难/不可能。
这是TableViewSlider的代码(包含TableViews的顶级UIControl)。任何想法将不胜感激!
@implementation OSETableViewSlider
- (void) initialize {
self.backgroundColor = [UIColor backgroundFlatColor];
self.mainTableView = [self createUITableView];
self.mainTableView.frame = CGRectMake(0,0, self.frame.size.width, self.frame.size.height);
self.mainTableView.hidden = NO;
[self addSubview:self.mainTableView];
self.transitionInProgress = NO;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self initialize];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self) {
[self initialize];
}
return self;
}
- (UITableView *)createUITableView {
UITableView *newTable = [[UITableView alloc] init];
newTable.hidden = YES;
newTable.separatorStyle = UITableViewCellSeparatorStyleNone;
newTable.scrollEnabled = YES;
newTable.bounces = YES;
newTable.dataSource = self;
newTable.delegate = self;
newTable.backgroundColor = [UIColor backgroundFlatColor];
return newTable;
}
- (void)setFrame:(CGRect)frame {
super.frame = frame;
self.mainTableView.frame = CGRectMake(0,0, frame.size.width, frame.size.height);
}
- (void)transitionToDate:(NSDate *)date fromRight:(BOOL)rightToLeft {
[self.viewController beginTransitionToDate:date];
self.transitionTableView = [self createUITableView];
self.transitionTableView.frame = CGRectMake( rightToLeft ? self.frame.size.width : (-1 * self.frame.size.width), 0,
self.frame.size.width, self.frame.size.height );
self.transitionTableView.hidden = NO;
[self addSubview:self.transitionTableView];
self.transitionInProgress = YES;
[UIView animateWithDuration:0.2f animations:^{
self.transitionTableView.frame = CGRectMake(0,0, self.frame.size.width, self.frame.size.height);
self.mainTableView.frame = CGRectMake( rightToLeft ? (-1 * self.frame.size.width) : self.frame.size.width, 0,
self.frame.size.width, self.frame.size.height);
} completion:^(BOOL completed){
[self.viewController endTransitionDidChange:YES];
[self.mainTableView removeFromSuperview];
self.mainTableView = self.transitionTableView;
self.transitionInProgress = NO;
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.viewController activityCountForTransition:(tableView!=self.mainTableView)];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self.viewController cellNumber:indexPath.item forTransition:(tableView!=self.mainTableView)];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self.viewController cellNumber:indexPath.item forTransition:(tableView!=self.mainTableView)].frame.size.height;
}
- (void)layoutSubviews {
if(!self.transitionInProgress) {
[self.mainTableView setFrame:CGRectMake(0,0, self.frame.size.width, self.frame.size.height)];
}
}
- (BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
NSLog(@"begin track");
self.locationInView = [touch locationInView:self.superview];
self.fingerTracking = YES;
self.fingerMoved = NO;
self.transitionTableView = nil;
return YES;
}
- (CGFloat) calcOffsetForTouch:(UITouch *)touch {
CGFloat fingerOffset = [touch locationInView:self.superview].x - self.locationInView.x;
return fingerOffset + self.startingOffset;
}
- (BOOL) continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
self.fingerMoved = YES;
CGFloat offset = [self calcOffsetForTouch:touch];
//NSLog(@"offset is: %f flarb: %f", offset, fabs(offset));
if(offset < 0 && (!self.transitioningLeft || [OSEUtils isNull:self.transitionTableView])) {
[self.viewController beginTransitionToDate:[OSEUtils daysOffset:1 fromDate:self.viewController.selectedDate withTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]]];
[self.transitionTableView removeFromSuperview];
self.transitionTableView = [self createUITableView];
self.transitioningLeft = YES;
NSLog(@"going left");
[self addSubview:self.transitionTableView];
[self.transitionTableView reloadData];
}
if(offset > 0 && (self.transitioningLeft || [OSEUtils isNull:self.transitionTableView])) {
[self.viewController beginTransitionToDate:[OSEUtils daysOffset:-1 fromDate:self.viewController.selectedDate withTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]]];
[self.transitionTableView removeFromSuperview];
self.transitionTableView = [self createUITableView];
self.transitioningLeft = NO;
NSLog(@"going right");
[self addSubview:self.transitionTableView];
[self.transitionTableView reloadData];
}
CGFloat mult = self.transitioningLeft ? 1 : -1;
if(fabs(offset) > (self.frame.size.width / 3.0f)) {
if(self.transitioningLeft) {
offset = -1 * self.frame.size.width;
} else {
offset = self.frame.size.width;
}
[UIView animateWithDuration:0.2f animations:^{
self.mainTableView.frame = CGRectMake(offset, 0, self.frame.size.width, self.frame.size.height);
self.transitionTableView.frame = CGRectMake(offset + (mult * self.frame.size.width), 0,
self.frame.size.width, self.frame.size.height);
} completion:^(BOOL finished) {
[self.mainTableView removeFromSuperview];
if(self.transitioningLeft) {
[self.viewController.daySelector jumpToNext];
} else {
[self.viewController.daySelector jumpToPrevious];
}
self.mainTableView = self.transitionTableView;
self.transitionTableView = nil;
[self.viewController endTransitionDidChange:YES];
}];
return NO;
}
self.mainTableView.frame = CGRectMake(offset, 0, self.frame.size.width, self.frame.size.height);
self.transitionTableView.frame = CGRectMake(offset + (mult * self.frame.size.width), 0, self.frame.size.width, self.frame.size.height);
self.transitionTableView.hidden = NO;
return YES;
}
- (void) endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
NSLog(@"end tableslide track");
[UIView animateWithDuration:0.2f animations:^{
self.mainTableView.frame = CGRectMake(0,0,self.frame.size.width, self.frame.size.height);
self.transitionTableView.frame = CGRectMake(((self.transitioningLeft ? 1 : -1 ) * self.frame.size.width), 0, self.frame.size.width, self.frame.size.height);
} completion:^(BOOL completion){
[self.transitionTableView removeFromSuperview];
self.transitionTableView = nil;
[self.viewController endTransitionDidChange:NO];
}];
self.fingerTracking = NO;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *tableHitTest = [self.mainTableView hitTest:point withEvent:event];
if([tableHitTest isKindOfClass:[OSECellPanelControl class]]) {
return tableHitTest;
} else {
return self;
}
}
@end
答案 0 :(得分:1)
当用户向左或向右滑动时,为什么要创建新的UITableView
?使用内置的deleteRowsAtIndexPath:
和insertRowsAtIndexPath:
方法为滑入和滑出的行设置动画效果会更加高效,而无需滑入和滑出整个UITableView
。
您可以在浏览日期时查看tableview内容更改动画,以便at this for a reference。
我不知道您当前的设置,但是当我尝试使用可滑动的UITableViewCell
这个完全相同的东西并且它的超级视图可以刷卡时,我遇到了获得我想要的交互的问题。如果这有助于解决您的问题,您可以查看检测用户滑动的位置。如果用户在UITableViewCell的左右边缘的特定偏移内滑动,则它会滑动单元格,该偏移之外的任何内容(单元格的中心)都会刷过UITableView本身。然后,您可以设置删除和插入新行的动画。
此外,通过每次重新实例化一个新的UITableView,您每次都强制重新实例化UITableViewCell。通过使用删除和插入方法,您可以通过dequeueReusableCellWithIdentifier
方法继续使用现有单元格。每次重新实例化UITableView时,您的单元格都将设置为nil并丢弃,需要新的tableview创建单元格的完整新实例。这是非常低效的。
答案 1 :(得分:1)
您正在深入了解触摸跟踪和点击检测。请使用更高级别的API - 手势识别器。使用手势,您可以设置优先级(在此之前必须先失败)。
因此,您需要在容器视图上进行几个自定义手势(不再需要作为控件)。如果初始触摸点不在视图的边缘(在某个边界内),则这些失败。这些会触发整个表视图的更改。
表格单元格具有滑动手势,每个手势都需要自定义手势失败。这些会触发您的细胞删除逻辑。
答案 2 :(得分:1)
您的想法与iOS7解锁屏幕和日历的构建方式有一些相似之处。在解锁屏幕中,您可以滑动通知,上下移动通知列表,然后滑动以解锁。在日历应用中,您可以滑动以更改当前日期,或者滑动标题以更改周。因此,我建议观看 WWDC 2013会话视频#217“探索iOS 7上的滚动视图”,它解释并演示了他们是如何完成的,以及如何复制功能。
基本上,你可以做的(以及他们为解锁屏幕和日历屏幕做了什么)是:(A)在UITableView中嵌套UIScrollViews或(B)在每个单元格上使用滑动/平移手势委托,(C)嵌套UITableView以及其他UITableViews,表示启用了分页控制的UIScrollView中的天数。
(A)将允许您在单元格中公开删除按钮。您可以将删除按钮放在单元格中的UIScrollView下,以滑动内容的方式显示它。
(B)将允许您跟踪单元格中的手势,如果需要可以取消它,并使用单元格的contentView来显示删除按钮。
(C)将允许您轻松地从一个UITableView滑动到另一个UITableView,并且通过分页启用,您将获得免费的“卡入到位或反弹”动画PLUS您可以轻松地重复使用两个UITableViews而不是每天分配一个。
就个人而言,我会选择(B)和(C)。
答案 3 :(得分:0)
原来我的hitTest方法存在问题。用[super hitTest ...]替换[self.mainTableView hitTest ...]解决了我的问题。我想我弄乱了一些坐标,导致这个方法在返回视图时返回nil。我并不是100%确定它究竟出了什么问题,但它现在确实有效。