This is Slideout menu using SWRevealController Which run perfectly but can swipe to open but doesn't swipe to close the menu
After adding the library I did few changes but I did know where is the issue.
This is the code in the main viewcontroller
#IBOutlet weak var menuButton:UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.revealViewController().delegate = self
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
self.revealViewController().delegate = self
var swl = self.revealViewController()
if swl != nil
{
swl.panGestureRecognizer()
swl.tapGestureRecognizer()
}
}
#IBAction func but_back(sender: AnyObject) {
self.navigationController?.interactivePopGestureRecognizer!.delegate = self
self.navigationItem.leftBarButtonItem?.target=self.revealViewController()
self.navigationItem.leftBarButtonItem?.action=Selector("revealToggle:")
self.revealViewController().revealToggle(sender)
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
func revealController(revealController: SWRevealViewController!, willMoveToPosition position: FrontViewPosition)
{
if position == FrontViewPosition.Left // if it not statisfy try this --> if revealController.frontViewPosition == FrontViewPosition.Left
{
self.view.userInteractionEnabled = true
revealController.panGestureRecognizer().enabled=true
}
else
{
self.view.userInteractionEnabled = false
revealController.panGestureRecognizer().enabled=false
}
}
It appears you are disabling the pan gesture recognizer, along with disabling user interaction on your view, when the the reveal view controller front position is not at the left position in your delegate method implementation for revealController:willMoveToPosition: from SWRevealViewControllerDelegate. Therefore, the reveal view controller can only move to a single position. You can change that code to allow the additional positions that you require.
For example, if you comment out this code
func revealController(revealController: SWRevealViewController!, willMoveToPosition position: FrontViewPosition)
{
if position == FrontViewPosition.Left // if it not statisfy try this --> if revealController.frontViewPosition == FrontViewPosition.Left
{
self.view.userInteractionEnabled = true
revealController.panGestureRecognizer().enabled=true
}
else
{
self.view.userInteractionEnabled = false
revealController.panGestureRecognizer().enabled=false
}
}
that should prevent the disabling of the pan gesture unnecessarily.
If you need to disable the reveal view controller pan gesture, I'd suggest using the delegate method revealControllerPanGestureShouldBegin: from SWRevealViewControllerDelegate.
Related
I have already implemented the delegate line, but methods doesnt get called.
My view is a MAP, and the gesture on map doesnt work either.
override func viewDidLoad() {
super.viewDidLoad()
if self.revealViewController() != nil {
menuBtn.target = self.revealViewController()
self.revealViewController().delegate = self
menuBtn.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
}
func revealController(revealController: SWRevealViewController, willMoveToPosition position: FrontViewPosition)
{
if revealController.frontViewPosition == FrontViewPosition.left // if it not statisfy try this --> if revealController.frontViewPosition == FrontViewPosition.Left
{
self.Map.isUserInteractionEnabled = false
}
else
{
self.Map.isUserInteractionEnabled = true
}
}
func revealController(revealController: SWRevealViewController, didMoveToPosition position: FrontViewPosition)
{
if revealController.frontViewPosition == FrontViewPosition.left // if it not statisfy try this --> if revealController.frontViewPosition == FrontViewPosition.Left
{
self.Map.isUserInteractionEnabled = false
}
else
{
self.Map.isUserInteractionEnabled = true
}
}
none of these funcs get called... there are any change on new lib?
had to implement:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.revealViewController().view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
self.revealViewController().frontViewController.revealViewController().tapGestureRecognizer()
self.revealViewController().frontViewController.view.isUserInteractionEnabled = false
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.revealViewController().frontViewController.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
self.revealViewController().frontViewController.view.isUserInteractionEnabled = true
}
on my menu view controller
say, I have a button lying under UITableView, how can I click the button through the UITableViewCell but do not trigger the cell click event:
The reason I put the button behind the tableview is that I want to see and click the button under the cell whose color set to be clear, and when I scroll the table, the button can be covered by cell which is not with clear color
I created a sample project and got it working:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let tap = UITapGestureRecognizer(target: self, action: #selector(TableViewVC.handleTap))
tap.numberOfTapsRequired = 1
self.view.addGestureRecognizer(tap)
}
func handleTap(touch: UITapGestureRecognizer) {
let touchPoint = touch.locationInView(self.view)
let isPointInFrame = CGRectContainsPoint(button.frame, touchPoint)
print(isPointInFrame)
if isPointInFrame == true {
print("button pressed")
}
}
To check of button is really being pressed we need to use long tap gesture:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let tap = UILongPressGestureRecognizer(target: self, action: #selector(TableViewVC.handleTap))
tap.minimumPressDuration = 0.01
self.view.addGestureRecognizer(tap)
}
func handleTap(touch: UILongPressGestureRecognizer) {
let touchPoint = touch.locationInView(self.view)
print(" pressed")
if touch.state == .Began {
let isPointInFrame = CGRectContainsPoint(button.frame, touchPoint)
print(isPointInFrame)
if isPointInFrame == true {
print("button pressed")
button.backgroundColor = UIColor.lightGrayColor()
}
}else if touch.state == .Ended {
button.backgroundColor = UIColor.whiteColor()
}
}
Get the touch point on the main view. Then use following method to check the touch point lies inside the button frame or not.
bool CGRectContainsPoint(CGRect rect, CGPoint point)
You can write your custom view to touch button or special view behind the topview
class MyView: UIView {
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
for subview in self.subviews {
if subview is UIButton {
let subviewPoint = self.convertPoint(point, toView: subview)
if subview.hitTest(subviewPoint, withEvent: event) != nil { // if touch inside button view, return button to handle event
return subview
}
}
}
// if not inside button return nomal action
return super.hitTest(point, withEvent: event)
}
}
Then set your controller view to custom MyView class
The default behavior while a collection view is mid-scroll:
tap #1: stops the scrolling
tap #2: triggers didSelectItemAtIndexPath
What I want while a collection view is mid-scroll:
tap #1: triggers didSelectItemAtIndexPath
What would be a clean, correct approach to achieve this? FWIW, I realize this might be unexpected behavior.
I think the best approach is to use the UICollectionView addGestureRecognizer to add a touch gesture recognizer, then process the touch gesture (e.g. get the touch location in the collection view, use that to get the indexPath of the item that was touched, then call the collectionView.didSelectItemAtIndexPath yourself). As for the scrolling, you could use the UISrollViewDelegate methods to disable user interaction on the collection view once the scroll starts, then re-enable user interaction on the collection view once the scrolling stops and/or in the viewDidDisappear view controller function.
Like this:
public class MyViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
var collectionViewTap:UITapGestureRecognizer?
override public func viewDidLoad() {
collectionViewTap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
self.view.addGestureRecognizer(collectionViewTap!)
}
override public func viewDidDisappear(animated: Bool) {
collectionView.userInteractionEnabled = true
}
func handleTap (sender:UITapGestureRecognizer) {
let touchPoint = sender.locationOfTouch(0, inView: collectionView)
let indexPath = collectionView.indexPathForItemAtPoint(touchPoint)
if (indexPath != nil) {
collectionView(collectionView, didSelectItemAtIndexPath: indexPath!)
}
}
public func scrollViewWillBeginDragging(scrollView: UIScrollView) {
collectionView.userInteractionEnabled = false
}
public func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
collectionView.userInteractionEnabled = true
}
}
In your initializer for the collection view, add an additional target for the pan gesture
self.panGestureRecognizer.addTarget(self, action: #selector(allowSelectionOfItemDuringScroll(_:)))
Then, you can implement it like this:
#objc private func allowSelectionOfItemDuringScroll(_ sender: UIPanGestureRecognizer) {
let yTranslation = sender.translation(in: self).y
var isScrolling: Bool {
if sender.state == .began {
return false
}
if isDragging && isDecelerating {
return false
}
return isDragging || isDecelerating
}
if yTranslation == 0 && isScrolling {
let selectionPoint = sender.translation(in: self)
if let index = indexPathForItem(at: selectionPoint) {
self.delegate?.collectionView?(self, didSelectItemAt: index)
}
}
I tried calling tabBarController!.tabBar.hidden = true in viewDidLoad() and it hides the TabBar. However, I tried to set tap gesture and hide the bar on Tap. The parent viewController that has ScrollView inside it with subview (that is connected with IBOutlet as myView)
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
myView.addGestureRecognizer(tap)
}
func handleTap(sender: UITapGestureRecognizer? = nil) {
print("A") // logs successfully
if TabBarHidden == false {
print("B") // logs successfully
//I tried:
tabBarController?.tabBar.hidden = true
// I also tried
tabBarController?.tabBar.alpha = 0
tabBarController?.tabBar.frame.origin.x += 50
hidesBottomBarWhenPushed = true
} else {
...
TabBarHidden = false
}
}
hidden does work when I call it in viewDidLoad as I said, but not if I call in tap gesture function. What may be the problem? What am I missing?
this code totally works for me:
class ViewController: UIViewController {
var tabBarHidden: Bool = false {
didSet {
tabBarController?.tabBar.hidden = tabBarHidden
}
}
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapGestureRecognized(_:)))
view.addGestureRecognizer(tapGestureRecognizer)
}
func tapGestureRecognized(sender: UITapGestureRecognizer) {
tabBarHidden = !tabBarHidden
}
}
I have View controller with embedded SWRevealViewController I've added code below to disable any interaction while the menu on use.
The viewcontroller is embeded with tableview.
How to make menu disappears when users tap on the view-controller as the slack app "When the menu is on use and you tap on the chat the menu disappears"
class Feed: UIViewController,SWRevealViewControllerDelegate {
#IBOutlet weak var menuButton:UIBarButtonItem!
#IBOutlet weak var menuButton:UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.revealViewController().delegate = self
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
fetchMessages()
}
func revealController(revealController: SWRevealViewController!, willMoveToPosition position: FrontViewPosition)
{
if position == FrontViewPosition.Left // if it not statisfy try this --> if revealController.frontViewPosition == FrontViewPosition.Left
{
self.view.userInteractionEnabled = true
}
else
{
self.view.userInteractionEnabled = false
}
func revealController(revealController: SWRevealViewController!, didMoveToPosition position: FrontViewPosition)
{
if position == FrontViewPosition.Left // if it not statisfy try this --> if revealController.frontViewPosition == FrontViewPosition.Left
{
self.view.userInteractionEnabled = true
}
else
{
self.view.userInteractionEnabled = false
}
}
}
//set the delegate in your view controller class
class FeedVC: UIViewController,SWRevealViewControllerDelegate,UIGestureRecognizerDelegate
override func viewDidLoad() {
super.viewDidLoad()
self.revealViewController().delegate = self
var swl=self.revealViewController()
if swl != nil
{
swl.panGestureRecognizer()
swl.tapGestureRecognizer()
}
}
// create the left bar button action
#IBAction func but_back(sender: AnyObject) {
self.navigationController?.interactivePopGestureRecognizer.delegate=self
self.navigationItem.leftBarButtonItem?.target=self.revealViewController()
self.navigationItem.leftBarButtonItem?.action=Selector("revealToggle:")
self.revealViewController().revealToggle(sender)
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
//set the delegate method for SWLReval
func revealController(revealController: SWRevealViewController!, willMoveToPosition position: FrontViewPosition)
{
if position == FrontViewPosition.Left // if it not statisfy try this --> if revealController.frontViewPosition == FrontViewPosition.Left
{
self.view.userInteractionEnabled = true
revealController.panGestureRecognizer().enabled=true
}
else
{
self.view.userInteractionEnabled = false
revealController.panGestureRecognizer().enabled=false
}
}
the updated code is available in this link , download the project in here