在iOS应用程序中拖动UITableViewCells时自动滚动UITableView
我已经实现了一个在UITableView中对单元格重新排序的系统。一切正常,只是我不能将单元格重新排序到iPhone屏幕上没有显示的位置 所以我实现了一个条件来检查我是否必须滚动在iOS应用程序中拖动UITableViewCells时自动滚动UITableView,ios,objective-c,uitableview,scroll,Ios,Objective C,Uitableview,Scroll,我已经实现了一个在UITableView中对单元格重新排序的系统。一切正常,只是我不能将单元格重新排序到iPhone屏幕上没有显示的位置 所以我实现了一个条件来检查我是否必须滚动 NSArray *indexVisibles = [_tableView indexPathsForVisibleRows]; NSInteger indexForObject = [indexVisibles indexOfObject:indexPath]; if (indexForObject == NSNotF
NSArray *indexVisibles = [_tableView indexPathsForVisibleRows];
NSInteger indexForObject = [indexVisibles indexOfObject:indexPath];
if (indexForObject == NSNotFound){
[_tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
}
我的问题是,动画不是甜蜜和干净
我认为检查一个单元格是否显示的操作对我的系统来说是非常大的,并且在移动单元格时会有一个小的延迟,但是我也不知道为什么隐藏单元格时滚动会如此困难
我已经将UITableViewScrollPositionTop
更改为UITableViewScrollPositionMiddle
,现在更好了,但速度非常快,所以总是滚动到我的UITableView的顶部
我想慢慢来
其他失败尝试:
备选案文1:
[UIView animateWithDuration:0.2
animations:^{_tableView.contentOffset = CGPointMake(0.0, _tableView.contentOffset.y - 50);}
completion:^(BOOL finished){ }];
但这有两个问题:
[UIView animateWithDuration: 1.0
animations: ^{
[_tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionMiddle
animated:NO];
}completion: ^(BOOL finished){
}
];
我还在寻找一种通过长按tableview单元格来渲染它们的方法。 我为此找到了一个存储库。如果您不介意将第三方库放到您的项目中,请查看它!:)
我个人将此代码用于我的应用程序Cheetah Note。他们工作得很有魅力!强烈推荐 当拖动的单元格位于顶部时,使用选项1尝试滚动到拖动的单元格位置-1:
NSArray *indexVisibles = [_tableView indexPathsForVisibleRows];
NSInteger indexForObject = [indexVisibles indexOfObject:indexPath];
if (indexForObject == 0){
[_tableView scrollToRowAtIndexPath:indexPathForCellBefore
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
}
要平滑滚动tableview,请使用以下代码段:
[UIView animateWithDuration: 1.0 animations: ^{
[_tableView scrollToRowAtIndexPath:indexPathForCellBefore atScrollPosition:UITableViewScrollPositionTop animated:NO];
} completion: ^(BOOL finished){
}];
当然,当你向下滚动时,你需要修改它才能工作。我已经用一个非常漂亮的解决方案解决了我的问题,所以我将用三个简单的步骤来解释如何做到这一点 我从中获得了一些灵感,并将其分享到我自己的知识库中 A.管理手势识别 长按手势识别: scrollTableWithCell: 当您处于表格的限制(上下)时,调用它进行滚动移动的方法 customSnapshoFromView: 返回给定视图的自定义快照*/
- (UIView *)customSnapshoFromView:(UIView *)inputView {
// Make an image from the input view.
UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, NO, 0);
[inputView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Create an image view.
snapshot = [[UIImageView alloc] initWithImage:image];
snapshot.layer.masksToBounds = NO;
snapshot.layer.cornerRadius = 0.0;
snapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0);
snapshot.layer.shadowRadius = 5.0;
snapshot.layer.shadowOpacity = 0.4;
return snapshot;
}
更新NapshotWithPosition:
给定一个CGPoint,它会更改快照位置,以显示正在移动的单元格在_tableView的正确位置
-(void)updateSnapshotWithPosition:(CGPoint)location{
CGPoint center = snapshot.center;
center.y = location.y;
snapshot.center = center;
}
-(void)deleteSnapshotForRowAtIndexPath:(NSIndexPath *)sourceIndexPath{
UITableViewCell *cell = [_tableView cellForRowAtIndexPath:sourceIndexPath];
cell.hidden = NO;
cell.alpha = 0.0;
[UIView animateWithDuration:0.25 animations:^{
snapshot.center = cell.center;
snapshot.transform = CGAffineTransformIdentity;
snapshot.alpha = 0.0;
cell.alpha = 1.0;
} completion:^(BOOL finished) {
[snapshot removeFromSuperview];
}];
}
DeleteSnapshotForRow索引路径:
拖动完成后,需要从_tableView中删除快照
-(void)updateSnapshotWithPosition:(CGPoint)location{
CGPoint center = snapshot.center;
center.y = location.y;
snapshot.center = center;
}
-(void)deleteSnapshotForRowAtIndexPath:(NSIndexPath *)sourceIndexPath{
UITableViewCell *cell = [_tableView cellForRowAtIndexPath:sourceIndexPath];
cell.hidden = NO;
cell.alpha = 0.0;
[UIView animateWithDuration:0.25 animations:^{
snapshot.center = cell.center;
snapshot.transform = CGAffineTransformIdentity;
snapshot.alpha = 0.0;
cell.alpha = 1.0;
} completion:^(BOOL finished) {
[snapshot removeFromSuperview];
}];
}
计算滚动
声明使用上述代码所需的变量
@implementation YourClassName{
CADisplayLink *_scrollDisplayLink;
CGFloat _scrollRate;
UIView *snapshot; // A snapshot of the row user is moving.
NSIndexPath *sourceIndexPath; // Initial index path, where gesture begins.
}
这就是解决我的问题所需的一切。我正在使用Objective-C,但在该存储库的描述中,我发现了这一点。我将测试它。我无法编译该项目。是的,我很抱歉听到这一消息。。存储库已经很长时间没有更新了。您可以在本教程中使用LPRTableView。在本教程中,您可以找到将swift类导入对象文件的方法:)请检查此存储库,希望这对您有用。这似乎是正确的,但它有一些错误,它不适用于我的项目。但是我正在研究您的代码,以找到错误并修复错误。这对我没有帮助,因为
滚动箭头路径:atScrollPosition:Animated
的动画非常强大,我希望平滑地滚动UITableView是,它解决了我的一个问题,那就是当你将单元格拖动到顶部时,如何将其保持在0的位置,但移动并不平滑,这是我所期望的。我只是想确认一下。我将尝试检查其他问题。我已经尝试了if(indexForObject==0&&indexPath.row>0){[\u tableView scrollToRowAtIndexPath:[NSIndexPath indexPath indexPathForRow:indexPath.row-1片段:0]atScrollPosition:UITableViewScrollPositionMiddle动画:是];}
我不知道UITableViewScrollPositionMiddle和UITableViewScrollPositionTop的区别。但中间,它走得相当快(我都不想要),但它更真实的动画请检查此存储库希望这是你的工作。github.com/hpique/hpreOrderTableViews您是否可以共享视图控制器的所有源代码,或者您是否可以显示什么是“_elementsOffset”(它是如何计算的)和其他辅助方法,例如“calculateScroll”elementsOffset是可选的,如果您的表顶部有要锁定的元素,您可以使用它。我在这个存储库中分享了我的课程。如果您有任何问题,请尽管问我;)希望它能帮助你!
-(void)deleteSnapshotForRowAtIndexPath:(NSIndexPath *)sourceIndexPath{
UITableViewCell *cell = [_tableView cellForRowAtIndexPath:sourceIndexPath];
cell.hidden = NO;
cell.alpha = 0.0;
[UIView animateWithDuration:0.25 animations:^{
snapshot.center = cell.center;
snapshot.transform = CGAffineTransformIdentity;
snapshot.alpha = 0.0;
cell.alpha = 1.0;
} completion:^(BOOL finished) {
[snapshot removeFromSuperview];
}];
}
-(void)calculateScroll:(UIGestureRecognizer *)gestureRecognizer{
const CGPoint location = [gestureRecognizer locationInView:_tableView];
CGRect rect = _tableView.bounds;
// adjust rect for content inset as we will use it below for calculating scroll zones
rect.size.height -= _tableView.contentInset.top;
//[self updateCurrentLocation:gestureRecognizer];
// tell us if we should scroll and which direction
CGFloat scrollZoneHeight = rect.size.height / 6;
CGFloat bottomScrollBeginning = _tableView.contentOffset.y + _tableView.contentInset.top + rect.size.height - scrollZoneHeight;
CGFloat topScrollBeginning = _tableView.contentOffset.y + _tableView.contentInset.top + scrollZoneHeight;
// we're in the bottom zone
if (location.y >= bottomScrollBeginning)
{
_scrollRate = (location.y - bottomScrollBeginning) / scrollZoneHeight;
}
// we're in the top zone
else if (location.y <= topScrollBeginning)
{
_scrollRate = (location.y - topScrollBeginning) / scrollZoneHeight;
}
else
{
_scrollRate = 0;
}
}
_reorderGestureRecognizer = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(longPressGestureRecognized:)];
[_tableView addGestureRecognizer:_reorderGestureRecognizer];
@implementation YourClassName{
CADisplayLink *_scrollDisplayLink;
CGFloat _scrollRate;
UIView *snapshot; // A snapshot of the row user is moving.
NSIndexPath *sourceIndexPath; // Initial index path, where gesture begins.
}