I am trying to disable the user interaction to the view from one view. Below is my code.
DashboardViewControler.m
if([selectedTitle isEqual:#"VIEW"])
{
LatLongViewController * latview =[[LatLongViewController alloc]init];
latview.view.userInteractionEnabled = NO;
[self performSegueWithIdentifier:#"SWRevealViewController" sender:self];
}
In the latview, I have UITextField and UILabel. I want to disable the user interaction while above scenario matches. Any help will be appreciated.
latview.view.userInteractionEnabled = NO;
You can't do it with IBOutlet. All IBOutlet are
operated by ViewController. Here is my solution:
-Create new BOOL in LatLongViewController.h file:
#property BOOL editMode;
-In DashboardViewControler.m
if([selectedTitle isEqual:#"VIEW"])
{
LatLongViewController * latview =[[LatLongViewController alloc]init];
latview.editMode = NO;
[self performSegueWithIdentifier:#"SWRevealViewController" sender:self];
}
-In LatLongViewController.m
- (void)viewDidLoad {
if(_editMode == NO){
view.userInteractionEnabled = NO;
}
}
I think you should use textfield.enable = NO; if u have only one UITextField in this view.
Assuming your UIViewController owns the concerned views as properties:
yourTextfield.userInteractionEnabled = NO;
A beginners guide how to connect an view IBOutlet from Storyboard can be found here.
To disable user interaction for all subviews, iterate over them:
for (UIView *view in [self.view subviews]) {
view.userInteractionEnabled = NO;
}
I have 6 UIButtons set up in my UIView, all in the exact same location. What I want to do, is to swipe from left to right or right to left, in order to go through the buttons.
I have the UIGestures all set up and working on the view, I am just not sure the best way to go about cycling through these UIButtons.
I was thinking that it could be simple enough to tag each UIButton and HIDE all but one, but am not sure about the best way to loop through these.
Just put them in an NSMutableArray and whatever button is at index 0 is the visible one, as they swipe you'd remove the button at index 0, set it to hidden = YES and add it to the end of the array then set the button at index 0's hidden = NO.
Assuming you're using ARC, inside your class' implementation (.m) file:
#interface MyFancyButtonClass () {
NSMutableArray *_swipeButtons;
}
inside your viewDidLoad:
_swipeButtons = [NSMutableArray arrayWithObjects:buttonOne, buttonTwo, buttonThree, buttonFour, nil];
buttonOne.hidden = NO;
buttonTwo.hidden = buttonThree.hidden = buttonFour.hidden = YES;
inside your gestureRecognizer:
UIButton *currentVisibleButton = [_swipeButtons firstObject];
UIButton *nextVisibleButton = [_swipeButtons objectAtIndex:1];
[_swipeButtons removeObject:currentVisibleButton];
[_swipeButtons addObject:currentVisibleButton];
currentVisibleButton.hidden = YES;
nextVisibleButton.hidden = NO;
Create a NSMutableArray like this:
NSMutableArray * buttons = [[NSMutableArray alloc] init];
[buttons addObject:button1];
[buttons addObject:button2];
[buttons addObject:button3];
[buttons addObject:button4];
[buttons addObject:button5];
Save this array to a property like this
self.buttons = buttons;
Store the currentButton Like this:
int currentButton = 0;
Get the current button like this:
UIButton * currentSelectedButton = buttons[currentButton];
Cycle through the buttons like this:
UIButton * currentSelectedButton = buttons[currentButton];
currentSelectedButton.hidden = YES;
currentButton++;
if (currentButton >= self.buttons.count)
currentButton = 0;
currentSelectedButton = buttons[currentButton];
currentSelectedButton.hidden = NO;
I have eight (8) UIButtons setup in my game. When one is selected it shows that it is selected and if you click it again it will show as unselected. However, I want to make it so that when you select a button and any of the other seven (7) are selected, they become unselected.
I know how to do this through the use of [buttonName setSelected:NO] but the problem is I can't pass buttonOne to buttonTwo if buttonTwo has already been passed to buttonOne because I have already imported buttonTwo's header file in buttonOne. It throws a parse error if I have both headers importing each other. I've been stuck on this for a while now and was hoping that someone might have a solution to my problem.
Thanks for any help.
Get the parent view of the current button and iterate through all the buttons inside, unselecting all of them. Then, select the current one.
// Unselect all the buttons in the parent view
for (UIView *button in currentButton.superview.subviews) {
if ([button isKindOfClass:[UIButton class]]) {
[(UIButton *)button setSelected:NO];
}
}
// Set the current button as the only selected one
[currentButton setSelected:YES];
Note: As suggested on the comments, you could keep an array of buttons and go over it the same way the above code does with the subviews of the parent view. This will improve the performance of your code in case the view containing the buttons has many other subviews inside.
I know its too late to answer this question but I did it in only small lines of code . Here is what i did :
NSArray *arrView = self.view.subviews;
for (UIButton *button in arrView) {
if ([button isKindOfClass:[UIButton class]]) {
[((UIButton *) button) setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
}
}
[button1 setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
Simple way to do.
-(void)buttonSelected:(id)sender{
UIButton *currentButton = (UIButton *)sender;
for(UIView *view in self.view.subviews){
if([view isKindOfClass:[UIButton class]]){
UIButton *btn = (UIButton *)view;
[btn setSelected:NO];
}
}
[currentButton setSelected:YES];
}
I actually created an answer by reading all of your guys input, which I thank you greatly for. The tag property of the UIButton class was unknown to me before this post.
I created own subclass of UIButton, let's call it CustomUIButton.m. I created a NSMutableArray property for use when storing the buttons, which I'll call customButtonArray.
When I created the button, I set the tag property, and added the button to a local array on the parent view controller. After all buttons I wanted were created, I set the customButtonArray, like so:
// Initialize buttonHolderArray
NSMutableArray *buttonHolderArray = [[NSMutableArray alloc] init];
// Create a button
CustomUIButton *newButton = [[CustomUIButton alloc] initWithFrame:CGRectMake(10, 10, 50, 30)];
newButton.tag = 1;
[newButton setImage:[UIImage imageNamed:#"newButtonUnselected" forControlState:UIControlStateNormal]];
[buttonHolderArray addObject:newButton];
// Create additional buttons and add to buttonHolderArray...
// using different numbers for their tags (i.e. 2, 3, 4, etc)
// Set customButtonArray property by iterating through buttonHolderArray
NSInteger buttonCount = [buttonHolderArray count];
for (int i = 0; i < buttonCount; i++)
{
[[buttonHolderArray objectAtIndex:i] setCustomButtonArray:buttonHolderArray];
}
To deselect any other button selected when a different buttons handleTap: is called, I iterated through the customButtonArray in the subclass main file and set the selected property to NO. I also set the correct image from another array property that I manually populated with the images, which I did so the array didn't have to be populated every time a button was pressed. At the end, unselected all other buttons, like so:
// Populate two arrays: one with selected button images and the other with
// unselected button images that correspond to the buttons index in the
// customButtonArray
NSMutableArray *tempSelectedArray = [[NSMutableArray alloc] init];
[tempSelectedArray addObject:[UIImage imageNamed:#"newButtonSelected"]];
// Add the other selected button images...
// Set the property array with this array
[self setSelectedImagesArray:tempSelectedArray];
NSMutableArray *tempUnselectedArray = [[NSMutableArray alloc] init];
[tempUnselectedArray addObject:[UIImage imageNamed:#"newButtonUnselected"]];
// Add the other unselected button images...
// Set the property array with this array
[self setUnselectedImagesArray:tempUnselectedArray];
- (void)handleTap:(UIGestureRecognizer *)selector
{
// Get the count of buttons stored in the customButtonArray, use an if-elseif
// statement to check if the button is already selected or not, and iterate through
// the customButtonArray to find the button and set its properties
NSInteger buttonCount = [[self customButtonArray] count];
if (self.selected == YES)
{
for (int i = 0; i < buttonCount; i++)
{
if (self.tag == i)
{
[self setSelected:NO];
[self setImage:[[self unselectedImagesArray] objectAtIndex:i] forControlState:UIControlStateNormal];
}
}
}
else if (self.selected == NO)
{
for (int i = 0; i < buttonCount; i++)
{
if (self.tag == i)
{
[self setSelected:NO];
[self setImage:[[self selectedImagesArray] objectAtIndex:i] forControlState:UIControlStateNormal];
}
}
}
for (int i = 0; i < buttonCount; i++)
{
if (self.tag != i)
{
[self setSelected:NO];
[self setImage:[[self unselectedImagesArray] objectAtIndex:i] forControlState:UIControlStateNormal];
}
}
}
Thanks for all of the useful information though, figured I should share the final answer I came up with in detail to help anyone else that comes across this problem.
I figured out a pretty easy way to solve this. My example is for 2 buttons but you can easily add more if statements for additional buttons. Connect all buttons to the .h file as properties and name them (I did button1 & button2). Place the following code in your .m file and Connect it (via the storyboard) to all of your buttons. Make sure when you are setting up your button to set an image for BOTH the normal UIControlStateNormal & UIControlStateSelected or this wont work.
- (IBAction)selectedButton1:(id)sender {
if ([sender isSelected]) {
[sender setSelected:NO];
if (sender == self.button1) {
[self.button2 setSelected:YES];
}
if (sender == self.button2) {
[self.button1 setSelected:YES];
}
}
else
{
[sender setSelected:YES];
if (sender == self.button1) {
[self.button2 setSelected:NO];
}
if (sender == self.button2) {
[self.button1 setSelected:NO];
}
}
To answer "It throws a parse error if I have both headers importing each other"...
You should refrain from using #import in .h files as much as possible and instead declare whatever you're wanting to use as a forward class declaration:
#class MyCustomClass
#interface SomethingThatUsesMyCustomClass : UIViewController
#property (nonatomic, strong) MyCustomClass *mcc;
#end
Then #import the header in your .m file:
#import "MyCustomClass.h"
#implementation SomethingThatUsesMyCustomClass
-(MyCustomClass *)mcc
{
// whatever
}
#end
This approach will prevent errors caused by #import cycles.
Though I must say I agree with SergiusGee's comment on the question that this setup feels a bit strange.
The easiest approach here would be to get the parent UIView the buttons are on and iterate through it. Here's a quick example from my code:
for (UIView *tmpButton in bottomBar.subviews)
{
if ([tmpButton isKindOfClass:[UIButton class]])
{
if (tmpButton.tag == 100800)
{
tmpButton.selected = YES;
[tmpButton setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
[tmpButton setTitleColor:[UIColor greenColor] forState:UIControlStateHighlighted];
}else{
tmpButton.selected = NO;
[tmpButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[tmpButton setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
}
}
}
Did you try using ReactiveCocoa framework and add some blocks for your code , this is not the most simple approach yet i would say it is the most effective when you have multiple dependencies and very good for scaling
I have created a small project for a solution to your problem using my suggested approach (I tried to adapt it to the good old MVC pattern instead of my preferred MVVM)
you can find it here
https://github.com/MWaly/MWButtonExamples
make sure to install cocoa pods file as we need "ReactiveCocoa" and "BlocksKit" for this sample
we will use two main classes
ViewController => The viewController object displaying the buttons
MWCustomButton => Custom UIButton which handles events
when creating the buttons a weak reference to the viewController is also created using the property
#property (weak) ViewController *ownerViewController ;
events will be handled using the help of blocksKit bk_addEventHandler method and pass it to the block of the ViewController (selectedButtonCallBackBlock)
[button bk_addEventHandler:^(id sender)
{
self.selectedButtonCallBackBlock(button);
} forControlEvents:UIControlEventTouchUpInside];
now in the ViewController for each button touched the callBackButtonBlock will be trigerred , where it will change its currently selected button if applicable
__weak __typeof__(self) weakSelf = self;
self.selectedButtonCallBackBlock=^(MWCustomButton* button){
__typeof__(self) strongSelf = weakSelf;
strongSelf.currentSelectedButton=button;
};
in the MWCustomButton class , it would listen for any changes in the property of "currentSelectedButton" of its ownerViewController and will change its selection property according to it using our good Reactive Cocoa
///Observing changes to the selected button
[[RACObserve(self, ownerViewController.currentSelectedButton) distinctUntilChanged] subscribeNext:^(MWCustomButton *x) {
self.selected=(self==x);
}];
i think this would solve your problem , again your question might be solved in a simpler way , however i believe using this approach would be more scalable and cleaner.
Loop through all views in parent view. Check if it is a UIButton(or your custom button class) and not the sender. Set all views isSelected to false. Once loop is finished, set sender button isSelected to true.
Swift 3 way:
func buttonPressed(sender: UIButton) {
for view in view.subviews {
if view is UIButton && view != sender {
(view as! UIButton).isSelected = false
}
}
sender.isSelected = true
}
Swift 4
//Deselect all tip buttons via IBOutlets
button1.isSelected = false
button2.isSelected = false
button3.isSelected = false
//Make the button that triggered the IBAction selected.
sender.isSelected = true
//Get the current title of the button that was pressed.
let buttonTitle = sender.currentTitle!
This question already has an answer here:
Fading out an UIButton when touched
(1 answer)
Closed 9 years ago.
I have a UIButton that changes image on highlight. When transitioning from UIControlStateHighlight to UIControlStateNormal, I want the highlighted image to slowly fade back into the normal image. Is there an easy way to do this?
I ended up subclassing UIButton. Here's the implementation file code. I took some app-specific stuff out, so I haven't tested this exact code, but it should be fine:
#import "SlowFadeButton.h"
#interface SlowFadeButton ()
#property(strong, nonatomic)UIImageView *glowOverlayImgView; // Used to overlay glowing animal image and fade out
#end
#implementation SlowFadeButton
-(id)initWithFrame:(CGRect)theFrame mainImg:(UIImage*)theMainImg highlightImg:(UIImage*)theHighlightImg
{
if((self = [SlowFadeButton buttonWithType:UIButtonTypeCustom])) {
self.frame = theFrame;
if(!theMainImg) {
NSLog(#"Problem loading the main image\n");
}
else if(!theHighlightImg) {
NSLog(#"Problem loading the highlight image\n");
}
[self setImage:theMainImg forState:UIControlStateNormal];
self.glowOverlayImgView = [[UIImageView alloc] initWithImage:theHighlightImg];
self.glowOverlayImgView.frame = self.imageView.frame;
self.glowOverlayImgView.bounds = self.imageView.bounds;
self.adjustsImageWhenHighlighted = NO;
}
return self;
}
-(void)setHighlighted:(BOOL)highlighted
{
// Check if button is going from not highlighted to highlighted
if(![self isHighlighted] && highlighted) {
self.glowOverlayImgView.alpha = 1;
[self addSubview:self.glowOverlayImgView];
}
// Check if button is going from highlighted to not highlighted
else if([self isHighlighted] && !highlighted) {
[UIView animateWithDuration:1.0f
animations:^{
self.glowOverlayImgView.alpha = 0;
}
completion:NULL];
}
[super setHighlighted:highlighted];
}
-(void)setGlowOverlayImgView:(UIImageView *)glowOverlayImgView
{
if(glowOverlayImgView != _glowOverlayImgView) {
_glowOverlayImgView = glowOverlayImgView;
}
self.glowOverlayImgView.alpha = 0;
}
#end
You could also just pull the highlighted image from [self imageForState:UIControlStateHighlighted] and use that, it should work the same. The main things are to make sure adjustsImageWhenHighlighted = NO, and then overriding the setHighlighted: method.
I have 2 buttons on my view and i want to disable the first button when i click on an other button and disable the second when I click again on the button.
I have tried with this code
if (button1.enable = NO) {
button2.enable = NO;
}
So I have in a NavigationBar a "+" button and 5 disable buttons in my view.
When I push the "+" button I want to enable the first button and when I push again that enable the second…
Thanks
if (button1.enabled == YES)
{
button1.enabled = NO;
button2.enabled = YES;
}
else (button2.enabled == YES)
{
button2.enabled = NO;
button1.enabled = YES;
}
Is that what your looking for? It would be an IBAction for the other button.
button1.enable = YES should be button1.enable == YES
a better readable form: [button1 isEnabled]
You're saying
if (button1.enabled = NO) {
when you probably mean
if (button1.enabled == NO) {
= is the assignment operator, and == is the boolean equality operator. What you're doing at the moment is assigning YES to button1.enable, which obviously enables button1. Then, because button.enable is true, control enters the if's clause and enables button2.
EDIT: To answer your new question ("When I push the "+" button I want to enable the first button and when I push again that enable the second..."), let's say that you initialise the button states somewhere. In your #interface add an instance variable
NSArray *buttons;
so your interface declaration looks something like
#interface YourViewController: UIViewController {
IBOutlet UIButton *button1;
IBOutlet UIButton *button2;
IBOutlet UIButton *button3;
IBOutlet UIButton *button4;
IBOutlet UIButton *button5;
NSArray *buttons;
}
and then initialise buttons like so:
-(void)viewDidLoad {
[super viewDidLoad];
buttons = [NSArray arrayWithObjects: button1, button2, button3, button4, button5, nil];
[buttons retain];
for (UIButton *each in buttons) {
each.enabled = NO;
}
-(void)viewDidUnload {
[buttons release];
[super viewDidUnload];
}
Let's say you hook up the + button's Touch Up Inside event handler to plusPressed:. Then you'd have
-(IBAction)plusPressed: (id) button {
for (UIButton *each in buttons) {
if (!each.enabled) {
each.enabled = YES;
break;
}
}
}
Each time plusPressed: is called, the next button in the array will be enabled. (I'm writing the above away from a compiler; there may be syntax errors.)
You could also make buttons a property. I didn't, because other classes have no business accessing buttons.