I have some key events, that correspond to buttons also. What property/method to I have to set/call for a button to look depressed (change state?) for say half a second?
The way I solved this is I set the NSButton to a type of 'Push On Push Off' and then used the following code in my key event handler:
NSButton *button = [self.superview viewWithTag:event.keyCode];
if (button != nil && button.state == NSOffState) {
[button performClick:event];
[button performSelector:#selector(performClick:) withObject:event afterDelay:0.5];
}
This will highlight the button as if the user had clicked on it, and then it will click on it again in half a second.
I believe the button cell's -setHighlighted: method controls whether the button looks pressed or not. You may also need to call -setNeedsDisplay: on the button after changing it, and it's possible that the button will change its cell's highlighted state by itself, so I'm afraid you may need to fiddle around to get this working.
(I have to admit, though, that I'm not entirely certain about any of this.)
Related
in my Navigation Controller I need to temporarily disable the back button. I know that it can be hidden using the following or something similar:
[self.navigationController.navigationItem setHidesBackButton:YES animated:YES];
But that is not what I need, instead I want the back button to be greyed out and non-responsive to user touch events. Is their a way to achieve this without replacing the default back button?
Thanks in advance!
To disable the back button, these commands would make it do what you want it to do:
Enable:
self.navigationController.navigationBar.userInteractionEnabled = YES;
self.navigationController.navigationBar.tintColor = [UIColor blueColor];
Disabled:
self.navigationController.navigationBar.userInteractionEnabled = NO;
self.navigationController.navigationBar.tintColor = [UIColor lightGrayColor];
Update:
As of iOS 7, there's also a swipe that you'll want to disable on the UINavigationBar.
// You wrap it an 'if' statement so it doesn't crash
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
// disable the interactivePopGestureRecognizer
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
This hides the back button, so it becomes unreachable for the user. And it disables the swipe gesture.
[self.navigationItem setHidesBackButton:YES animated:YES];
Swift:
navigationItem.setHidesBackButton(true, animated: true)
See more info in Apple's documentation.
I know this is quite old but I had this problem too.
In my case in one scenario I had to disable the back button and in another one I had to disable all navigation buttons. my solution was disabling the navigation bar in total in both scenarios:
self.navigationController.view.userInteractionEnabled = NO;
This won't show the buttons as disabled but will prevent touches.
Hope this will help
I believe that following should help:
self.navigationController.navigationItem.backBarButtonItem.enabled = NO;
UPDATE
Sorry guys, my belief didn't come true.
It seems that property backBarButtonItem is designed only for setting custom title or image for Back Button.
From documentation:
If you want to specify a custom image or title for the back button,
you can assign a custom bar button item (with your custom title or
image) to this property instead. When configuring your bar button
item, do not assign a custom view to it; the navigation item ignores
custom views in the back bar button anyway.
The default value of this property is nil.
Unfortunately I didn't find any way of disabling back button with saving its native look and behaviour, because any time when I try to set custom UIBarButtonItem into navigationItem.backBarButtonItem property - it gets updated with appropriate native back button style and it always has enabled == YES.
I think this is done by Apple for a reason because we basically shouldn't force the user to stay on a detail screen and disable him from going back.
Also, in iOS7 and later user always can use swipe-from-left-edge gesture (if you don't disable it) to go back.
The only one ugly thing that I can recommend is to create a custom UIBarButtonItem and set it into leftBarButtonItem with 'Back' title, target and selector which will pop your viewController. By default it will substitute native back button.
Then you can disable it as usual using navigationItem.leftBarButtonItem.enabled = NO.
Unfortunately it will not look and act (in case of title updating depending on available space) as native back button :(
Just set a disabled back button on the navigation item of the previous view controller. Don't try to disable your custom back button if you already had one, won't work. Just set a new one which is disabled. You can reach the previous navigation item through the UINavigationBar.backItem property.
// set disabled back button
let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItem.Style.plain, target: nil, action: nil)
backButton.isEnabled = false
navigationController?.navigationBar.backItem?.backBarButtonItem = backButton
// disable pop gesture
navigationController?.interactivePopGestureRecognizer?.isEnabled = false
As the titles says i wonder if it is possible to detect if the mouse button is down. I tried putting this code in my app delegate.m but with no success.
- (void)mouseDown:(NSEvent *)theEvent
{
NSLog(#"hello world!");
}
A quick google search showed me that this method only works inside of NSWindows. However, there most be some way to detect if mouse position is pressed, and if so; how can i do it?
You can use NSEvent addGlobalMonitorForEventsMatchingMask:
define in your control:
id mouseEventMonitor;
-(id)init{
mouseEventMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask)
handler:^(NSEvent *event){
NSLog(#"theEvent->%#",event);
//here you will receive the all mouse DOWN events
if (event.modifierFlags & NSCommandKeyMask)
{
NSLog(#"theEvent1->%#",event);
}else{
NSLog(#"theEvent2->%#",event);
}
}];
return self;
}
Cocoa Event Monitors are the way to go.
You can use them to track pretty much every kind of mouse event outside of your view hierarchy.
Check out the documentation in the Cocoa Event Handling Guide for information on how to use them and similar topics here on SO like
In what way a view or a window could know that mouseDown outside itself in Xcode?
How do i detect keystrokes using objective c?
Although you mention mouseDown in your question and have accepted an answer that describes how to set up a monitor, as far as I can tell from the rest of the question, you don't actually need an event that fires when the mouse button is pressed, but instead just want to check if a mouse button is currently pressed.
NSEvent has a class property you can use for this:
[NSEvent pressedMouseButtons]
This returns the indices of the currently pressed mouse buttons:
A return value of 1 << 0 corresponds to the left mouse button, 1 << 1 corresponds to the right mouse button, 1<< n, n >=2 correspond to other mouse buttons.
I put this code to confirm my suspicion
if (self.Ihatethis.selected) {
self.Ilikethis.enabled=!self.Ilikethis.enabled;
return;
}
So basically one button will toggle enable state for the other.
Now I already have:
[self.Ilikethis setImage:[UIImage imageNamed:#"button-recommend-active"] forState:UIControlStateSelected];
[self.Ihatethis setImage:[UIImage imageNamed:#"button-dislike-active"] forState:UIControlStateSelected];
somewhere in viewDidLoad.
The result is when button is disabled, it looks like the normal button except that it's dimmed.
When button is disabled, I want the selected button to keep looking like it's selected state.
So how would I do so?
Don't disable your button. Make its userInteraction set to NO
btn.userInteractionEnabled = NO;
Hope it helps you..
I would like to make my button pop up when i actually press the button for more than one secs. When it pops up, the letter or word in the button should appear with it... Any guidance on how to do this? Would really appreciate any help provided...
This is easy, What you need to do is implemenent longtap on that Button. UILongPressGestureRecognizer. So what that gesture takes over, you can animate the CGSizeMake to make the frame grow bigger than what it is or you could use scale property to scale the button bigger.
Hope this is clear enough. Let me know if this works out for you...
UPDATE: Some code -
- (void)longPressHandler:(UILongPressGestureRecognizer *)gesture
{
UIButton *btn;
if(gesture.state == UIGestureRecognizerStateBegan)
{
btn = (UIButton *)gesture.view;
[btn setFrame:CGRectMake(btn.frame.origin.x, btn.frame.origin.y, 150, 70)];
}
return;
}
FYI, LongTap gesture has different states UIGestureRecognizerStateBegan, UIGestureRecognizerStateChanged, UIGestureRecognizerStateEnded. There are some more but these are the main.
I have programmed a Quiz in Xcode where I've created UIButtons programmatically displaying the answer to a question. When the user clicks the button the next question is loaded and the buttons position i shuffled to not make the right answer in the same place for each question (the right answer is however under the same UIButton for every question.)
This is how I create my buttons:
if (self.buttonRightAnswer == nil)
{
self.buttonRightAnswer = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.buttonRightAnswer addTarget:self action:#selector(rightAnswer) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:self.buttonRightAnswer];
}
self.buttonRightAnswer.frame = CGRectMake(20.0, [[randomPositionArray objectAtIndex:0] floatValue], 280.0, 40.0);
[self.buttonRightAnswer setTitle:[[self.quiz.arrayWithQuestions objectAtIndex:questionNr - 1]valueForKey:#"RightAnswer"] forState:UIControlStateNormal];
When the user clicks the right an answer the next question loads. Here it's a problem. The next question loads with the same method only shuffled positions and the animation of the press-down of the button is drawn after the buttons been moved resulting in the user seeing where the right answer is now.
How can I wait for the animation before moving the buttons?
I could solve this by having the buttons stay in one place, shuffling out the questions over the buttons and comparing the users answer with the right answer.. but this requires a hell of a lot more code.
You can use some of shit-code and insert some kind of 'sleep' before next shuffling buttons
Before you create the buttons againg (after a question was answered), you can add something like (if you use differen images for button states)
-(void)waitUntilButtonDeselected
{
bool selected = YES;
while (selected)
{
bool selected = (self.buttonRightAnswer.currentBackgroundImage == UIImageOfNotSelectedButton);
}
}
The idea here is to check if the image of the button corresponds to not selected button.
Typically when using a UIButton, events are triggered on UIControlEventTouchUpInside, or at the end of the touch.
You're triggering it on the touch down which is causing issues with the animation you want to happen.
It might be simpler for you to switch to using UIControlEventTouchUpInside instead of UIControlEventTouchDown since this should solve your problem and be more consistent with other iPhone apps.