简体   繁体   中英

How to implement a tap gesture recognizer for multiple subviews with Swift

I have a tableView with 3 Static Cells, each cell contains a subview with labels displaying the desired text, what I want to accomplish is to have the orientation programmatically rotate from Portrait to Landscape when the user taps on any of the 3 subviews.

I got it working for the first subview. However, when I try to add the same Tap gesture recognizer to the other subviews it still only works for one subview. Please advise, what am I missing? Thanks for any input.

Portrait:

在此输入图像描述

Landscape

在此输入图像描述

Table View Controller code:

import UIKit

class SampleTableViewController: UITableViewController {

    @IBOutlet weak var newYorkViewWrapper: UIView!
    @IBOutlet weak var sanFranciscoViewWrapper: UIView!
    @IBOutlet weak var chicagoViewWrapper: UIView!

    //Vars
    let tapRec = UITapGestureRecognizer()


    override func viewDidLoad() {
        super.viewDidLoad()

        print("Sample view rendered.")


        //Tap gesture
        tapRec.addTarget(self, action: "tappedView")
        newYorkViewWrapper.addGestureRecognizer(tapRec)
        newYorkViewWrapper.userInteractionEnabled = true
        sanFranciscoViewWrapper.addGestureRecognizer(tapRec)
        sanFranciscoViewWrapper.userInteractionEnabled = true
        chicagoViewWrapper.addGestureRecognizer(tapRec)
        chicagoViewWrapper.userInteractionEnabled = true
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    //--------------------------------------------------------
    // MARK: Hide status bar
    //--------------------------------------------------------
    override func prefersStatusBarHidden() -> Bool {
        return true
    }

    func tappedView(){
        let value = UIInterfaceOrientation.LandscapeLeft.rawValue
        UIDevice.currentDevice().setValue(value, forKey: "orientation")
    }

    //--------------------------------------------------------
    // MARK: View Orientation method
    //--------------------------------------------------------
    override func shouldAutorotate() -> Bool {
        return true
    }


}

when I try to add the same Tap gesture recognizer to the other subviews it still only works for one subview

You've answered your own question beautifully. You can't do this:

    newYorkViewWrapper.addGestureRecognizer(tapRec)
    sanFranciscoViewWrapper.addGestureRecognizer(tapRec)
    chicagoViewWrapper.addGestureRecognizer(tapRec)

Instead, you must make three different tap gesture recognizers and add one to each view.

As Matt says, a gesture recognizer only works with a single view. The only way you can make a tap gesture recognizer work with multiple views would be to attach it to the superview, and then write extra code that figures out which of your subviews (if any) it hit. This is usually more trouble than it's worth, though, and you're better off simply creating a separate gesture recognizer for each view.

On case I've found where it is useful to attach a gesture recognizer to the superview is letting the user tap on a view who's position is being animated. Gesture recognizers don't handle position animation, so you have to do that yourself.

I resolved my own issue by defining 4 separate UITapGestureRecognizer() variables as shown below and then adding the appropriate gesture recognizer to the appropriate view.

//Vars
let tapRecForHistoryView = UITapGestureRecognizer()
let tapRecForMissionView = UITapGestureRecognizer()
let tapRecForServiceAreaView = UITapGestureRecognizer()
let tapRecForServiceAreaMapView = UITapGestureRecognizer()


override func viewDidLoad() {
        super.viewDidLoad()
        //Tap gesture
        tapRecForHistoryView.addTarget(self, action: "tappedView")
        tapRecForMissionView.addTarget(self, action: "tappedView")
        tapRecForServiceAreaView.addTarget(self, action: "tappedView")
        tapRecForServiceAreaMapView.addTarget(self, action: "tappedView")
        historyViewWrapper.addGestureRecognizer(tapRecForHistoryView)
        historyViewWrapper.userInteractionEnabled = true
        missionViewWrapper.addGestureRecognizer(tapRecForMissionView)
        missionViewWrapper.userInteractionEnabled = true
        serviceAreaViewWrapper.addGestureRecognizer(tapRecForServiceAreaView)
        serviceAreaViewWrapper.userInteractionEnabled = true
        serviceAreaMapWrapper.addGestureRecognizer(tapRecForServiceAreaMapView)
        serviceAreaMapWrapper.userInteractionEnabled = true
    }

//--------------------------------------------------------
// MARK: Local Methods
//--------------------------------------------------------
func tappedView(){
    let value = UIInterfaceOrientation.LandscapeLeft.rawValue
    UIDevice.currentDevice().setValue(value, forKey: "orientation")
}

I am now able to tap each individual view and the orientation will programmatically rotate from Portrait to Landscape.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM