I have been trying to write a program in which a button appears after a timer fires. The timer is working properly, as is the firing event (I have tested this with different events). However, the button I am making appear is not showing up. Also, I would like the button background image to change when the button is pressed and held. I have tried making the button just have a background color instead of an image, but that does not work either. The code is located in the Timer selector within the view controller Any help is appreciated. Thanks!
- (void)timerFireMethod:(NSTimer *)timer
{
Button = [UIButton buttonWithType:UIButtonTypeCustom];
Button.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2);
[Button setBackgroundImage:[UIImage imageNamed:#"buttonUnheldBGImage"]
forState:UIControlStateNormal];
[Button setBackgroundImage:[UIImage imageNamed:#"buttonHeldBGImage"]
forState:UIControlStateHighlighted];
[Button setTitle:#"Press and Hold" forState:UIControlStateNormal];
[Button addTarget:self action:#selector(aSelector:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:Button];
}
The timer class that calls this is:
- (void)timer
{
globalTimer = [NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:#selector(timerFireMethod:)
userInfo:Nil
repeats:NO];
}
globalTimer is a global NSTimer
You have set the center of the button but you also need the frame of it, i believe that the button is showing now but his frame is (0,0).
You have to set a size to your button as well. If you want it at the center of your super view just do :
CGRect buttonFrame = CGRectMake(self.view.frame.size.width/2-100,self.view.frame.size.height/2-100, 200,200);
Button.frame = buttonFrame;
The center property is essentialy used for UI Element that already have a size.
Just replace your first 2 lines,
UIButton * Button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
Button.frame = CGRectMake(20, 200, 200, 200);
Related
I have a little problem using the navigation bar in an iOS project using objective-c.
I have some view controllers which are managed by a navigationviewcontroller, in a hierarchy like 1-2-3.
For the Viewcontrollers 2 and 3, I define custom back buttons in the viewWillAppear function, as I need to assign them a more complex logic when touching them. This is the reason why I do not set the back buttons in the previous view controller.
Everything works fine like this, my single problem is that, on transition from one view to another, the arrow of the back button is overlayed by a little view in the color of the navigation bar's background color until up to 50%, and then disappears when the transition has finished.
I create my back buttons in the navigationbar with this function, which is called in viewWillAppear:
- (void)setupCustomBackButton:(NSString *)title
action:(SEL)action
buttonFrame:(CGRect)buttonFrame {
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
backButton.frame = buttonFrame;
[backButton setImage:[UIImage imageNamed:#"backArrowOwn"] forState:UIControlStateNormal];
backButton.imageEdgeInsets = UIEdgeInsetsMake(0.0f, -8.0f, 0.0f, 0.0f);
[backButton setTitle:title forState:UIControlStateNormal];
[backButton.titleLabel setFont:[UIFont systemFontOfSize:17.0]];
backButton.titleEdgeInsets = UIEdgeInsetsMake(0.0f, -3.0f, 0.0f, 0.0f);
[backButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[backButton addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = barButton;
}
I hope that maybe someone has a good hint for me! Thanks!
After some long trying, I finally managed to save the problem on my own.
So basically, when I create a leftBarButton, the button does not begin at the left margin, but has some space to the left margin. When I now inset my button image with a negative inset, the image will be basically outside my button frame. This portion is then weirdly overlayed on transition.
To fix this, I just add another UIBarButtonItem additionally to my leftBarButtonItems. This seems to fix the issue for me, although I do not really know why exactly.
Also, I think that it is weird that the leftBarButton in the navigationBar does not begin exactly at the margin, but has a space to the margin and I have to inset my image in order to get the exact same position for the image, as the default back button has.
My new code for creating a custom back button now looks like this:
- (void)setupCustomBackButton:(NSString *)title
action:(SEL)action
buttonFrame:(CGRect)buttonFrame {
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
backButton.frame = buttonFrame;
[backButton setImage:[UIImage imageNamed:#"customBackArrow"] forState:UIControlStateNormal];
backButton.imageEdgeInsets = UIEdgeInsetsMake(0.0f, -8.0f, 0.0f, 0.0f);
[backButton setTitle:title forState:UIControlStateNormal];
[backButton.titleLabel setFont:[UIFont systemFontOfSize:17.0]];
backButton.titleEdgeInsets = UIEdgeInsetsMake(0.0f, -3.0f, 0.0f, 0.0f);
[backButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[backButton addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:backButton];
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
self.navigationItem.leftBarButtonItem = nil;
[self.navigationItem setLeftBarButtonItems:[NSArray arrayWithObjects:negativeSpacer,barButton, nil] animated:NO];
}
Thanks everyone and I hope that my answer helps anyone else too!
Try to move the custom button initialization to the viewDidLoad method.
I have some custom type UIButtons placed pragmatically in a custom view. The view is basically a menu. I am generating the buttons with the following code, inside the view's .m file:
-(void) generateButtons: (NSMutableArray *) buttonsArray
{
UIImage *barItemImage = [[UIImage imageNamed:#"ipad-menubar-button.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
float buttonWidth = (self.frame.size.width - (2 * FIRSTBUTTONXCOORDINATE) - 25)/ 6.0f;
float xCoord = FIRSTBUTTONXCOORDINATE;
float yCoord = (self.frame.size.height - BUTTONHEIGHT) / 2.0f;
for (int i = 0; i < buttonsArray.count; i++)
{
NSString* buttonTitle = [buttonsArray objectAtIndex:i];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:#selector(botButtonAction:)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:buttonTitle forState:UIControlStateNormal];
button.frame = CGRectMake(xCoord, yCoord, buttonWidth, BUTTONHEIGHT);
button.tag = i;
[button setBackgroundImage:barItemImage forState:UIControlStateNormal];
xCoord += buttonWidth + 5;
[self addSubview:button];
}
}
On touchUpInside, botButtonAction is called and it does what it is supposed to. However, the buttons do not usually give any visual indication of the touchUpInside. When I touchDown on a button and swipe in any direction, then I see the background color get darker. Sometimes, I see the same visual indication on touchUpInside. It seems completely random though.
Any ideas as to what I might be doing wrong here?
Edit: Sorry, I got occupied with other issues. Here is the code for botButtonAction and the method it calls
-(void) botButtonAction: (UIButton *) sender
{
if (self.delegate)
[self.delegate optionsMenuAction:self data:sender.tag];
}
-(void)optionsMenuAction:(OptionsMenueView *)view data:(int)tag
{
if (self.PDFVC)
{
[self.navigationController popToViewController:self animated:YES];
}
if (!self.optionsMenue.isAtWPC || tag != WPC)
[self transitionFromViewAtIndex:self.selectedVCIndex toView:tag];
else
[self transitionFromViewAtIndex:self.selectedVCIndex toView:WPList];
}
But since I am using touchUpInside, these methods don't get called on touchDown. I just want the button to be highLight (grayout the bg a little) on touchDown. As I state before, that happens on touchDown and swipe.
Edit
I had so far been running this on actual devices (iPad air and iPad 2). When I tried running it on the simulator, I get the correct result. On mouse click, the button gets highlighted.
Edit
I think I figured out the exact problem (still looking for a solution). If I touchDown precisely on the button and the touch does not cover any part of the insets, then the highlighting works. However, if the touch covers part of the button and also part of the insets/outside, then the highlighting doesn't work.
add this line:
[button setBackgroundImage:HighlightImage forState:UIControlStateHighlighted];
change the title colour when tap on the button like this
[yourButon setTitleColor:[UIColor colorYouWant] forState:UIControlStateHighlighted];
hope this will help you......
put this code in botButtonAction:
-(void)botButtonAction:(UIButton *)sender
{
[sender setBackgroundImage:[UIImage imageNamed:#"some iamge.png"]
forState:UIControlStateNormal];
}
or use the code below code in for loop
[button setBackgroundImage:[UIImage imageNamed:#"back_button_press.png"] forState: UIControlStateHighlighted];
or if you want to give some color then setcolour of button
I had this problem at some point too. These other answers will give you the result you seek normally. However.... You are using [UIButton buttonWithType:UIButtonTypeCustom].. Which is really buggy if you do not alloc/init the UIButton.. Try changing this line to a normal button allocation and then add the following lines of the answers in this post. This should work for you.
So in short,
replace [UIButton buttonWithType:UIButtonTypeCustom];
with [[UIButton alloc] init];
And then add the following changes to your code to change the image.
[myNewlyAllocatedButton setBackgroundImage:[UIImage imageNamed:#"back_button_press.png"] forState: UIControlStateHighlighted];
I'm trying to create two buttons whose label is initially set as a default value. The two buttons are managed by a popOverViewController, in which the viewDidLoad method initialise all the controls. I also have another method called addButtons that gets executed by the AppDelegate after receiving a valid response from Apple's servers containing products descriptions and prices.
My problem is that I can't get the label updated with that method.
My viewDidLoad method in the popOverViewController is:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// Add a label to the popover's view controller.
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(button1Week:)
forControlEvents:UIControlEventTouchDown];
NSString *priceWeekly = [NSString stringWithFormat:#"weekly subscription"];
[button setTitle:priceWeekly forState:UIControlStateNormal];
button.frame = CGRectMake(0.0, 0.0, 200.0, 50.0);
[button2 addTarget:self
action:#selector(button1Month:)
forControlEvents:UIControlEventTouchDown];
[button2 setTitle:#"monthly subscription" forState:UIControlStateNormal];
button2.frame = CGRectMake(0.0, 55.0, 200.0, 50.0);
[self.view addSubview:button];
[self.view addSubview:button2];
}
and my update label method, of which I'm sure it gets called at the right time, is:
-(void)addButtons {
[self.button setTitle:#"updated label" forState:UIControlStateNormal];
[self.button2 setTitle:#"updated label 2" forState:UIControlStateNormal];
}
can you please check my code and suggest the right way to update the labels? Basically I want to initialize the controls with a default label because of the waiting time between controls creation and server response.
UPDATE:
I have updated the code as follows, but still everything that's inside the addButtons method gets executed as I have an NSLog to check, but the button title still remains as created in viewdidload
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// Add a label to the popover's view controller.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
ilManifestoAppDelegate *delegate = (ilManifestoAppDelegate*)[[UIApplication sharedApplication] delegate];
[button addTarget:self
action:#selector(button1Week:)
forControlEvents:UIControlEventTouchDown];
// [button setTitle:priceWeekly forState:UIControlStateNormal];
button.frame = CGRectMake(0.0, 0.0, 200.0, 50.0);
[button2 addTarget:self
action:#selector(button1Month:)
forControlEvents:UIControlEventTouchDown];
// [button2 setTitle:#"monthly subscription" forState:UIControlStateNormal];
button2.frame = CGRectMake(0.0, 55.0, 200.0, 50.0);
// [self addButtons];
NSString *weekPrice = [NSString stringWithFormat:#"settimanale a %#",delegate.priceWeek];
[button setTitle:weekPrice forState:UIControlStateNormal];
[button2 setTitle:#"updated label 2" forState:UIControlStateNormal];
NSLog(#"week price %#", weekPrice);
[self.view addSubview:button];
[self.view addSubview:button2];
}
-(void)addButtons {
UIButton *button = [UIButton buttonWithType:UIButtonTypeInfoDark];
[button setTitle:#"modificato" forState:UIControlStateNormal];
[self.view addSubview:button];
NSLog(#"addButtons executed");
}
In viewDidLoad you are using button and button2. In addButtons you are using self.button and self.button2. Did you ensure that these are the same buttons?
Also place a breakpoint in addButtons to see if it really is called, if you haven't done this yet.
Have you also created the outlet to the buttons in the xib, if you haven't placed them only with code.
I'm using UINavigationController. How do I stop (call the invalidate method) on my timer when the user hits the back button.
I presume you can use viewWillDisappear method to detect indirectly when back is pressed and invalidate your timer
//Put this viewDidLoad and make sure you have a back.png that mimics back button
UIImage *buttonImage = [UIImage imageNamed:#"back.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:buttonImage forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
[button addTarget:self action:#selector(backPressed:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = customBarItem;
- (void)backPressed:(id)sender {
[yourTimer invalidate];
}
If the timer is running in another class use NSNotificationCenter to post a notification in backPressed Method
See NSNotification Center example here NSNotification Tutorial
I am now creating an App that has a browser like Safari:
There is a UITextField(left side) and UISearchBar(right side) inserted into the UINavigationBar on the top of the view.
I am wondering if there is a way to add an animation on a "Cancel" button at the time it appears when user touches the UITextField.
The animation is just like it is on the Safari: when User touches the UITextField, the "Cancel" button comes from right outside of the window while the UISearchBar is fading.
Note that I am initializing the "Cancel" button by UIBarbuttonItem(UIBarButtonSystemItemCancel).
Any help would be appreciated.
Update:
Finally I found the anwser by myself. It seems that you cannot assign a specific position where UIBarButtonItem shows up or hide. So one possible way to solve this problem is to customize a UIButton just looks like the UIBarButtonItem, here is the code:
-(void)viewDidLoad {
......
CGSize backgroundStretchPoints = {4, 2};
UIImage *image = [[UIImage imageNamed:#"UINavigationBarDefaultButton.png"] stretchableImageWithLeftCapWidth:backgroundStretchPoints.width
topCapHeight:backgroundStretchPoints.height];
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(330, 23, 80, 30); // initialize the button outside the window
[button setBackgroundImage:image forState:UIControlStateNormal];
[button setTitle:#"Cancel" forState:UIControlStateNormal];
button.titleLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:12];
[button addTarget:self action:#selector(cancelButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[navigationBar addSubview: button];
.......
}
and when you click the UITextField(i.e.), the cancel button will slide into the window:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView animateWithDuration:0.25 animations:^{
button.frame = CGRectMake(232, 23, 80, 30); // here is the position button will slide into window with animation
}];
}