iOS - 移动自定义UITableViewCell

原创 2016年08月29日 15:11:49

这里写图片描述
1.长按即可触发移动cell,操作逻辑简单;
2.移动cell时越靠近屏幕边缘,速度越快;
3.被移动cell的样式可以自定义;
调研

如果只是实现移动UITableViewCell,系统自带的API即可搞定。
调用下面的方法[tableView setEditing:YES animated:YES];即可进入编辑模式。然后实现下面的方法即可开启移动cell。
//默认编辑模式下,每个cell左边有个红色的删除按钮,设置为None即可去掉

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return UITableViewCellEditingStyleNone;
}
//是否允许indexPath的cell移动
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
    //更新数据源
}

用系统的方法有几个缺点:
1.需要用一个开关去控制编辑状态,不方便;
2.移动cell的时候cell右边有个指示图标,看着不爽;
3.被移动cell的样式不能自己定制。
综上所述,需要自己去写效果了。

实现原理
大概原理:为UITableView添加一个长按手势,然后给选中的cell截图;让截图随着手势移动,同时记录选中的indexPath,方便位置互换。

1.添加长按手势

longPressGesutre = UILongPressGestureRecognizer.init(target: self, action:#selector(HomePageViewController.handleLongpressGesture(_:)))
        longPressGesutre.minimumPressDuration = 0.5
        self.tableView.addGestureRecognizer(longPressGesutre)

2.处理手势开始

    func handleLongpressGesture(sender:UILongPressGestureRecognizer) {

        switch sender.state {
        case UIGestureRecognizerState.Began:
            gestureBegan(sender)
            break
        case UIGestureRecognizerState.Changed:
            gestureChanged(sender)
            break
        case UIGestureRecognizerState.Cancelled:
            gestureEnded(sender)
            break
        case UIGestureRecognizerState.Ended:
            gestureEnded(sender)
            break
        default:

            break
        }
    }

3 开始处理手势

private func gestureBegan(gesture:UILongPressGestureRecognizer) {
        let location:CGPoint = gesture.locationInView(self.tableView)
        let indexPath:NSIndexPath! = self.tableView.indexPathForRowAtPoint(location)

        if indexPath != nil {
            // 开启边缘滚动
            startEdgeScroll()
            sourceIndexPath = indexPath
            let cell:HomeSubTableViewCell = self.tableView.cellForRowAtIndexPath(indexPath) as! HomeSubTableViewCell
            snapshot = self.customSnapshotFromView(cell)
            var center:CGPoint = cell.center
            snapshot.center = center
            snapshot.alpha = 0
            self.tableView.addSubview(snapshot)
            UIView.animateWithDuration(0.25, animations: {
                center.y = location.y
                self.snapshot.center = center
                self.snapshot.transform = CGAffineTransformMakeScale(1, 1)
                self.snapshot.alpha = 1.0
                self.snapshotColor = cell.backgroundColor
                cell.backgroundColor = UIColor.clearColor()
                cell.hidden = true
                }, completion: nil)
        }
    }

4 处理手势状态变化,并交换数据源

private func gestureChanged(gesture:UILongPressGestureRecognizer) {
        let location:CGPoint = gesture.locationInView(self.tableView)
        let indexPath:NSIndexPath! = self.tableView.indexPathForRowAtPoint(location)
        var center:CGPoint = snapshot.center
        center.y = location.y
        snapshot.center = center
        if indexPath != nil && indexPath.isEqual(sourceIndexPath) == false {

            let cellA:HomeSubTableViewCell = tableView.cellForRowAtIndexPath(sourceIndexPath) as! HomeSubTableViewCell
            let cellB:HomeSubTableViewCell = tableView.cellForRowAtIndexPath(indexPath) as! HomeSubTableViewCell
            let modelToMove:HomePageCellModel = self.dataArr![sourceIndexPath.row]
            self.dataArr!.removeAtIndex(sourceIndexPath.row)
            self.dataArr!.insert(modelToMove, atIndex: indexPath.row)
            StoreDataModel.sharedInstance.changeChooseRate((cellA.model?.nameEn)!, codeB: (cellB.model?.nameEn)!)
            self.tableView.moveRowAtIndexPath(sourceIndexPath, toIndexPath: indexPath)
            sourceIndexPath = indexPath
        }
    }

5 手势结束或者取消,结束之后将视图还原

private func gestureEnded(gesture:UILongPressGestureRecognizer) {
        if edgeScrollTimer != nil {
            edgeScrollTimer.invalidate()
            edgeScrollTimer = nil
        }
        let cell:HomeSubTableViewCell = self.tableView.cellForRowAtIndexPath(sourceIndexPath) as! HomeSubTableViewCell
        UIView.animateWithDuration(0.25, animations: {
            self.snapshot.center = cell.center
            self.snapshot.transform = CGAffineTransformIdentity
            self.snapshot.alpha = 0
            cell.backgroundColor = self.snapshotColor
            cell.hidden = false
            }, completion: { (finished:Bool) in
                self.snapshot.removeFromSuperview()
                self.snapshot = nil
        })
        sourceIndexPath = nil
    }

6.处理边缘滚动

///开始边界翻滚
    private func startEdgeScroll() {
        edgeScrollTimer = CADisplayLink.init(target: self, selector: #selector(processEdgeScroll))
        edgeScrollTimer.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
    }

    @objc private func processEdgeScroll() {

        gestureChanged(longPressGesutre)

        let minOffsetY:CGFloat = self.tableView.contentOffset.y + 150
        let maxOffsetY:CGFloat = self.tableView.contentOffset.y + self.tableView.bounds.size.height - 150
        let touchPoint = snapshot.center

        //处理上下达到极限之后不再滚动tableView,其中处理了滚动到最边缘的时候,当前处于edgeScrollRange内,但是tableView还未显示完,需要显示完tableView才停止滚动
        if touchPoint.y < 150 {
            if self.tableView.contentOffset.y <= 0 {
                return
            } else {
                if self.tableView.contentOffset.y - 1 < 0 {
                    return;
                }
                self.tableView.setContentOffset(CGPointMake(self.tableView.contentOffset.x
                    , self.tableView.contentOffset.y), animated: false)
                snapshot.center = CGPointMake(snapshot.center.x, snapshot.center.y - 1)
            }

        }

        if touchPoint.y > self.tableView.contentSize.height - 150 {
            if self.tableView.contentOffset.y >= self.tableView.contentSize.height - self.tableView.bounds.size.height {
                return
            } else {
                if self.tableView.contentOffset.y + 1 > self.tableView.contentSize.height - self.tableView.bounds.size.height {
                    return;
                }
                self.tableView.setContentOffset(CGPointMake(self.tableView.contentOffset.x, self.tableView.contentOffset.y + 1), animated: false)
                snapshot.center = CGPointMake(snapshot.center.x, snapshot.center.y + 1)
            }
        }
        // 处理滚动
        let maxMoveDistance:CGFloat = 20

        if touchPoint.y < minOffsetY {
            // cell在向上滚动
            let moveDistance:CGFloat = (minOffsetY - touchPoint.y) / 150 * maxMoveDistance
            self.tableView.setContentOffset(CGPointMake(self.tableView.contentOffset.x, self.tableView.contentOffset.y - moveDistance), animated: false)
            snapshot.center = CGPointMake(snapshot.center.x, snapshot.center.y - moveDistance)
        } else if touchPoint.y > maxOffsetY {
            // cell在向下滚动
            let moveDistance:CGFloat = (touchPoint.y - maxOffsetY) / 150 * maxMoveDistance
            self.tableView.setContentOffset(CGPointMake(self.tableView.contentOffset.x, self.tableView.contentOffset.y + moveDistance), animated: false)
            snapshot.center = CGPointMake(snapshot.center.x, snapshot.center.y + moveDistance)
        }
    }

总结
通过截图实现以假乱真,自由移动截图产生的”cell”;交换的时候,首先要交换数据源,再交换cell;处理边缘滚动的时候,需要小心各种边界条件。

版权声明:阳仔原创,转载请注明出处。

相关文章推荐

iOS table简单实现增加移动和删除功能与自定义cell的实现

在RootViewController.h文件中 #import @interface RootViewController : UIViewController { ...

iOS_UITableView 编辑(cell的插入, 删除, 移动)

iOS_UITableView 编辑(cell的插入, 删除, 移动) 说明: UITableView 中的cell的插入, 删除, 移动效果的实现, 主要通过UITableView的协议中...

iOS之实现按钮拖动/tableViewcell多选,拖动/collectionviewcell多选,拖动(交换位置)

iOS之实现按钮拖动

iOS tableViewCell 的移动操作 (添加长按手势)

iOS tableViewCell 的移动操作 (添加长按手势)

iOS-TableView拖动Cell更换次序

效果: 长按某个Cell,Cell会有一个明显的弹起放大效果。这时候,你可以通过拖动cell和其他Cell更换顺序。   实现的原理: 1,浮层 长按后,UITa...

UITableViewCell的标记、移动、删除、插入

这篇文章是建立在  代码实现 UITableView与UITableViewCell基础上进行修改,用不上的代码我注释调,部分不明白可以看看上篇博客;实现的功能是对UITableViewCell...

iOS自定义长按手势,随意拖动Cell

iOS自定义长按手势,随意拖动Cell起因 最近在做一个项目,要对UITableViewCell进行拖动蹂躏,具体效果如下: 本来打算用UIRespon这几个方法来做,最后发现在UITableView...

cell上添加按钮点击不执行的解决办法

self.isPlayOrPause=YES;          UIView *spbg=[[UIView alloc]initWithFrame:CGRectMake(10,10, self....

自定义表格编辑状态下左侧多选按钮

当项目中需要自定义表格多选编辑状态下的选中图片时候,系统并没有给我们什么方法去直接自定义。此时我们需要在选中cell的方法里去做一些操作...

iOS、UITableViewCell、自定义

  • 2016年02月18日 17:38
  • 9.85MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS - 移动自定义UITableViewCell
举报原因:
原因补充:

(最多只允许输入30个字)