【问题标题】:Scroll Table View with a cell that was selected with a long press使用长按选择的单元格滚动表格视图
【发布时间】:2014-06-03 03:47:49
【问题描述】:

我有一个表格视图,我想在选定单元格时滚动它并将其“弹出”并在表格视图周围移动。表格视图滚动得很好,长按选择一个单元格可以工作,但是当我选择了一个单元格时,我无法滚动表格视图。

我阅读了UIGestureRecognizerDelegate,但我不确定这是否有所作为。我也称这些方法

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

这是我的部分代码:

- (IBAction)longPressGestureRecognized:(id)sender {

UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender;
UIGestureRecognizerState state = longPress.state;
//longPress.delegate = self;

CGPoint location = [longPress locationInView:self.personTableView];
NSIndexPath *indexPath = [self.personTableView indexPathForRowAtPoint:location];

static UIView       *snapshot = nil;        ///< A snapshot of the row user is moving.
static NSIndexPath  *sourceIndexPath = nil; ///< Initial index path, where gesture begins.

switch (state) {
    case UIGestureRecognizerStateBegan: {
        if (indexPath) {
            sourceIndexPath = indexPath;

            UITableViewCell *cell = [self.personTableView cellForRowAtIndexPath:indexPath];
            // capture the color of the cell before blacking out
            savedTextColor = cell.detailTextLabel.textColor;

            // Take a snapshot of the selected row using helper method.
            snapshot = [self customSnapshotFromView:cell];

            // Add the snapshot as subview, centered at cell's center...
            __block CGPoint center = cell.center;
            snapshot.center = center;
            snapshot.alpha = 0.0;
            [self.personTableView addSubview:snapshot];
            [UIView animateWithDuration:0.25 animations:^{

                // Offset for gesture location.
                center.y = location.y;
                snapshot.center = center;
                snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05);
                snapshot.alpha = 0.98;

                // Black out.
                cell.detailTextLabel.alpha = 0;
                cell.textLabel.alpha = 0;
            } completion:nil];
        }
        break;
    }
    case UIGestureRecognizerStateChanged: {
        CGPoint center = snapshot.center;
        center.y = location.y;
        snapshot.center = center;

        // Is destination valid and is it different from source?
        if (indexPath && ![indexPath isEqual:sourceIndexPath]) {

            // ... update data source.
            [dataSingelton saveUpdatedPersonList:(int)indexPath.row sourceIndex:(int)sourceIndexPath.row];
            //[[dataSingelton mutableDataArray] exchangeObjectAtIndex:indexPath.row withObjectAtIndex:sourceIndexPath.row];

            // ... move the rows.
            [self.personTableView moveRowAtIndexPath:sourceIndexPath toIndexPath:indexPath];

            // ... and update source so it is in sync with UI changes.
            sourceIndexPath = indexPath;
        }
        break;
    }

    default: {
        // Clean up.
        UITableViewCell *cell = [self.personTableView cellForRowAtIndexPath:sourceIndexPath];
        [UIView animateWithDuration:0.25 animations:^{
            snapshot.center = cell.center;
            snapshot.transform = CGAffineTransformIdentity;
            snapshot.alpha = 0.1;
            cell.detailTextLabel.alpha = 1;
            cell.textLabel.alpha = 1;
        } completion:^(BOOL finished) {
            [snapshot removeFromSuperview];
            snapshot = nil;
            cell.hidden = NO;
        }];
        sourceIndexPath = nil;
        break;
    }
}

}

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}



- (UIView *)customSnapshotFromView:(UIView *)inputView {

    UIView *snapshot = [inputView snapshotViewAfterScreenUpdates:YES];
    snapshot.alpha = 0.1;
    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;
}

当我像这样将委托设置为 self 时:

longPress.delegate = self;

能够滚动的视图,但随后我选择的单元格没有移动。我缺少什么来完成这项工作?

* 更新 * 在做了更多阅读/研究之后,我认为为了达到我想要的效果(Apple 天气应用程序中 TableView 上的滚动效果),我认为我的长按手势也必须处理我的表格视图的滚动。默认滚动开始立即滚动整个表格,因为我需要表格仅在长按单元格位于我的 TableView 的顶部或底部时滚动。我这样想对吗?我一直试图找到一个例子来分解和研究,但没有找到类似的东西。

** 已更新 ** 因此,我试图弄清楚当用户将单元格向上拖动到顶部时如何触发向上滚动计时器。我现在遇到的问题是确定该单元格何时接近顶部,何时位于 tableview 的最顶部,这很容易我可以使用tableViewHight + 100 之类的东西,但是当 tableview 是时此代码将不起作用向下滚动。这是我目前所拥有的:

NSLog(@"This is table view hight %.2f", tableViewHight);

            NSLog(@"This is content offset %f",  (personTableView.contentOffset.y));

            NSLog(@"Should be 100 place holder %.2f", (tableViewHight - tableViewHight) + personTableView.contentOffset.y + 100);

            NSLog(@"location y %f", location.y);



            // gets called repeatedly
            // Step 1: check to see if we need to start scrolling
            if (location.y < tableViewHight - tableViewHight + 100) {
                // ** top **
                // Step 2: make sure the current y postoin isn't greater then the previous y postion
                if (location. y <= originalLocation.y) {
                   // NSLog(@"This is the offset y %f", self.personTableView.contentOffset.y);

                        // Step 4: check to see if we have a timer and if not create one
                        [self startTimer];


                }
                else{
                    //Step 3: they started to scroll up so end the timer
                    [self endTimer];
                }
            }
            else if(location.y > tableViewHight - 100)
            {
                // ** bottom **
                // Step 2: make sure the current y postoin isn't less then the previous y postion
                if (location. y >= originalLocation.y) {

                        NSLog(@"its less then 0");
                        if (!timer) {
                            // Step 4: check to see if we have a timer and if not create one
                            [self startTimer];
                        }


                }
                else{
                     //Step 3: they started to scroll up so end the timer
                    [self endTimer];
                }
            }
            else{
                // ** middle **
                // Step 2: check to see if we have a timer and if so destory it
                [self endTimer];
            }

基本上我想在单元格距离可滚动表格视图的高度小于 100px 时触发 if 语句。

【问题讨论】:

  • 您能否提供完整的代码以及应用的解决方案,因为我面临同样的情况?任何帮助将不胜感激。

标签: objective-c uitableview xcode5 tableview long-press


【解决方案1】:

UILongPressGestureRecognizer 可以得到当前y 的触摸位置。从中您可以计算出与UITableViewthe touch 的底部或顶部的距离。如果您确定它足够接近开始滚动,则开始重复 NSTimer,将 UITableView 的 contentOffset 递增或递减 1 个像素,滚动您的表格。通过更改计时器的timeInterval 来更改它的滚动速度。

UILongPressGestureRecognizer 结束时,或者如果触摸的y 位置移动到滚动区域之外,则使您的计时器无效,这将停止滚动。

如果您喜欢冒险,您还可以通过在用户向上或向下移动触摸时更改 timeInterval 来在用户接近 UITableView 边缘时动态提高滚动速度,因为这通常这种类型的功能是如何工作的。

祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-30
    • 1970-01-01
    • 2021-11-18
    • 2012-03-11
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多