防止UITableViewCell子视图上的交互

时间:2016-07-08 22:48:15

标签: ios swift cocoa-touch

我有一个大的UITableViewCell,里面有2个自定义UIViews。其中一个应该允许交互(选择和取消选择),其中一个视图不应该允许交互。

我知道我可以在整个单元格或每个子视图上启用或禁用交互,但如果我在UIView上禁用交互,则单元格仍会被选中或取消选择。

有没有办法,例如,允许触摸细胞的上半部分而不是底部?

这是我描述的UITableViewCell的截图

enter image description here

5 个答案:

答案 0 :(得分:2)

我会说您的实施存在缺陷,或者您有X / Y问题。考虑将单个单元格拆分为两个单独的单元格,并禁用底部单元格上的选择。

如果您必须继续使用此实现,请考虑禁用整个单元格上的选择。将手势识别器放在顶部子视图中,然后手动触摸didSelectRowAtIndexPath:

答案 1 :(得分:1)

您可以使用点击测试转发或取消触摸

wire tmpValid = 1, tmpData = 1;

答案 2 :(得分:1)

我完全同意JAL,你需要检查所有的细胞结构,但我也知道有时候在某些情况下不可能进行重构。

所以,我想这个,假设你有两个视图组成的CustomTableViewCell,例如view1和view2命名:

代码:

class MyView1 : UIView {
    var isTouched : Bool = false
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.isTouched = true
        self.nextResponder()?.touchesBegan(touches, withEvent: event)
    }
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.isTouched = false
        self.nextResponder()?.touchesEnded(touches, withEvent: event)
    }
}
class MyView2 : UIView {
    var isTouched : Bool = false
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.isTouched = true
        self.nextResponder()?.touchesBegan(touches, withEvent: event)
    }
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.isTouched = false
        self.nextResponder()?.touchesEnded(touches, withEvent: event)
    }
}
class CustomTableViewCell: UITableViewCell {
    @IBOutlet weak var myExampleLabel: UILabel!
    @IBOutlet weak var view1: MyView1!
    @IBOutlet weak var view2: MyView2!

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        print("situation: myView1 : \(self.view1.isTouched) myView2: \(self.view2.isTouched)")
        var responder : UIResponder! = self
        while responder.nextResponder() != nil {
           responder = responder.nextResponder()
           if responder is SimpleTableView.ViewController { // the name of your tableView delegate class
                let vc = responder as! ViewController
                let indexPath = vc.tableView.indexPathForCell(self)
                vc.tableView(vc.tableView, didSelectRowAtIndexPath: indexPath!)
            }
        }
        super.touchesBegan(touches, withEvent: event)
    }
}

另一方面,例如UIViewController UITableView

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    @IBOutlet var tableView: UITableView!
    var items: [String] = ["We", "Heart", "Swift", "So", "Much"]

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 140.0
        self.tableView.registerNib(UINib(nibName: "CustomTableViewCell", bundle:nil), forCellReuseIdentifier: "CustomTableViewCell")
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.items.count;
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell", forIndexPath: indexPath) as! CustomTableViewCell
        cell.myExampleLabel.text = self.items[indexPath.row]
        return cell
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let cell = tableView.cellForRowAtIndexPath(indexPath) as! CustomTableViewCell
        print("row = %d",indexPath.row)
        if cell.view1.isTouched { 
           print("tableView: touched view 1") 
           // do whatever you want with cell.view1
           // if you want you can disable cell.view2.userInteractionEnabled
        }
        else {
            print("tableView: touched view 2")
            // same thing for cell.view2
        }
    }
}

一些重要的事情

不要忘记为两个视图设置正确的自定义类,如下图所示:

enter image description here

答案 3 :(得分:0)

实现此功能的一种方法是绕过UITableViewDelegate方法,并在单元格上使用带有自定义回调处理程序的IBAction

  1. 将单元格的选择类型设置为,以防止在您点击单元格时选择/取消选择单元格。
  2. 确保您的UITableViewDelegate未实现tableView:didSelectRowAtIndexPath
  3. 在单元格中添加一个按钮视图并将其定位,使其覆盖您希望用户与之交互的区域。
  4. @IBAction func buttonTapped(sender: UIButton)子类中添加UITableViewCell
  5. 向单元格添加闭包变量。点击按钮时调用闭包。
  6. tableView:cellForRowAtIndexPath:委托方法中,设置单元格上的闭包以处理调用。
  7. 示例UITableViewCell子类:

    class MyTableViewCell: UITableViewCell {
    
        var selectionHandler: ((Void) -> Void)?
    
        override func prepareForReuse() { 
            // Remove the closure when the cell is recycled.
            selectionHandler = nil
        }
    
        @IBAction func buttonTapped(sender: UIButton) {
            // Call the closure when the button is tapped.
            selectionHandler?()
        }
    }
    

    UITableViewController

    class MyTableViewController: UITableViewController {
    
        override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
            let cell = ....
    
            // Set the closure to be called when the button is tapped.
            // Using weak self here to prevent a retain cycle.
            cell.selectionHandler = { [weak self] in
                self?.selectedCellAtIndexPath(indexPath)
            }
    
            return cell
        }
    
        // We are not using didSelectRowAtIndexPath
        // override func tableView(tableView: UITableView, didSelectRowAtIndexPath: NSIndexPath) {
        // }
    }
    

    我没有测试过这段代码,所以它可能无法编译,虽然它应该用来说明这个概念。

答案 4 :(得分:0)

从表格视图属性编辑器中,将Selection值设置为No Selection或以编程方式执行。禁用每个子视图上的交互,但您想要操作的子视图除外。将indexPath行值作为标记传递给该子视图,也许。或者从UIView子类化子视图以存储indexPath信息。接下来,对该子视图实施点击手势,并在点击手势识别方法上执行您的愿望操作。希望这些能做你想做的事。