My button is disabled but I want to show a message box when user clicks on it. How can I do it? Also I would like to mention that UIbutton is added on UITableview, and I tried the code below, but it always goes to else in DisableClick() function.
In cellForRowAtIndexPath:
button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(180, 6, 30, 30)];
[button setTag:4000];
[button addTarget:self action:#selector(click:event:) forControlEvents:UIControlEventTouchDown];
UITapGestureRecognizer* gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(DisableClick:)];
[self.view addGestureRecognizer:gesture];
[gesture release];
[cell.contentView addSubview:button];
In DisableClick()
- (void)DisableClick:(UIButton*)sender {
UITapGestureRecognizer *recognizer = (UITapGestureRecognizer *)sender;
CGPoint pt = [recognizer locationOfTouch:0 inView:market];
if (CGRectContainsPoint(market.bounds, pt)) {
NSLog(#"Disabled button tapped");
}
else
{
NSLog(#"go out"); // it's always go to here
}
}
Rather than desabling the button keep it enable. Change the image of button like disable image. Put a flag variable when button is tapped use this flag variable to run the code of enabled button and disabled button
BOOL btnFlg;//initialize it true or false on cellForRowAtIndex... method
- (void)DisableClick:(UIButton*)sender
{
if(btnFlg)
{
btnFlag=NO;
NSLog("button disabled");
}
else
{
btnFlag=YES;
NSLog("button enabled");
}
}
Why you are initialize a tap gesure for this button. You set the selector in ur addTarget
Maintain a btn boolean for the button status . Change the status whenever you want to disable or enable.
BOOL btnEnabled;
button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(180, 6, 30, 30)];
[button setTag:4000];
[button addTarget:self action:#selector(DisableClick:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button];
Make the target function as
- (void)DisableClick:(UIButton*)sender {
//set the function that you needed when the user tap on this button here.
if(btnEnabled) {
// here invoke the functions you needed when the button enabled
} else {
UIAlertView *msg = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"Your button is disabled" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[msg show];
}
}
You will need to subclass UIButton and implement
touchesBegan:withEvent: and touchesEnded:withEvent: methods for your purpose.
Related
I am adding an image in IBAction, I want to restore the old image back once the button is tapped.
It is not the image in the UIButton, it's the image in the UIImageView
- (IBAction)findMe:(id)sender
{
[self.imageView setImage:[UIImage imageNamed:#"image2"]];
}
I want to restore#"image1". immediate once button is tapped
some thing i need is some thing similar to
button setImage:[UIImage imageNamed:#"clicked.png"] forState:UIControlStateSelected | UIControlStateHighlighted];
but i don't want to change Button Image, but change UIImageView Image when clicked
You can use the following code
[yourButton addTarget:self action:#selector(touch2:) forControlEvents:UIControlEventTouchDown];
[yourButton addTarget:self action:#selector(touch3:) forControlEvents:UIControlEventTouchUpInside];
Now the selectors
-(void)touch2:(UIButton *)send
{
imageView.image= [UIImage imageNamed:#"image1"];
}
-(void)touch3:(UIButton *)send
{
imageView.image= [UIImage imageNamed:#"image2"];
}
Try it out:
- (IBAction)findMe:(id)sender
{
if (self.imageView.image) {
// store your old image here
NSLog(#"%#", self.imageView.image)
}
[self.imageView setImage:[UIImage imageNamed:#"image2"]];
}
Try this first create gesture for UIButton
UILongPressGestureRecognizer *btn_LongPress_gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleBtnLongPressgesture:)];
[buttonFindMe addGestureRecognizer:btn_LongPress_gesture];
When you press and release the button it calls this method.
-(void)handleBtnLongPressgesture:(UILongPressGestureRecognizer *)recognizer{
//as you hold the button this would fire
if (recognizer.state == UIGestureRecognizerStateBegan) {
//Change your image 1
}
//as you release the button this would fire
if (recognizer.state == UIGestureRecognizerStateEnded) {
//Change your image 2
}
}
I created some buttons in my code. I want to set it disable but I'm not sure how. here's my code.
UIButton *btn_levels = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn_levels.frame=CGRectMake(x-10, y, 40, 40);
[btn_levels setTitle:[beginer_lvl objectAtIndex:i] forState:UIControlStateNormal];
[btn_levels addTarget:self action:#selector(btn_Method) forControlEvents:UIControlEventTouchUpInside];
btn_levels.tag =i;
btn_levels.backgroundColor=[UIColor blackColor];
btn_levels.tintColor=[UIColor cyanColor];
NSLog(#"btn nm=%#",[beginer_lvl objectAtIndex:i]);
[self.scroll addSubview:btn_levels];
and that is the button method but I don't know what to do...
-(void)btn_Method
{
//to make button disable
}
Modify this line
[btn_levels addTarget:self action:#selector(btn_Method:) forControlEvents:UIControlEventTouchUpInside];
and this method
-(void)btn_Method:(UIButton*)sender
{
sender.enabled = NO;
}
change the statement
[btn_levels addTarget:self action:#selector(btn_Method) forControlEvents:UIControlEventTouchUpInside];
to
[btn_levels addTarget:self action:#selector(btn_Method:) forControlEvents:UIControlEventTouchUpInside];
Also change the below method -
-(void)btn_Method
{
//to make button disable
}
to
-(void)btn_Method:(UIButton*)button
{
//to make button disable
[button setEnabled:NO];
}
disabled but visible
btn_levels.enabled = NO;
also invisible
btn_levels.hidden = YES;
Target actions can send the object for which it'll performed the action. To make your method to know which button was tap, you need to make its definition to get the button inside the method. So just change you button definition to look like this,
- (void) btn_Method:(UIButton *)sender {...}
also, where you're adding target to the button you've to add a colon ( : ) after the method name to tell the compiler that, this action will need an object on which an action was added. So that line should look like this,
[btn_levels addTarget:self action:#selector(btn_Method:) forControlEvents:UIControlEventTouchUpInside];
^
Here, we will get a sender (you can give any name to your argument) of type UIButton with btn_Method action call. That's it, now you can do anything with that button, so in your case you want to make it disable, so the method would look like this,
- (void) btn_Method:(UIButton *)sender {
sender.enabled = NO;
}
I have a button that has a selected and non-selected state.
My target action code for the button is this:
NSArray *targets = [myButton actionsForTarget:self forControlEvent:UIControlEventTouchUpInside];
if ([targets count] == 0) {
[myButton addTarget:self action:#selector(save:) forControlEvents:UIControlEventTouchUpInside];
When the button is pressed, it goes to selected state in the method.
If the button is selected, a different action should be called. Is there any unintended consequence to doing it this way or is there a way to add actions with UIControlState instead?
if (myButton.selected == NO){
[myButton addTarget:self action:#selector(save:) forControlEvents:UIControlEventTouchUpInside];
}
else{
[myButton addTarget:self action:#selector(delete:) forControlEvent:UIControlEventTouchUpInside];
}
-(IBAction)myButton:(id)sender
{
UIButton *btn = (UIButton*)sender;
btn.selected = !btn.selected;
if(btn.selected)
{
//Do whatever you want when button is selected
[self delete];
}
else
{
//Do whatever you want when button isDeselected
[self save];
}
}
Your approach might be confusing. You can use like this.
[myButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
- (void)buttonPressed:(UIButton *)sender
{
if(sender.selected)
[self save];
else
[self delete];
}
-(void)save
{
// your code
}
-(void)delete
{
// your code
}
i believe that you are wanting something like toggle button. if i am right use yourbutton.currentTitle to follow the functionality. i.e. if [youtbutton.currentTitle isEqualToString: #"save]" then you should perform save and set that to delete and vice verse
I need your help. I am trying to build a game. When a hint button is pressed a new view is created programmatically with the code below:
In my gameController.m
//connect the Hint button
-(void)setHud:(HUDView *)hud
{
_hud = hud;
[hud.btnHelp addTarget:self action:#selector(actionHint) forControlEvents:UIControlEventTouchUpInside];
}
//the user pressed the hint button
-(void)actionHint
{
CGRect viewRect = CGRectMake(kScreenWidth/2 -kMenuWidth, kScreenHeight/2-kMenuHeight,kMenuWidth*10, kMenuHeight*2);
HintMenu* hintMenu = [HintMenu viewWithRect:viewRect];
[self.gameView addSubview:hintMenu];
}
This is my new View created programmatically.
+(instancetype)viewWithRect:(CGRect)r
{
HintMenu* hint = [[HintMenu alloc] initWithFrame:r];
hint.userInteractionEnabled = YES;
UIImage* image=[UIImage imageNamed:#"btn"];
hint.btnHelp = [UIButton buttonWithType:UIButtonTypeCustom];
[hint.btnHelp setTitle:#"button" forState:UIControlStateNormal];
hint.btnHelp.titleLabel.font = kFontHUD;
[hint.btnHelp setBackgroundImage:image forState:UIControlStateNormal];
hint.btnHelp.frame = CGRectMake(50, 30, image.size.width, image.size.height);
hint.btnHelp.alpha = 0.8;
[hint addSubview: hint.btnHelp];
UIImage* image2=[UIImage imageNamed:#"tile"];
hint.imageHelp=[[UIImageView alloc] initWithFrame:CGRectMake(image.size.width + 50 + 10, 30, image2.size.width, image2.size.height/2)];
hint.imageHelp.image=image2;
[hint addSubview:hint.imageHelp];
return hint;
}
I want to identify when the button in the new view is being pressed. Similarly with the above I add in my GameController.m
//connect the button in the Menu
-(void)setHintMenu:(HintMenu *)hintMenu
{
_hintMenu = hintMenu;
[hintMenu.btnHelp addTarget:self action:#selector(actionHintMenu) forControlEvents:UIControlEventTouchUpInside];
}
//the user pressed the menu button
-(void)actionHintMenu
{
NSLog(#"Button in menu pressed");
}
but the log is not shown. Can you help me on this?
edit:
If this code is added in the HintMenu.m which is my new Created view like this:
+(instancetype)viewWithRect:(CGRect)r
{
...
hint.btnHelp.alpha = 0.8;
[hint.btnHelp addTarget:self action:#selector(actionHintMenu:) forControlEvents:UIControlEventTouchUpInside];
[hint addSubview: hint.btnHelp];
..
}
//the user pressed the menu button
-(void)actionHintMenu:(UIButton *) button
{
NSLog(#"Button in menu pressed");
}
I am getting this error:
2013-06-16 16:44:30.559 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[HintMenu actionHintMenu]: unrecognized selector sent to class 0xe6f8'
*** First throw call stack:
Answer to you edited question
Replace
[hint.btnHelp addTarget:self action:#selector(actionHintMenu) forControlEvents:UIControlEventTouchUpInside];
with
[hint.btnHelp addTarget:hint action:#selector(actionHintMenu) forControlEvents:UIControlEventTouchUpInside];
I am not sure why you have added [hintMenu.btnHelp addTarget:self action:#selector(actionHintMenu) forControlEvents:UIControlEventTouchUpInside]; inside the setter method of your hintMenu view.
There is no call for the setter method of hintMenu and so the button target-action is not getting set.
I would suggest remove the -(void)setHintMenu:(HintMenu *)hintMenu completely.
Update actionHint
-(void)actionHint
{
CGRect viewRect = CGRectMake(kScreenWidth/2 -kMenuWidth, kScreenHeight/2-kMenuHeight,kMenuWidth*10, kMenuHeight*2);
HintMenu* hintMenu = [HintMenu viewWithRect:viewRect];
[hintMenu.btnHelp addTarget:self action:#selector(actionHintMenu) forControlEvents:UIControlEventTouchUpInside];
[self.gameView addSubview:hintMenu];
}
This is just a fix. If you ask me the right method, I would suggest setting the button target should be done within your custom view itself. For that you might maintain a delegate property in the view.
I have a grid of UIButtons. When I hit an 'edit' button, I want a delete button to appear over each of these buttons, which when pressed, deletes the button (and associated data). A bit like apple's home screen, when you hold down a button and it starts to wiggle with an X in the corner.
According to this post: Subclass UIButton to add a property I can use Associative References to add a property to each of my buttons. I've tried to add a UIButton as a property of my custom UIButton but I can't seem to get it to appear and have the feeling this isn't the right way to go. Here's my custom button main:
#import "UIButton+Property.h"
#import <objc/runtime.h>
#implementation UIButton(Property)
static char UIB_DELETEBUTTON_KEY;
#dynamic deleteButton;
- (void)setDeleteButton:(UIButton *)deleteButton {
deleteButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
deleteButton.frame = CGRectMake(100, 100, 50, 50);
objc_setAssociatedObject(self, &UIB_DELETEBUTTON_KEY, deleteButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIButton *)deleteButton {
return (UIButton *)objc_getAssociatedObject(self, &UIB_DELETEBUTTON_KEY);
}
#end
And here's where I add the buttons programmatically:
//Create a custom button for each custom book doc
for (int i = 0; i < [customBookDocs count]; ++i) {
BookDoc *customBookDoc = [customBookDocs objectAtIndex:i];
NSString *bookTitle = customBookDoc.book.title;
//create a button for each book
CGRect frame = CGRectMake(xCoord, yCoord, 200, 200);
UIButton *bookButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
bookButton.bookDoc = customBookDoc;
[bookButton setFrame:frame];
[bookButton setTitle:bookTitle forState:UIControlStateNormal];
[bookButton addTarget:self action:#selector(bookButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
xCoord += 250;
[self.view addSubview:bookButton];
[self.view addSubview:bookButton.deleteButton];
}
Is there an easier more sensible way to do this? Or am I on the right track?
ORIGINAL RESPONSE BEGAN:
... Someone else may have more to say about that, but I'm not sure why you'd need to use object association here. You can certainly add another button to your button as a property using regular subclassing, which is the route that I would take. ...
EDITS BELOW:
I thought that I had subclassed a UI control directly, but I realized that I was mistaken when I went to look for the code. #Joe rightly pointed out in the comments that there are issues with directly subclassing UI controls.
I was able to implement something like the functionality you described without using Associated Objects, by creating a wrapper class to hold the button and its related delete button. It works, but it's not very flexible, so I would generally recommend #Joe's method as a better solution.
Here's the relevant code:
I threw all of the code into the appDelegate to keep it simple. I don't recommend that in real life.
AppDelegate.m:
#implementation AppDelegate
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
UIButton *toggleDeleteButtons = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[toggleDeleteButtons setFrame:CGRectMake(20, 45, 280, 45)];
[toggleDeleteButtons setTitle:#"Toggle Delete" forState:UIControlStateNormal];
[toggleDeleteButtons addTarget:self action:#selector(toggleDeleteButtonAction) forControlEvents:UIControlEventTouchUpInside];
[[self window] addSubview:toggleDeleteButtons];
ButtonWrapper *myButtonWrapper = [[ButtonWrapper alloc] init];
[[myButtonWrapper button] setFrame:CGRectMake(20, 100, 200, 45)];
[[myButtonWrapper button] setTitle:#"This is my button" forState:UIControlStateNormal];
[[myButtonWrapper deleteButton] addTarget:self action:#selector(buttonDeleteRequested:) forControlEvents:UIControlEventTouchUpInside];
[[myButtonWrapper deleteButton] setTag:0];
[[self window] addSubview:[myButtonWrapper button]];
buttonWrapper1 = myButtonWrapper;
// Added instance called anotherButtonWrapper with tag 1, as above
// Added instance called stillAnotherButtonWrapper with tag 2, as above
[self.window makeKeyAndVisible];
return YES;
}
- (void)toggleDeleteButtonAction {
static BOOL deleteButtonsShown;
[buttonWrapper1 showDeleteButton:!deleteButtonsShown];
[buttonWrapper2 showDeleteButton:!deleteButtonsShown];
[buttonWrapper3 showDeleteButton:!deleteButtonsShown];
deleteButtonsShown = !deleteButtonsShown;
}
- (void)buttonDeleteRequested:(UIButton *)deleteButton {
// delete the specified button here
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Delete" message:[NSString stringWithFormat:#"Delete was pressed on button %i",[deleteButton tag]]delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
ButtonWrapper.m:
#implementation ButtonWrapper
#synthesize button;
#synthesize deleteButton;
- (ButtonWrapper *)init {
ButtonWrapper *newWrapper = [ButtonWrapper alloc];
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myButton setFrame:CGRectZero];
UIButton *myDeleteButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myDeleteButton setFrame:CGRectMake(0, 0, 100, 40)];
[myDeleteButton setTitle:#"Delete" forState:UIControlStateNormal];
[myDeleteButton setHidden:TRUE];
[myButton addSubview:myDeleteButton];
[newWrapper setButton:myButton];
[newWrapper setDeleteButton:myDeleteButton];
return newWrapper;
}
- (void)showDeleteButton:(BOOL)showButton {
if (showButton) {
[[self deleteButton] setHidden:FALSE];
[[self deleteButton] setEnabled:TRUE]; }
else {
[[self deleteButton] setHidden:TRUE];
[[self deleteButton] setEnabled:FALSE];
}
}
#end
This solution did not require me to implement all of the UI properties, but it did require extra work to hook up the embedded delegates, which is cumbersome. There may be a way to pass the delegates into the wrapper at initialization, but I couldn't make it work.