In Cocos2d, I have read that
[[[[CCDirector sharedDirector] openGLView] window] addSubview:someButton];
will add a UIView to the main window: http://www.cocos2d-iphone.org/forum/topic/3588
Yet in my code I have this:
- (void)onEnterTransitionDidFinish {
UIButton* button = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[[[[CCDirector sharedDirector] openGLView] window] addSubview:button];
}
But no button is visible. This method is part of a CCLayerColor which is the first scene presented in the app, if that matters. What am I doing wrong here? Thanks!
Edit: I can confirm that the buttons are being added to the windows subviews, because NSLogging
[[[[[CCDirector sharedDirector] openGLView] window] subviews] count]
shows a difference when I comment/uncomment the addSubview line. So why isn't the button showing up?
Edit 2:
Thanks to #Marine, I have found that my problem is the way I am declaring my button; using buttonWithType: solved the problem, because this code works:
UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(100, 100, 100, 100)];
[[[[CCDirector sharedDirector] openGLView] window] addSubview:button];
Can someone explain to me why using this class method works and using initWithFrame: doesn't? Because I would rather not create lots of autoreleased objects, and also because I have some UIButton subclasses that do NOT show up when I use the buttonWithType: method.
Edit 3 (Solution):
The reason why using anything but buttonWithType: doesn't work is that if you do not use that method to create the button, the background color of the button is not set, and by default it is clearColor. Using [button setBackgroundColor:[UIColor redColor]] or any other color fixes the problem. Also, if using a custom button class like this one, you might need to manually call [button awakeFromNib] if the button isn't connected to a nib.
Try the below code it would help you
-(id) init
{
if((self = [super init]))
{
UIView* glView = (UIView*) [[CCDirector sharedDirector] openGLView];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(100, 100, 250, 250)];
[btn addTarget:self action:#selector(actionper:) forControlEvents:UIControlEventTouchUpInside];
[glView addSubview:btn];
}
return self;
}
-(void) actionper : (id) sender
{
printf("\n Stuff of the Code on button Press");
}
I have posted the solution to the problem as an edit to the question.
Try using the bringsubviewtofront method of the OpenGL window passing the recently added button as the argument. Also make sure that the frame of your button is such that it is in the visible part of the screen. Try playing around with it's position.
Related
I have a UIButton on which I attached an UIControlEventTouchUpInside action. This button is inserted in a UIScrollView.
My problem is: touch events won't work until I hold on the button for a certain time. If I tap on it directly, or just click on it in the simulator, it won't work.
The thing is: when I just click on it, pointInside:withEvent: is actually triggered and returns YES. What could possibly prevent the event from being fired?
Try setting the delaysContentTouches property of your scrollView to NO.
It should work so you can check the following eg.:
1) make sure that you button is properly added to scrollview. For example like this:
...
myScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
myScrollView.bounces = NO;
[myScrollView setScrollEnabled:YES];
myScrollView.showsHorizontalScrollIndicator = NO;
myScrollView.delegate = self;
myScrollView.pagingEnabled = YES;
[self.view addSubview:myScrollView];
myScrollView.contentSize = CGSizeMake(320*5, 480);
...
UIButton *mybutton = [UIButton buttonWithType:UIButtonTypeCustom];
mybutton.frame = CGRectMake(0,0,100,100);
mybutton.tag = 1
[mybutton addTarget:self action:#selector(pressedmybutton:)
forControlEvents:UIControlEventTouchUpInside];
[myScrollView addSubview:bu];
2) make sure that button is top of the view stack. For testing purpose add at the end of the view init code [mybutton bringSubviewToFront];
3) test it on device and not just in Simulator. I experienced different scrolling/button pressing behavior in Simulator than on real device (which is the better for testing this out).
I have view hierarchy as follows
MyViewController --> ScrollView(added via IB) --> ImageView (+ zooming there) ---> button added on image View(added via code)
imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"map.png"]];
[scroll addSubview:imageView];
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
myButton.frame = CGRectMake(660, 120, 40, 40);
[myButton setTitle:#"10" forState:UIControlStateNormal];
[myButton addTarget:self action:#selector(asiaPressed:) forControlEvents:UIControlEventTouchUpInside];
[myButton setEnabled:YES];
[imageView addSubview:myButton];
later on in view controller, i defined selector as
-(void) asiaPressed:(id)sender{
NSLog(#"asiaPressed clicked");
}
But it is never going inside selector..
Pls help...i guess it is very basic error..
Thanks in advance
UIImageView has userInteractionEnabled property set to NO by default so it (and its subviews) does not receive touch events. You need to set that property to YES manually:
...
imageView.userInteractionEnabled = YES;
...
P.S. You also mention gesture recognizer in question title, however have not posted any code with it - so if it present it may also cause the problems, but the problem is most likely is what I described above
I want to create a new UIView on button click programmatically in cocos2d. Kindly help me with some sample code. Thanks in advance.
You have to create a button like-
UIButton* myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame = CGRectMake(30, 70,100,38); //set frame for button
[myButton setTitle:#"subview" forState:UIControlStateNormal];
[myButton addTarget:self action:#selector(buttonClicked:)forControlEvents:UIControlEventTouchUpInside];
Or you can use CCMenu as a button.
And then write the event handling function-
-(void)buttonClicked:(id)sender
{
UIView *myview=[[UIView alloc] initWithFrame: CGRectMake(0, 0,320,480)];
myview.backgroundColor=[UIColor redColor];
[[[CCDirector sharedDirector] openGLView] addSubview:myview];
[myview release];
}
}
As you wrote above, the class is called UIView. It's really simple to create a new View. Take a look at this code snippet.
-(void)youButtonAction:(id)sender {
//This method is executed as soon as you button is pressed.
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)];
[anotherView addSubview:newView]; //Add the newView to another View
[newView release];
}
I hope you got the point. At first you have to create the view, than add it to another view and in the end release it. ;-)
Sandro Meier
Ive got an iPhone/iPad universal application and I wanted to have a custom navigation bar where the top half of the nav bar contained our companies logos, and the bottom half was the standard navigation bar.
I figured out how to do this, showing in the code below, but my UIButton "logosButton" doesnt always respond to being clicked, it appears as though only certain parts of the button are active, and others dont do anything at all... I cannot figure out why this is.
- (void)viewDidLoad {
[super viewDidLoad];
[[self view] addSubview: navController.view];
float width = IS_IPAD ? 768.0f : 320.0f;
float logosHeight = IS_IPAD ? 20.0f : 20.0f;
float barHeight = IS_IPAD ? 32.0f : 32.0f;
self.navBar = [[UINavigationBar alloc] initWithFrame: CGRectMake(0.0f, logosHeight, width, barHeight)];
UIView *tempView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, logosHeight)];
UIButton *logosButton = [[UIButton alloc] init];
[logosButton setBackgroundImage:[UIImage imageNamed:#"logo_bar_alone.png"] forState:UIControlStateNormal];
[logosButton setBackgroundImage:[UIImage imageNamed:#"logo_bar_alone.png"] forState:UIControlStateHighlighted];
[logosButton addTarget:self action:#selector(logosButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[logosButton setFrame: CGRectMake(0, 0, width, logosHeight)];
[tempView addSubview: logosButton];
[[self view] addSubview: tempView];
[tempView release];
[[self view] addSubview: self.navBar];
self.navItem = [[UINavigationItem alloc] initWithTitle: #"Home"];
[self.navBar pushNavigationItem:self.navItem animated:NO];
}
The method: logosButtonClicked does get fired every now and then when I click on the UIButton, but I clearly am clicking on certain spots where nothing happens at all...
Very frustrating, I dont seem, to see a pattern in regards to where its active, but could someone please help out here?
EDIT
I think I have just stumbled across something, I changed the button to a UIButtonTypeRoundedRect and got rid of the images (and also made it larger) and it appears that I cannot click on the bottom OR top sections of the button where the button is rounded. So the middle rectangular section is the only section where I can click... why would this be?
EDIT 2
For anyone reviewing this question, please see taber's latest edit on his answer. The Navigation Controller is eating touches for some reason, and I need to figure out why this is so, could be a bug?
FINAL ANSWER :)
Okay after reviewing the project it looks like the UINavigationController that is positioned below the button is eating touches globally. Which is definitely weird because it was added as a subview BELOW your button. So there must be some kind of funky frame/touch-eating going on with the UINavigationController. I tried to set navigationController.titleView.userInteractionEnabled = NO but to no avail. If anyone knows how to basically make UINavigationController and UINavigationBar not eat touches (I'm talking about the background where no buttons exist) then please chime in. The UIButton touches work just fine when the UINavigationController isn't added to the view.
Original Answer
It may be some other UI elements in [self view] or tempView sitting on top of the button and intercepting taps. You might want to try either commenting out everything else in the view(s) and/or try setting the userInteractionEnabled property on them like this:
[otherUIElement setUserInteractionEnabled: NO];
EDIT:
This code makes it so that you CAN click the round rect edges but NOT the title text. So I suspect that it's some sort of subview preventing the button from catching the tap.
[logosButton addTarget:self action:#selector(logosButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[logosButton setFrame: CGRectMake(0, 0, 320.0, 50.0)];
[logosButton setTitle: #"HELLO" forState: UIControlStateNormal];
[logosButton.titleLabel setUserInteractionEnabled: YES];
EDIT #2:
Try using this subclassed button and see if the issue still occurs:
// NavBtn.h
#interface NavBtn : UIButton {
}
-(id)initWithTitle:(NSString *)text;
#end
// NavBtn.m
#import "NavBtn.h"
#implementation NavBtn
- (id)initWithTitle:(NSString *)text {
if ((self = [super initWithFrame: CGRectMake(0, 0, 320, 50)])) {
[self setTitle: text forState: UIControlStateNormal];
self.backgroundColor = [UIColor clearColor];
self.opaque = NO;
[self setBackgroundImage:[UIImage imageNamed:#"logo_bar_alone.png"] forState: UIControlStateNormal];
[self setBackgroundImage:[UIImage imageNamed:#"logo_bar_alone.png"] forState: UIControlStateHighlighted];
}
return self;
}
// i guess you shouldn't need to mess with layoutSubviews
#end
To load it into your view:
#import "NavBtn.h"
... in viewDidLoad, etc ...
NavBtn *btn = [[NavBtn alloc] initWithTitle: #"hey"];
[self.view addSubview: btn];
[btn release];
If THAT doesn't work, there's got to be some kind of third party library doing some funky category overriding of your UIButton class or something.
been looking at this for days..
- (void)viewDidAppear:(BOOL)animated {
#if !TARGET_IPHONE_SIMULATOR
UIButton *returnButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
returnButton.frame = CGRectMake(0, 0, 100, 100);
[returnButton setTitle:#"Tap here to return" forState:UIControlStateNormal];
[returnButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:returnButton];
[self.view bringSubviewToFront:returnButton];
[[self cameraController] setCameraOverlayView:[self view]];
[self presentModalViewController:[self cameraController] animated:YES];
[[self view] setFrame:[[[self cameraController] view] bounds]];
#endif
[super viewDidAppear:animated];
}
I think you need to hide the defaul camera control first by using : [[self cameraController] setShowsCameraControls:NO] . See more here
The default value of this property is YES, which specifies that the default camera controls are visible in the picker. Set it to NO to hide the default controls if you want to instead provide a custom overlay view using the cameraOverlayView property.
[[self cameraController] setCameraOverlayView:[self view]]; is almost certainly wrong. When viewDidAppear: is called, your view is already in the view hierarchy. Suddenly setting it as the cameraOverlayView is unlikely to do the right thing.