Подтвердить что ты не робот

IOS увеличит зону касания для UIButton в TableViewCell

У меня есть UIButton в моем UITableViewCell

Я сделал подкласс UIButton переопределить функцию pointInside:

var touchMargin:CGFloat = 20.0

override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
    let extendedArea = CGRectInset(self.bounds, -touchMargin, -touchMargin)
    return CGRectContainsPoint(extendedArea, point)
}

Однако область касания не увеличивается.
Я прикасаюсь к ячейке таблицы, если слегка коснувшись UIButton.

Не работает ли этот код из-за того, что кнопка помещается в ячейку?
Как я могу исправить?

4b9b3361

Ответ 1

Swift 3

//
//  ViewController.swift
//  test
//
//  Created by David Seek on 9/29/16.
//  Copyright © 2016 David Seek. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = MyButton(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
        button.backgroundColor = UIColor.white
        button.addedTouchArea = 50 // any value you want
        button.addTarget(self, action:#selector(self.action), for: .touchUpInside)
        self.view.addSubview(button)
    }

    func action() {
        print("touched")
    }

}

class MyButton: UIButton {
    var addedTouchArea = CGFloat(0)

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {

        let newBound = CGRect(
            x: self.bounds.origin.x - addedTouchArea,
            y: self.bounds.origin.y - addedTouchArea,
            width: self.bounds.width + 2 * addedTouchArea,
            height: self.bounds.width + 2 * addedTouchArea
        )
        return newBound.contains(point)
    }
}

Вы создаете UIButton размером 100x100 и .addedTouchArea, у вас есть UIButton - все еще оптический размер 100x100, но с областью касания 150x150.

Swift 2.X

class MyButton: UIButton {
    var addedTouchArea = CGFloat(0)

    override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {

        let newBound = CGRect(
            x: self.bounds.origin.x - addedTouchArea,
            y: self.bounds.origin.y - addedTouchArea,
            width: self.bounds.width + 2 * addedTouchArea,
            height: self.bounds.width + 2 * addedTouchArea
        )
        return newBound.contains(point)
    }
}

InterfaceBuilder

Если вы установили кнопку с помощью InterfaceBuilder, примените наш подкласс UIButton к вашей кнопке.

введите описание изображения здесь

Затем установите выход на кнопку, т.е. named buttonXY. И установите buttonXY.addedTouchArea = 50 в пределах viewDidLoad, f.e.

UITableViewCell

Поскольку вы запрашиваете UITableViewCell. Он работает точно так же.

В вашем классе ViewController:

extension ViewController: UITableViewDelegate, UITableViewDataSource {

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

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell") as! TableViewCell
        cell.selectionStyle = UITableViewCellSelectionStyle.none

        cell.myButton.addedTouchArea = 50 // any value you want
        tableView.rowHeight = 200

        return cell
    }
}

В вашем классе Cell:

class TableViewCell: UITableViewCell {

    @IBOutlet weak var myButton: MyButton!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    @IBAction func myButtonAction(_ sender: AnyObject) {
        print("touched")
    }
}

Единственное, о чем вы должны остерегаться: выход был установлен как выход UIButton, даже если я объявил его подклассом MyButton в InterfaceBuilder. Я должен был вручную переключить розетку на MyButton! @IBOutlet weak var myButton: MyButton!

Ответ 2

вы должны переопределить hitTest в представлении, которое вы хотите увеличить.

например.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (!self.isUserInteractionEnabled || self.isHidden || self.alpha <= 0.01) {
        return nil;
    }
    CGRect touchRect = CGRectInset(self.bounds, -10, -10);
    if (CGRectContainsPoint(touchRect, point)) {
        //TODO!? check supviews
        return self;
    }
    return nil;
}

Ответ 3

Сначала вам нужно создать подкласс UIButton:

class ButtonWithTouchSize: UIButton {

    var touchAreaPadding: UIEdgeInsets? = nil

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        if let inset = touchAreaPadding {
            let origin = CGPoint(x: 0 - inset.left, y: 0 - inset.top)
            let size = CGSize(width: inset.left + bounds.width + inset.right,
                              height: inset.top + bounds.height + inset.bottom)
            let rect = CGRect(origin: origin, size: size)
            return rect.contains(point)
        } else { 
            return super.point(inside: point, with: event)
        }
    }
}

Если вы помещаете экземпляр ButtonWithTouchSize непосредственно в контентный просмотр UITableViewCell, вы его получите. Но если вы завернете этот экземпляр в какой-либо контейнер, который находится в UITableViewCell contentView, ваш должен также переопределить его метод (внутри: с):

class ContainerView: UIView {

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        return btn.point(inside: point, with: event)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        btn.frame = self.bounds
    }

    private let btn: ButtonWithTouchSize = ButtonWithTouchSize()

}

Итак, чтобы подвести итог... вы должны переопределить точку (внутри: с) для каждого супервизора, размер которой меньшеThanOrEqual для размера кнопки