Disable Long Press Back Button (Callout Menu)

Is it possible to disable the back navigation menu in iOS 14+?

It can be done by subclassing UIBarButtonItem. Setting the menu to nil on a UIBarButtonItem doesn't work, but you can override the menu property and prevent setting it in the first place.

class BackBarButtonItem: UIBarButtonItem {
@available(iOS 14.0, *)
override var menu: UIMenu? {
set {
// Don't set the menu here
// super.menu = menu
}
get {
return super.menu
}
}
}

Then you can configure the back button in your view controller the way you like, but using BackBarButtonItem instead of UIBarButtonItem.

let backButton = BackBarButtonItem(title: "BACK", style: .plain, target: nil, action: nil)
navigationItem.backBarButtonItem = backButton

This is preferred because you set the backBarButtonItem only once in your view controller's navigation item, and then whatever view controller it will be pushing, the pushed controller will show the back button automatically on the nav bar. If using leftBarButtonItem instead of backBarButtonItem, you will have to set it on every view controller that will be pushed.

Edit:

The back navigation menu that appears on long press is a property of UIBarButtonItem. The back button of a view controller can be customized by setting the navigationItem.backBarButtonItem property and by doing so we can control the menu. The only problem with this approach that I see is losing the localization (translation) of the "Back" string which the system button has.

If you want the disabled menu to be the default behaviour you can implement this in one place, in a UINavigationController subclass conforming to UINavigationControllerDelegate:

class NavigationController: UINavigationController, UINavigationControllerDelegate {
  init() {
    super.init(rootViewController: ViewController())
    delegate = self
  }
   
  func navigationController(_ navigationController: UINavigationController,
                 willShow viewController: UIViewController, animated: Bool) {
    let backButton = BackBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
viewController.navigationItem.backBarButtonItem = backButton
  }
}

Use `navigationItem.backButtonDisplayMode = .minimal` with a custom back button image

Okay, I finally figured out all the problems I was having.

Basically, this code works just fine:

override func viewDidLoad() {
super.viewDidLoad()

let backImage = UIImage(named: "backImage")?.withRenderingMode(.alwaysOriginal)
navigationController?.navigationBar.backIndicatorImage = backImage
navigationController?.navigationBar.backIndicatorTransitionMaskImage = backImage

navigationItem.backButtonDisplayMode = .minimal
}

But I was having problems with the swipe back gesture not working anymore. Turns out, that's a simulator bug, works fine on device. Then there was the problems that the custom back button image didn't actually show up in my view, because of this:

let appearance = UINavigationBarAppearance()
appearance.backgroundColor = .pageBackground
appearance.titleTextAttributes = [.foregroundColor: UIColor.abbey]
appearance.shadowColor = .clear

navigationBar.scrollEdgeAppearance = appearance
navigationBar.standardAppearance = appearance
navigationBar.compactAppearance = appearance

As soon as you set a custom appearance, that completely wipes away the custom back button image. Simple fix, just set these things directly on the navigationBar without involving the appearance.

And now it all works!

How to disable long-click which opens the Android top menu bar with copy/paste/etc. buttons in Cordova Crosswalk apps?

Looks like this is a bug in Crosswalk, and a PR which fixes it has been submitted:

https://github.com/crosswalk-project/crosswalk/pull/3193

Disabling the context menu on long taps on Android

This should work on 1.6 or later (if I recall correctly). I don't believe there's a workaround for 1.5 or earlier.

<!DOCTYPE html>
<html>
<head>
<script>
function absorbEvent_(event) {
var e = event || window.event;
e.preventDefault && e.preventDefault();
e.stopPropagation && e.stopPropagation();
e.cancelBubble = true;
e.returnValue = false;
return false;
}

function preventLongPressMenu(node) {
node.ontouchstart = absorbEvent_;
node.ontouchmove = absorbEvent_;
node.ontouchend = absorbEvent_;
node.ontouchcancel = absorbEvent_;
}

function init() {
preventLongPressMenu(document.getElementById('theimage'));
}
</script>
</head>
<body onload="init()">
<img id="theimage" src="http://www.google.com/logos/arthurboyd2010-hp.jpg" width="400">
</body>
</html>

Prevent iOS Webkit Long Press on Link

I think you can disable that popup by setting the CSS -webkit-touch-callout property to none on the link. You would do this by editing the HTML or CSS file you're loading, not using Objective-C.

Preventing default context menu on longpress / longclick in mobile Safari (iPad / iPhone)

Thanks to JDandChips for pointing me to the solution. It works perfectly in combination with the longclick plugin. For documentation sake I'll post my own answer to show what I did.

HTML:

<script type="text/javascript"
src="https://raw.github.com/pisi/Longclick/master/jquery.longclick-min.js"></script>

<p><a href="http://www.google.com/">Longclick me!</a></p>

The Javascript already was OK:

function longClickHandler(e){
e.preventDefault();
$("body").append("<p>You longclicked. Nice!</p>");
}

$("p a").longclick(250, longClickHandler);

The fix was to add these rules to the style sheet:

body { -webkit-touch-callout: none !important; }
a { -webkit-user-select: none !important; }

Disabled context menu example.

Mobile Web - Disable long-touch/taphold text selection

Reference:

jsFiddle Demo with Plugin

The above jsFiddle Demo I made uses a Plugin to allow you to prevent any block of text from being selected in Android or iOS devices (along with desktop browsers too).

It's easy to use and here is the sample markup once the jQuery plugin is installed.

Sample HTML:

<p class="notSelectable">This text is not selectable</p>

<p> This text is selectable</p>

Sample jQuery:

$(document).ready(function(){

$('.notSelectable').disableSelection();

});

Plugin code:

$.fn.extend({
disableSelection: function() {
this.each(function() {
this.onselectstart = function() {
return false;
};
this.unselectable = "on";
$(this).css('-moz-user-select', 'none');
$(this).css('-webkit-user-select', 'none');
});
return this;
}
});

Per your message comment: I still need to be able to trigger events (notably, touchstart, touchmove, and touchend) on the elements.

I would simply would use a wrapper that is not affected by this plugin, yet it's text-contents are protected using this plugin.

To allow interaction with a link in a block of text, you can use span tags for all but the link and add class name .notSelected for those span tags only, thus preserving selection and interaction of the anchors link.

Status Update: This updated jsFiddle confirms you concern that perhaps other functions may not work when text-selection is disabled. Shown in this updated jsFiddle is jQuery Click Event listener that will fire a Browser Alert for when the Bold Text is clicked on, even if that Bold Text is not text-selectable.



Related Topics



Leave a reply



Submit