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学习笔记(11)TableView中移动cell和section

在TableView中移动cell和section 用tableView的moveSection:toSection:方法把一个Section移动到新位置。也可以使用moveRowAtIndex...

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

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

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

iOS-TableView拖动Cell更换次序

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

UITableView实现选择框和编辑状态时cell向右移动的自定义方法

一.首先我们先做一个tableview的demo看一下初始的效果// // TableViewController.m // UITableView实现选择框和编辑状态时cell向右移动UITab...

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

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

iOS - 移动自定义UITableViewCell

1.长按即可触发移动cell,操作逻辑简单; 2.移动cell时越靠近屏幕边缘,速度越快; 3.被移动cell的样式可以自定义; 调研如果只是实现移动UITableViewCell,系统自带的A...

IOS 自定义UITableViewCell

自定义的列表项,有几种方式,暂时我研究的还只有一种: 1、新建一个xib文件,在这个里面来设置你的Cell样式 在你新建文件要存放的位置,右键鼠标,选择New File,进入新建文件的界面 ...

ios中自定义cell,自定义UITableViewCell

通过继承UITableViewCell来自定义cell 1、创建一个空的项目、命名: 2、创建一个UITableViewController 并且同时创建xib: 3、设置AppD...

ios 自定义tableViewcell,UITableViewCell

自定义tableViewcell,当系统自带的tableView样式无法满足我们的需求可通过代码实现自定义cell

iOS开发:自定义UITableViewCell

上篇文章介绍了如何用UITableView显示表格,并讲了几种UITableViewCell的风格。不过有时候我们需要自己定义UITableViewCell的风格,其实就是向行中添加子视图。添加子视图...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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