Bubu
Bubu

Reputation: 669

Swift - detect touched coordinate of UIView

I am trying to make a custom jump bar which can be attached to UITableView.

Jumpbar picture

What I want to achieve now is if user touches A and slides through Z, I want print out A, B, C, D..., Z. Currently, it only prints A, A, A...A. Is there anyway I can achieve it?

Each letter is UIButton subview of UIView.

class TableViewJumpBar{
let tableView: UITableView
let view: UIView
let jumpBar: UIView!
private var jumpIndexes: [Character]

init(tableView: UITableView, view: UIView){
    self.view = view

    self.tableView = tableView
    jumpBar = UIView(frame: .zero)
    jumpBar.backgroundColor = UIColor.gray

    let aScalars = "A".unicodeScalars
    let aCode = aScalars[aScalars.startIndex].value
    jumpIndexes = (0..<26).map {
        i in Character(UnicodeScalar(aCode + i)!)
    }
}

func setFrame(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat){
    guard jumpIndexes.count > 0 else{
        print("Jump indexes cannot be empty")
        return
    }

    //Remove jumpbar and remove all subviews
    jumpBar.removeFromSuperview()
    for subView in jumpBar.subviews{
        subView.removeFromSuperview()
    }

    jumpBar.frame = CGRect(x: x, y: y, width: width, height: height)

    let height = height/CGFloat(jumpIndexes.count)
    for i in 0..<jumpIndexes.count{
        let indexButton = UIButton(frame: CGRect(x:CGFloat(0.0), y: CGFloat(i)*height, width: width, height: height))
        indexButton.setTitle(String(jumpIndexes[i]), for: .normal)
        indexButton.addTarget(self, action: #selector(jumpIndexButtonTouched(_:)), for: .allEvents)
        jumpBar.addSubview(indexButton)
    }

    self.view.addSubview(jumpBar)
}

///Touch has been begun
@objc private func jumpIndexButtonTouched(_ sender: UIButton!){
    print(sender.titleLabel?.text)
}

Upvotes: 1

Views: 371

Answers (1)

Sergey Hleb
Sergey Hleb

Reputation: 172

this code works and print start and finish characters.

class ViewController: UIViewController {

    @IBOutlet weak var myTableView: UITableView!
    @IBOutlet weak var myView: UIView!
    var startChar = ""
    var finishChar = ""


    override func viewDidLoad() {
        super.viewDidLoad()
        let table = TableViewJumpBar(tableView: myTableView, view: myView)
        table.setFrame(x: 0, y: 0, width: 100, height: self.view.frame.size.height)
        print(myView.subviews[0].subviews)
        setPanGesture()
    }

    func setPanGesture() {
        let pan = UIPanGestureRecognizer(target: self, action: #selector(panRecognized))
        self.myView.addGestureRecognizer(pan)
    }

    @objc func panRecognized(sender: UIPanGestureRecognizer) {
        let location = sender.location(in: myView)
        if sender.state == .began {
            for button in myView.subviews[0].subviews {
                if let button = button as? UIButton, button.frame.contains(location), let startCharacter = button.titleLabel?.text {
                    self.startChar = startCharacter
                }
            }
        } else if sender.state == .ended {
            for button in myView.subviews[0].subviews {
                if let button = button as? UIButton, button.frame.contains(location), let finishCharacter = button.titleLabel?.text {
                    self.finishChar = finishCharacter
                }
            }
            print("start with \(startChar), finish with \(finishChar)")
        }
    }

} 

In your code I delete Button action. you can use labels instead Buttons.

class TableViewJumpBar {
    let tableView: UITableView
    let view: UIView
    let jumpBar: UIView!
    private var jumpIndexes: [Character]

    init(tableView: UITableView, view: UIView){
        self.view = view

        self.tableView = tableView
        jumpBar = UIView(frame: .zero)
        jumpBar.backgroundColor = UIColor.gray

        let aScalars = "A".unicodeScalars
        let aCode = aScalars[aScalars.startIndex].value
        jumpIndexes = (0..<26).map {
            i in Character(UnicodeScalar(aCode + i)!)
        }
    }

    func setFrame(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat){
        guard jumpIndexes.count > 0 else{
            print("Jump indexes cannot be empty")
            return
        }
        jumpBar.removeFromSuperview()
        for subView in jumpBar.subviews{
            subView.removeFromSuperview()
        }

        jumpBar.frame = CGRect(x: x, y: y, width: width, height: height)

        let height = height/CGFloat(jumpIndexes.count)
        for i in 0..<jumpIndexes.count{
            let indexButton = UIButton(frame: CGRect(x:CGFloat(0.0), y: CGFloat(i)*height, width: width, height: height))
            indexButton.setTitle(String(jumpIndexes[i]), for: .normal)
            jumpBar.addSubview(indexButton)
        }
        self.view.addSubview(jumpBar)
    }

}   

Some output results:
ScreenShot

Upvotes: 2

Related Questions