How to have a UIKit button open another view? - objective-c

I have a grid of buttons in one page. I want the buttons to lead to another view when clicked. What should I add to the following action to change the view?
-(void)buttonPressed:(UIButton *)button {
NSLog(#"button %u -- frame: %#", button.tag, NSStringFromCGRect(button.frame));
}
The grid of buttons is created with:
{
int rows = 13, columns = 4;
UIView *buttonView = [[UIView alloc] initWithFrame:CGRectMake(0.f, 0.f, 80*columns, 32*rows)];
int currentTag = 0;
for (int y = 0; y < rows; y++) {
for (int x = 0; x < columns; x++) {
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
// [button.layer setBorderWidth:1.0];
// [button.layer setBorderColor:UIColor blackColor]];
button.backgroundColor=[UIColor colorWithRed: 201.0/255.0 green: 201.0/255.0 blue:201.0/255.0 alpha: 1.0];
button.tag = currentTag;
currentTag++;
[button.layer setBorderColor: [[UIColor blackColor] CGColor]];
[button.layer setBorderWidth: 1.0];
[button setTitle:[NSString stringWithFormat:#"%d",currentTag] forState:UIControlStateNormal];
button.frame = CGRectMake(80*x, 32*y, 80, 32);
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[buttonView addSubview: button];
}
}
// Center the view which contains your buttons
CGPoint centerPoint = buttonView.center;
centerPoint.x = self.view.center.x;
buttonView.center = centerPoint;
[self.view addSubview:buttonView];
}

Maybe you want to connect an action?
[button addTarget:self
selector:#selector(buttonPressed:)
forControlEvents:UIControlEventTouchUpInside];
(check syntax, this is by memory...)

Rinju's answer would work, but it needs a little more explanation. I'm not sure why exactly you would like to create this grid of buttons (more info would be nice), but if you want each button to show a new view, then tags are important!
If you want to open the same view, but with different properties shown on that view, you'd need to create a new view controller class. Let's call this DetailViewController.
Now, in your buttonPressed: method, you're going to need to instantiate this view controller and set a property of it!
#interface DetailViewController : UIViewController
#property (nonatomic, assign) int buttonTag;
...
//other methods, properties, etc. here
...
#end
Now, in your view controller where the buttons are, you can do this (for the sake of simplicity, I will assume you are using storyboards. If not, it can still be easily accomplished similar to what Rinju has done).
-(void)buttonPressed:(UIButton*)button {
[self performSegueWithIdentifier:#"DetailView" sender:button];
}
Now, you can implement the prepareForSegue method, which is called just before the segue fires:
-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender {
if( [[segue identifier] isEqualToString:#"DetailView"] ) {
DetailViewController *detailView = [segue destinationViewController];
detailView.buttonTag = ((UIButton*)sender).tag;
}
}
Now that the tag is set for your new detail view controller, you can probably use switch statements (or better yet, a model object which is passed this buttonTag) in viewDidLoad: of the DetailViewController to set up the UI there. Basically what we are doing is using the tag of the button to distinguish which button was pressed, and based on this create a new view!
What you may want to do is create a typedef enum structure to make names for the tags instead of using raw integers. This will increase the readability of your code, and also will help you in not getting confused ;)

-(void)buttonPressed:(UIButton *)button
{
NSLog(#"button %u -- frame: %#", button.tag, NSStringFromCGRect(button.frame));
Cart *crtObj=[[Cart alloc]initWithNibName:#"Cart" bundle:nil];
[self.navigationController pushViewController:crtObj animated:YES];
[crtObj release];
}

Related

tvOS: Setting focus order

I currently have 3 objects called MenuButton that's a child of UIButton. These are defined in a row as shown in the image.
I've defined the highlight states in my MenuButton -didUpdateFocusInContext:withAnimationCoordinator method:
- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context
withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{
if (context.nextFocusedView == self)
{
[self setTitleColor:[UIColor whiteColor]
forState:UIControlStateNormal];
}
else if (context.previouslyFocusedView == self)
{
[self setTitleColor:[UIColor colorWithRed:25.0/255.0
green:23.0/255.0
blue:16.0/255.0
alpha:1.0]
forState:UIControlStateNormal];
}
}
I've also set canBecomeFocused in the MenuButton object via:
- (BOOL)canBecomeFocused
{
return YES;
}
I've set my initial focus button using:
[_camerasButton setNeedsFocusUpdate]
When I swipe right on the Simulator remote, I'm not able to get it to focus on Deliveries.
Can someone please explain how I can use UIFocusGuide to implement this correctly in Objective-C?
UPDATE 1
Based on JustinVoss' suggestion on the first comment, I set breakpoint and did a _whyIsThisViewNotFocusable on the debug console. Received this hint:
(lldb) po [(UIView*)0x7ff68054f7c0 _whyIsThisViewNotFocusable]
ISSUE: This view may not be focusable because other views or focus guides are occluding it.
I'm defining my MenuButton frames as shown:
MenuButton *deliveriesButton = [MenuButton buttonWithType:UIButtonTypeCustom];
[deliveriesButton setTitle:#"Deliveries" forState:UIControlStateNormal];
[deliveriesButton setTitleColor:[UIColor colorWithRed:25.0/255.0
green:23.0/255.0
blue:16.0/255.0
alpha:1.0]
forState:UIControlStateNormal];
[deliveriesButton.titleLabel setFont:[Constants lightFontOfSize:39]];
[deliveriesButton sizeToFit];
deliveriesButton.center = CGPointMake(viewWidth/2,
menuBarHeight / 2);
[self.view addSubview:deliveriesButton];
_deliveriesButton = deliveriesButton;
Using the solution referenced by Justin Voss in the comments above, I went through the UIViews in my UIViewController and set:
view.userInteractionEnabled = NO;
on any view that I did not need to have a selection on (including background UIImageView objects). This resolved the problem.
Hope this helps someone else

Show touch when clicked UIButton Objective-C

I have a UIButton that has only an UIImage set, when Clicked (long press) the images changes automatically with a shadow, What I want is that even if the button gets clicked but not with a long press the images should have the shadow. I already tried from IB to set the UIButton properties Reverse on Highlight and Shows Touch On Highlight but with no results
This is about UIControl Class. It's default to be with shadow. So if you wanna customize it, you should addTarget to your button to every action on UIButton like tapping,long press,touchUpInside and I think it s not about long press it's just you can't realize the difference on tapping.
in one of my project I customize my button actions like this:
buyButton = [[UIButton alloc] initWithFrame:CGRectMake(self.frame.size.width*3/4-2, 0, self.frame.size.width/4+4, self.frame.size.height)];
[buyButton addTarget:self action:#selector(buyButtonClicked:) forControlEvents:UIControlEventTouchDown];
[buyButton addTarget:self action:#selector(buyButtonNormal:) forControlEvents:UIControlEventTouchUpInside];
[buyButton addTarget:self action:#selector(buyButtonNormal:) forControlEvents:UIControlEventTouchUpOutside];
and methods of this like:
- (void) buyButtonClicked:(UIButton *) sender {
if ([self.backgroundColor isEqual:[Util UIColorForHexColor:#"fede32"]]) {
self.backgroundColor = [Util UIColorForHexColor:#"fdca2e"];
}
else if([self.backgroundColor isEqual:[Util UIColorForHexColor:#"cfd3dc"]]) {
self.backgroundColor = [Util UIColorForHexColor:#"c0c5d0"];
}
}
- (void) buyButtonNormal:(UIButton *) sender {
if ([self.backgroundColor isEqual:[Util UIColorForHexColor:#"fdca2e"]]) {
self.backgroundColor = [Util UIColorForHexColor:#"fede32"];
}
else if([self.backgroundColor isEqual:[Util UIColorForHexColor:#"c0c5d0"]]) {
self.backgroundColor = [Util UIColorForHexColor:#"cfd3dc"];
}
[delegate purchaseOffer:selectedOffer];
}
If you need more information about UIButton actions there are a lot of question on this site.

Cycling through Image Array within Object in Time Intervals (Objective-C)

My general question is how do you have an object with an image array:
#import <Foundation/Foundation.h>
#interface Object: NSObject {
UIImage *image[imageNumber];
}
And then take these images and apply them to a button in a different class, starting with imageArray[0] and every few seconds changing it to imageArray[1], etc, but stopping the loop at the last image.
What I specifically did was create a Plant object:
#import <Foundation/Foundation.h>
#interface Plant : NSObject {
UIImage *plantImage[3];
int imageNumber; //to specify which image to display, increments with timer
NSTimer *plantImageTimer;
}
and declared then made a few methods like
-(void)addPlantImages:(UIImage *) firstImage withPlantImage2:(UIImage *) secondImage withPlantImage3:(UIImage *) thirdImage{
plantImage[0] = firstImage;
plantImage[1] = secondImage;
plantImage[2] = thirdImage;
}
//this makes the Plant into a button
-(void)createPlantButtonForPlant:(Plant *) plantType forView:(UIView *) view withButtonRect:(CGRect) buttonRect{
imageNumber=0;
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = buttonRect;
button.hidden = NO;
[view addSubview:button];
[plantType growPlant:button]; //explained in code below
}
And from here I don't know what to do anymore.
I tried using an NSTimer, but you can't put parameters into the selector, so I can't specify which button (or Plant) I want to cycle images through.
Extra tidbits of code in Plant that I have (which do not work); I'm using NSTimer userinfo incorrectly, but I don't understand how to use it, to be honest.
-(void)growPlant:(UIButton *) button{
plantImageTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(changePlantImage:) userInfo:button repeats:YES];
}
-(void)changePlantImage: (UIButton *) plantButton{
if(imageNumber == 3){
[plantImageTimer invalidate];
} else {
[plantButton setImage:plantImage[imageNumber] forState:UIControlStateNormal];
imageNumber++;
}
}
I imported Plant into my view controller (called PracticeViewController) and tried to make it so that when I clicked a button, a Plant button popped up and cycled through the images.
(void)buttonAction{
theButton.hidden = YES; //I did make this button, just didn't add the code here. Declared in header.
CGRect imageViewRect = CGRectMake(100, 100, 100, 100);
Plant *testPlant = [Plant new];
[testPlant addPlantImages:[UIImage imageNamed:#"plant2.png"] withPlantImage2:[UIImage imageNamed:#"plant2.png"] withPlantImage3:[UIImage imageNamed:#"plant2.png"];
[testPlant createButtonForPlant:testPlant forView:self.view withButtonRect:imageViewRect];
}
If you need more code or other information, just comment below and I will reply asap.
Now that I've done more programming, I realize how complicated I made this code lol. Anyway, all I would have had to do was add
[button addTarget:self action:#selector(changePlantImage) forControlEvents:UIControlEventTouchUpInside];
after making the button instance. This would then scroll through whichever images the plant had in its array.

UIButton does not detect touch events when clicked

I've created a tableview that has custom cells (I've subclassed UITableViewCell).
I'm creating several UIButtons in it. Declaring this in the .h file:
#property (nonatomic, strong) UIButton *myButton;
and this in the .m file:
myButton = [[UIButton alloc] initWithFrame:CGRectMake(-100.0, 285.0, 60.0, 30.0)];
myButton.titleLabel.font = [UIFont boldSystemFontOfSize:16.0];
myButton.backgroundColor = [UIColor clearColor];
[myButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[myButton setTitle:#"text" forState:UIControlStateNormal];
[myButton addTarget:self action:#selector(myButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:myButton];
I'm moving the cell to the right using UIPanGestureRecognizer and then the UIButton is revealed (notice that it is in a negative X index).I can see it but it is not clickable (I guess it is not in the view any more).
Any suggestion about how to make it clickable?
More details:
In the init of the cell, I'm doing:
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
panGesture.delegate = self;
[self.contentView addGestureRecognizer:panGesture];
Then I implemented the gesture:
-(void)handlePanGesture:(UIPanGestureRecognizer *)sender {
CGPoint translate = [sender translationInView:self.contentView];
CGRect currentFrame = self.contentView.frame;
switch ([sender state]) {
case UIGestureRecognizerStateChanged:
currentFrame.origin.x = translate.x;
self.contentView.frame = currentFrame;
break;
default:
break;
}
}
When the frame moves to the right - the button is revealed. But not clickable...
If a button's frame is outside that of its parent's frame, it will not register touches. In this case, you mention that your button stops working when its frame's x location is set to -100. This makes sense because it is outside the touch area.
Your pan gesture you implemented moves the cell's view, so while the button may appear on screen, it is still OUTSIDE of the cell's view, hence it cannot receive touches.
One possible suggestion for fixing this would be to make your cells bigger from the start. So for example, if a cell's frame size is currently 0,0,320,44, you could instead make it -100,0,420,44 and place the contents of your cell accordingly. Now, your button's frame would change to 0,0,x,y and it would be inside of the cell's view and able to receive touches.

How can I create a ToggleButton in Obj-C? Skin the UISwitch or subclass the UIButton? [duplicate]

Is there either a way to implement UISwitch with custom graphics for the switch-states?
Or as an alternative the other way round, an UIButton with UISwitch functionality?
UIButton already supports a "switch" functionality.
Just set a different image in Interface Builder for the "Selected State Configuration", and use the selected property of UIButton to toggle its state.
set the image to show on selected state:
[button setImage:[UIImage imageNamed:#"btn_graphics"] forState:UIControlStateSelected];
and then on touch up inside selector, set:
button.selected = YES;
if you want this to cancel another button's selection, set:
otherButton.selected = NO;
To build on what PGB and nurne said above, after you set your states and attach a selector (event method) you would want to put this code in that selector.
- (IBAction)cost:(id)sender
{
//Toggle current state and save
self.buttonTest.selected = !self.buttonTest.selected;
/**
The rest of your method goes here.
*/
}
For programmatically inclined:
-(void) addToggleButton {
CGRect aframe = CGRectMake(0,0,100,100);
UIImage *selectedImage = [UIImage imageNamed:#"selected"];
UIImage *unselectedImage = [UIImage imageNamed:#"unselected"];
self.toggleUIButton = [[UIButton alloc] initWithFrame:aframe];
[self.toggleUIButton setImage:unselectedImage forState:UIControlStateNormal];
[self.toggleUIButton setImage:selectedImage forState:UIControlStateSelected];
[self.toggleUIButton addTarget:self
action:#selector(clickToggle:)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.toggleUIButton];
}
-(void) clickToggle:(id) sender {
BOOL isSelected = [(UIButton *)sender isSelected];
[(UIButton *) sender setSelected:!isSelected];
}