重新排列UITableView中的部分

时间:2018-10-02 11:25:52

标签: ios uitableview move sections

我有带有部分和行(https://imgur.com/a/hrYTEVR)的UITableView。我知道如何启用对行的重新排序,但是我不知道如何实现对部分的重新排序。 我需要将重排序控件添加到section(https://imgur.com/a/V5kU9Ew)中,然后当用户触摸此控件时,section下的行应该失败。之后,用户可以将部分移到新位置。 在阅读了关于stackoverflow和其他站点的主题之后,我没有发现如何实现这样的好主意。 我考虑过通过单元实现节,但是在这种情况下,我无法在节下翻转行以进一步移动到新位置。 如果您有任何想法,请给我建议。谢谢!

2 个答案:

答案 0 :(得分:0)

您可以将标题用于节,而不能将表格视图单元格用于节。首先,您需要告诉表视图中需要多少节:

func numberOfSections(in tableView: UITableView) -> Int{ 
    return yourSectionNumber 
}

然后为每个部分指定:

func headerView(forSection section: Int) -> UITableViewHeaderFooterView? {
    return yourSpecifiedHeaderView
}

或者,如果要使用Apple提供的部分的默认标题视图,则可以使用:

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
     return yourSectionTitle
}

然后进行订购,您可以一起订购您的部分和数据。这里的建议是创建自己的包含tableView行数据的类。例如:

class Foo {
    var sectionTitle: String
    var data: [AnotherClassForData]
}

class AnotherClassForData {
    var rowTitle: String
   // other properties
}

然后在tableView中,您将有一个类为Foo的对象的数组。 例如:

var dataSource = [Foo]()

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
     return dataSource[section].sectionTitle
}

然后在代码中的某个地方,您可以像这样重新排序:

dataSource.sorted(by: { $0.sectionTitle > $1.sectionTitle } ) 

然后,您可以像往常一样重新加载tableView:

DispatchQueue.main.async {
    self.tableView.reloadData()
}

答案 1 :(得分:0)

没有本机功能可以实现您想要的。如果我理解正确,那么您将希望折叠整个行的一部分,然后开始拖动“标题”。如果您想自己执行此操作,建议您从平移手势识别器开始,该识别器在标题按钮上触发。

手势应该相对明显。在标题上启动后,您需要在表格视图中使用locationIn来跟踪位置。

要折叠行,您需要做的就是使用适当的动画修改表格视图单元格,例如:

tableView.beginUpdates()
tableView.deleteSections([myIndexPath], with: .top) // Maybe experiment with animation type
// Modify whatever you need to correspond this change in the data source
tableView.endUpdates()

由于将要删除的部分也将删除具有手势识别器的视图(标题)。这意味着将手势直接添加到表视图甚至是其超级视图可能会更好。您仅在按下标题上的那些按钮之一时才需要强制它触发。您可以对此有了一些认识here。其余不受此更改的影响。

在这一点上,您可能需要创建一个额外的视图,该视图代表您的部分堆栈并顺您的手指。如果您将其添加为子视图并在其超级视图中使用平移手势识别器locationIn来操纵它的中心,这应该非常容易:

movableSectionView.center = panGestureRecognizer.location(in: movableSectionView.superview!) 

因此,到目前为止,您应该能够抓住一个折叠所有单元格的区域,并能够拖动“部分堆栈”视图。现在,您需要检查表格视图中的什么位置,以了解将节放在哪里。这有点痛苦,但是可以使用visibleCellstableView.indexPath(for: )来完成:

func indexPathForGestureRecognizer(_ recognizer: UIGestureRecognizer) -> IndexPath {
    let coordinateView: UIView = tableView.superview! // This can actually be pretty much anything as long as it is in hierarchy
    let y = recognizer.location(in: coordinateView).y
    if let hitCell = tableView.visibleCells.first(where: { cell in
        let frameInCoordinateView = cell.convert(cell.bounds, to: coordinateView)
        return frameInCoordinateView.minY >= y && frameInCoordinateView.maxY <= y
    }) {
        // We have the cell at which the finger is. Retrieve the index path
        return tableView.indexPath(for: hitCell) ?? IndexPath(row: 0, section: 0) // This should always succeed but just in case
    } else {
        // We may be out of bounds. That may be either too high which means above the table view otherwise too low
        if recognizer.location(in: tableView).y < 0.0 {
            return IndexPath(row: 0, section: 0)
        } else {
            guard tableView.numberOfSections > 0 else {
                return IndexPath(row: 0, section: 0) // Nothing in the table view at all
            }
            let section = tableView.numberOfSections-1
            return IndexPath(row: tableView.numberOfRows(inSection: section), section: section)
        }
    }
}

手势识别器结束后,您可以使用此方法来获取要放入项目的部分。因此:

tableView.beginUpdates()
// Modify whatever you need to correspond this change in the data source
tableView.insertSections([indexPathForGestureRecognizer(panGestureRecognizer).section], with: .bottom)
tableView.endUpdates()

基本上,这对于重新排序应该足够了,但是您可能希望在表格视图中显示拖动部分所在的位置。就像在要放入堆栈的部分末尾有一个占位符。通过简单地添加然后移动一个额外的占位符单元格(重用indexPathForGestureRecognizer来获得位置),这应该相对容易。

玩得开心。