Is there a tooltip property for a UIButton instance that will display text when the mouse hovers over the button?
UIButton is an iOS class.
There is no mouse.
As there is no mouse in IOS, there is no "mouse over" or tooltip property of UIButton.
But you could try to simulate one using event handling.
If user touches the button and holds his finger in, a text is shown.
If user touches up he likes to select the button.
If user does move outside the button and ends the touch there, the tooltip is hided.
Check UIControlEvent for UIButton, i.e. "Touch Up Inside" "Touch Drag Enter" "TOuch Drag Exit"
That is true that you don't have mouse in iOS, but now that we have Catalyst which let you run ios apps on macOS, we do have mouse.
For any UIView you can use :
addGestureRecognizer(UIHoverGestureRecognizer(target: self, action: #selector(hoverEvent(_:))))
and do what you want in the implementation such as :
#objc
func hoverEvent(_ sender: UIHoverGestureRecognizer? = nil) {
switch sender?.state {
case .began, .changed:
myButton.isHidden = false
case .ended, .cancelled, .failed, .possible:
myButton.isHidden = true
default:
break
}
}
Related
Context
I have an app that runs only from the macOS menubar. (The LSUIElement property in info.plist is set to YES).
Instead of a menu, this app shows an NSPopover when the menubar button is clicked. The popover holds an NSHostingView which has an extremely simple SwiftUI view:
struct PopoverContentView: View
{
#State private var color: CGColor = .white
var body: some View
{
ColorPicker(selection: $color) {
Text("Pick a Color:")
}
}
}
Problem
Clicking on the ColorPicker() does not open the macOS color picker window. The UI of the ColorPicker() button changes, to show the "selected" border state but the color-picker window never appears.
However, if I change LSUIElement to be NO and then make the app active by clicking its Dock icon (so that it takes over the menubar), THEN clicking on the ColorPicker() in the popover actually reveals the color-picker window.
Do you know of a way to force macOS to show the color-picker window for a background application?
The answer turned out to be simple. In the AppKit ViewController that opens the popover when the menubar button is clicked (PopoverController, for me), I simply did this:
extension PopoverController: NSPopoverDelegate
{
func popoverWillShow(_ notification: Notification)
{
NSApp.activate(ignoringOtherApps: true)
}
}
The ColorPicker now correctly shows the standard macOS system color panel on click.
I am currently writing a tvOS app. I've been detecting and overriding the menu button with tapRecognizer to switch between storyboards and other functions. My issue is when I am on my home screen and press menu it does not exit the app. Instead it remembers the last function I used when overriding the menu button and performs that function. Any thoughts on how to clear the tapRecognizer? Or a function that will exit the app?
I'm overriding the menu button with
in Storyboard1
tapRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(home)];
tapRecognizer.allowedPressTypes = #[[NSNumber numberWithInteger:UIPressTypeMenu]];
[self.view addGestureRecognizer:tapRecognizer];
in my home subroutine I send the user back to my home page storyboard. But from then on the menu button will not exit the app but send me back to storyboard1.
thanks,
SW
Instead of using your own gesture recognizer, override pressesBegan:
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
if(presses.first?.type == UIPressType.Menu) {
// handle event
} else {
// perform default action (in your case, exit)
super.pressesBegan(presses, withEvent: event)
}
}
If you are using UIGestureRecognizer instead of responding to presses, all you need to do is to disable the recognizer:
tapRecognizer.enabled = NO;
So if no recognizer with UIPressTypeMenu is listening, tvOS suspends the app and displays the home screen. (I've tested this)
You have to override 2 methods to prevent exiting app by pressing Menu button.
Here is ready-to-use template:
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
for press in presses {
switch press.type {
case .Menu:
break
default:
super.pressesBegan(presses, withEvent: event)
}
}
}
override func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
for press in presses {
switch press.type {
case .Menu:
//Do some staff there!
self.menuButtonPressed()
default:
super.pressesEnded(presses, withEvent: event)
}
}
}
If you overwrite the menu button, the app won't be accepted:
EDIT: You can overwrite, but the menu button has to work as a back button to homescreen from the entry point of the app.
10.1 Details
The Menu button on the Siri Remote does not behave as expected in your
app.
Specifically, when the user launches the app and taps the Menu button
on the Siri remote, the app does not exit to the Apple TV Home screen.
Next Steps
Please revise your app to ensure that the Siri remote buttons behave
as expected and comply with the Apple TV Human Interface Guidelines.
It may be help you...
it is swift code.
let menuPressRecognizer = UITapGestureRecognizer()
menuPressRecognizer.addTarget(self, action: #selector(YourViewController.menuButtonAction(_:)))
menuPressRecognizer.allowedPressTypes = [NSNumber(integer: UIPressType.Menu.hashValue)]
self.view.addGestureRecognizer(menuPressRecognizer)
As per Apple's documentation, for custom press handling, we should override all four of these methods-
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
This is the official documentation from XCode:
Generally, all responders which do custom press handling should
override all four of these methods.
Your responder will receive either pressesEnded:withEvent or pressesCancelled:withEvent: for each
press it is handling (those presses it received in pressesBegan:withEvent:).
pressesChanged:withEvent: will be invoked for presses that provide
an analog value
(like thumbsticks or analog push buttons)
*** You must handle cancelled presses to ensure correct behavior in
your application. Failure to
do so is very likely to lead to incorrect behavior or crashes.
SwiftUI Seekers:
I don't know how much this answer helps, but just adding available actions in SwiftUI.
YourAnyView
.onExitCommand(perform: {
print("onExitCommand")
})
.onMoveCommand { direction in
print("onMoveCommand", direction)
}
REF:
onmovecommand
onexitcommand
Does someone knows why in ElCapitan GM and Xcode 7 GM the popover appears outside of the view?
The popover is triggered by the "Button".
The picture below is a new project with no code written by me, jut a button.
Is it a bug or a new "feature"?
I just tried it, and it seems that you can't set the popover anchor in the Storyboard. Perhaps this is indeed a bug in the new release.
To display the popover programmatically, set the StoryboardID of your popover view controller, for example: "PopoverViewController". Below, it's implemented in the main view controller as a lazy var, so it's instantiated just once, the first time it's referenced.
Connect an IBAction from your button to the main view controller — here, a function called "displayPopover". The "guard let" statement makes sure the sender can be cast as an NSButton.
Then, just call:
presentViewController:asPopover...
lazy var popoverViewController: NSViewController = {
return self.storyboard!.instantiateControllerWithIdentifier("PopoverViewController")
as! NSViewController
}()
#IBAction func displayPopover(sender: AnyObject) {
guard let button = sender as? NSButton else {return}
self.presentViewController(popoverViewController, asPopoverRelativeToRect: button.frame, ofView: button, preferredEdge: NSRectEdge.MaxY, behavior: NSPopoverBehavior.Transient)
}
In my OS X app, using Interface Builder, I have a window that looks like this:
I'd like to add a button to the right-hand side, to achieve this:
If this is possible, how can I do it?
It is not possible to do with Interface Builder, however you can get it done with little bit of coding :
NSButton *closeButton = [window standardWindowButton:NSWindowCloseButton]; // Get the existing close button of the window. Check documentation for the other window buttons.
NSView *titleBarView = closeButton.superview; // Get the view that encloses that standard window buttons.
NSButton *myButton = …; // Create custom button to be added to the title bar.
myButton.frame = …; // Set the appropriate frame for your button. Use titleBarView.bounds to determine the bounding rect of the view that encloses the standard window buttons.
[titleBarView addSubview:myButton]; // Add the custom button to the title bar.
Swift 2.2 and Auto Layout, Create an "OK" button to the right of the title bar:
let myButton = NSButton()
myButton.title = "OK"
myButton.bezelStyle = .RoundedBezelStyle
let titleBarView = window!.standardWindowButton(.CloseButton)!.superview!
titleBarView.addSubview(myButton)
myButton.translatesAutoresizingMaskIntoConstraints = false
titleBarView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[myButton]-2-|", options: [], metrics: nil, views: ["myButton": myButton]))
titleBarView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-1-[myButton]-3-|", options: [], metrics: nil, views: ["myButton": myButton]))
With auto layout, you don't need to hard-code button's frame. And it is always on the right of the title bar even you resize the window.
I have a UIButton that is added to a UIImageView (it's a big chart)
The button appears nicely and I have the TouchUpInside attached to a delegate:
this.TouchUpInside += delegate { ShowPopOver (); }
This event is never fired though. The button has UserInteractionEnabled=true
I add the button to the top of the view:
UIButton b = new DataPointButton (frame);
_parentView.AddSubview (b);
_parentView.BringSubviewToFront(b);
Is there anything I need to do to enable touches on code created buttons?
In UIView the UserIntaractionEnabled property is set to YES by default when there is a button on it. Howewer, in case of UIImageView it is NO by default.
Set it to YES to make buttons work:
myUIImageView.userInteractionEnabled = YES;