UITableViewController选择某个section的header

37

我有一个带有多个分区的UITableView。 每个分区都有一个分区头部(自定义视图),是否有一种简单的方法来检测当有人选择了该分区的头部?(就像didSelectRowAtIndexPath,但是用于头部?)

5个回答

74

这并不与@rckoenes的答案有很大区别,但它提供了一种更正统的方式来处理视图上的事件,而不是使用不可见的按钮。

我更愿意向我的标题视图添加UITapGestureRecognizer,而不是添加不可见的按钮并调整它们的大小:

UITapGestureRecognizer *singleTapRecogniser = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)] autorelease];
[singleTapRecogniser setDelegate:self];
singleTapRecogniser.numberOfTouchesRequired = 1;
singleTapRecogniser.numberOfTapsRequired = 1;   
[yourHeaderView addGestureRecognizer:singleTapRecogniser];

然后:

- (void) handleGesture:(UIGestureRecognizer *)gestureRecognizer;
你可以使用 gesture.view 来查看哪个被触摸。然后执行你需要的操作以确定它是哪个标题(标签,数据数组查找...)

我认为你必须将方法更改为: - (void) gestureHandler:(UIGestureRecognizer *)gestureRecognizer; 因为你定义动作为 gestureHandler - fsulser
使用 YourView *tappedView = (YourView *)gestureRecognizer.view; 来查看哪个视图被触摸,这更加明确。 - steveen zoleko
1
numberOfTouchesRequirednumberOfTapsRequired 默认值为 1,无需将它们设置为 1。 - Jonathan Cabrera

29

不能使用UITableViewDelegate来实现。

你可以添加一个跟区头视图一样大小的按钮,将其添加到视图中,并设置按钮的标签为区索引。然后将UIViewController添加为UIControlEventTouchUpInside 的目标。

通过查看按钮的标签,你可以知道哪个区被点击了。


或者您可以在“viewForHeaderInSection”方法中返回一个头部大小的UIButton,而不是将其添加为视图并返回它。 - mahesh.me

9

以下是我在Swift 2中使用的方法:

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let footerView = UITableViewHeaderFooterView()
    footerView.textLabel?.text = "Header Text"
    let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
    tapRecognizer.delegate = self
    tapRecognizer.numberOfTapsRequired = 1
    tapRecognizer.numberOfTouchesRequired = 1
    footerView.addGestureRecognizer(tapRecognizer)
    return footerView
}

@objc func handleTap(gestureRecognizer: UIGestureRecognizer) {
    print("Tapped")
}

6

这个方法可以用来评估部分和行。我希望能对那些苦于无法正确使用此方法的人有所帮助。

override func viewDidLoad() {
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(sectionTapped(sender:)))
    tableView?.addGestureRecognizer(tapGesture)
    tapGesture.delegate = self as? UIGestureRecognizerDelegate
}

@objc func sectionTapped(sender: UITapGestureRecognizer) {
    if sender.state == UIGestureRecognizerState.ended {
        guard let tableView = self.tableView else {
            return
        }
        if let view = sender.view {
            let tapLocation = sender.location(in: tableView)
            if let tapIndexPath = tableView.indexPathForRow(at: tapLocation) {              
                if (tableView?.cellForRow(at: tapIndexPath) as? UITableViewCell) != nil {
                    // do something with the row
                    print("tapped on row at index: \(tapIndexPath.row)")
                }
            }  else {
                for i in 0..<tableView.numberOfSections {
                    let sectionHeaderArea = tableView.rectForHeader(inSection: i)
                    if sectionHeaderArea.contains(tapLocation) {
                        // do something with the section
                        print("tapped on section at index: \(i)")
                    }
                }
            }
        }
    }
}

这个解决方案适用于iOS 13及以上版本。在iOS 12上,点击标题会返回tapIndexPath.row的值为0。如果你的目标是在节标题上进行点击,则可以省略if let view = sender.view块。 - J Kasparian

0

这是Taku答案的稍微更新版本。

override func viewDidLoad() {
        super.viewDidLoad()
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(sectionTapped(sender:)))
        tableView.addGestureRecognizer(tapGesture)
        tapGesture.delegate = self
    }

@objc func sectionTapped(sender: UITapGestureRecognizer) {
        guard sender.state == .ended else { return }
        
        let tapLocation = sender.location(in: tableView)
        if let tapIndexPath = tableView.indexPathForRow(at: tapLocation),
           let cell = tableView.cellForRow(at: tapIndexPath) {
            // TODO: Do something with row
            print("tapped on row at index: \(tapIndexPath.row)")
        } else {
            for section in 0..< tableView.numberOfSections {
                let headerRect = tableView.rectForHeader(inSection: section)
                if headerRect.contains(tapLocation) {
                    // TODO: Do something with the section
                    print("Tapped on section at index: \(section)")
                }
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接