touchevents not triggering from inside subview - iphone

I'm having my share of trouble trying to get a touch event through a UIView to it's attached childviews.
I have a number of images I want to do various things with, so I'm interested in reading the touch events on them. It worked fine until I decided to group them in a UIView, so I'm guessing I need to switch some setting on or off to let the events through.
[TouchImageView.h] -------------------------------------------------------
#interface TouchImageView : UIImageView
[TouchImageView.m] -------------------------------------------------------
- (id)initWithFrame:(CGRect)aRect {
if (self = [super initWithFrame:aRect]) {
// We set it here directly for convenience
// As by default for a UIImageView it is set to NO
self.userInteractionEnabled = YES;
state = 0 ;
rect = aRect ;
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// Do what you want here
NSLog(#"touchesBegan!" );
}
[in my delegate's didFinishLaunchingWithOptions] -------------------------
NSArray *myImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"front-photos.jpg"],
[UIImage imageNamed:#"front-films.jpg"],
[UIImage imageNamed:#"front-presentations.jpg"],
mainMenuView = [[UIView alloc] init ] ;
mainMenuView.userInteractionEnabled = YES; // tried setting this to both YES and NO. Same result.
[self.viewController.view addSubview:mainMenuView] ;
myImage = [[TouchImageView alloc] initWithFrame:CGRectMake(0.0f, menuTopHeight, menuButtonWidth, menuButtonHeight)];
[myImage setImage:[myImages objectAtIndex:0]] ;
[mainMenuView addSubview:myImage] ;
Can someone tell me what I'm doing wrong? I've seen a lot of similar posts here on SO on this topic, but most of them about setting userInteractionEnabled(?)

It turns out that I needed to define a frame for the UIView. So I changed
mainMenuView = [[UIView alloc] init] ;
into this:
mainMenuView = [[UIView alloc] initWithFrame:[UIScreen mainScreen] bounds] ;
and it worked again.

First of all mainMenuView.userInteractionEnabled = NO; should be YES
Also UIImageView has userInteractionEnabled set to NO by deafult, so you will have to set it to YES
After this line
[mainMenuView addSubview:myImage] ;
//add
myImage.userInteractionEnabled = YES;

Related

How do I programmatically add a UIImage to a UIImageView then add that UIImageView to another UIView?

As the title says, I'm trying to create a UIImage that will go inside a UIImageView (so that I can animate it later) then I want to put that UIImageView into another classes UIView.
So far my relevant code is:
This is the viewDidLoad for my root view controller:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.playerViewController = [[TUKIPlayerViewController alloc] init];
[self.view addSubview:playerViewController.view];
}
And this is the init for the UIImageView:
- (id)init
{
if (self = [super init]) {
playerIdle = [UIImage imageNamed:#"playerIdle.png"];
playerView = [[UIImageView alloc] initWithImage:playerIdle];
self.view = playerView;
}
return self;
}
It builds and runs with 0 errors.
What am I doing wrong? I don't see the playerIdle.png anywhere. Though I'm betting I'm doing this terribly wrong.
In your ViewController , add the imageview directly...
- (void)viewDidLoad
{
playerView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"playerIdle.png"]];
[self.view addSubView: playerView];
}
Try this:
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"name.png"]];
[self.view addSubview:imgView];
Pls try the below code :
- (id)init
{
if (self = [super init]) {
playerIdle = [UIImage imageNamed:#"playerIdle.png"];
playerView = [[UIImageView alloc] initWithImage:playerIdle];
[self.view addSubview:playerView];
}
return self;
}
Hope this might help you.....
You should use [self.view addSubview:playerView]; instead of just setting it(self.view = playerview;). What I also do most of the times is bringing that subview to the front:
[self.view bringSubviewToFront:playerView];
Hope it helps
Or you could try:
myUIImageViewObject.image = myUIImageObject;
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"name.png"]];
imagView.frame=CGRectMake(40,130,45,45);
[self.view addSubview:imgView];

how to rotate view with navigation controll?

#implementation MainViewController
#synthesize scrollView,imageView;
- (id) init {
if (self != nil) {
self.title = #"Evolution";
}
return self;}
- (void)viewDidLoad {
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected:)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
int numberOfImages = 32;
CGFloat currentX = 0.0f;
for (int i=1; i <= numberOfImages; i++) {
// create image
NSString *imageName = [NSString stringWithFormat:#"page-%d.jpg", i];
UIImage *image = [UIImage imageNamed:imageName];
imageView = [[UIImageView alloc] initWithImage:image];
// put image on correct position
CGRect rect = imageView.frame;
rect.origin.x = currentX;
imageView.frame = rect;
// update currentX
currentX +=454; //mageView.frame.size.width;
[scrollView addSubview:imageView];
[imageView release];
}
[scrollView addGestureRecognizer:tapGesture];
scrollView.contentSize = CGSizeMake(currentX, 800);
scrollView.pagingEnabled=YES;
scrollView.userInteractionEnabled = YES;
scrollView.maximumZoomScale = 15;
scrollView.minimumZoomScale = 0.5;
scrollView.bounces = NO;
scrollView.bouncesZoom = NO;
scrollView.delegate = self;
scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[self.view addSubview:scrollView];
[scrollView release];
[super viewDidLoad];}
- (BOOL)shouldAutorotateToInterfaceOrientation(UIInterfaceOrientation)interfaceOrientation{
return YES;}
-(void)tapDetected:(UIGestureRecognizer*)recognizer{
ImageViewController *settings = [[ImageViewController alloc] init];
[self.navigationController pushViewController:settings animated:YES];
[settings release];}
#end
#implementation ImgScrollViewAppDelegate
#synthesize window;#synthesize viewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application{
LogMethod();
// If you want the status bar to be hidden at launch use this:
// application.statusBarHidden = YES;
//
// To set the status bar as black, use the following:
// application.statusBarStyle = UIStatusBarStyleBlackOpaque;
// Create window
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// this helps in debugging, so that you know "exactly" where your views are placed;
// if you see "red", you are looking at the bare window, otherwise use black
// window.backgroundColor = [UIColor redColor];
viewController = [ [ MainViewController alloc ] init ];
navigationController = [ [ UINavigationController alloc ] initWithRootViewController: viewController ];
/* Anchor the view to the window */
[window addSubview:[navigationController view]];
/* Make the window key and visible */
[window makeKeyAndVisible];
}
#end
in above code i have problem that is when check it on simulator then rotate device left and right. But view not change and i want to change it. how i modify it?
In your view controller implementation there is a method - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation. If you want it to rotate to any orientation, make it return YES. If you only want it to autorotate to some orientations, add an if statement to check and return yes or no.

Put small images on the top of UIImageView?

I've got a UIImageView in a page that gets its image from the Interface builder and I'm trying to put small icons on the top of it (it's a small map and I want to put icons on it). I know it's probably very simple but I tried to look it up in the documentation but it pretty much got me more confused.
Using Interface Builder, can't you just drag a UIImageView into an existing UIImageView? In effect, you end up with one UIImageView embedded within another.
You should also be able to easily set the hidden property of the "small map" UIImageView in code, depending on if that UIImageView is needed or not.
Hope this helps. Good Luck.
Let It Be Known
you could compose your own UIView by adding both the large and small UIViewImage views.
I have illustrated my approach below with the Pseudocode .
-(id) initwithFrame:(CGRect) frame
{
if(self = [super initWithFrame:frame])
{
iContainer = [[UIView alloc] initWithFrame:frame];
[iContainer addSubViews:iLargerUIImageView];
[iContainer addSubViews:iSmallUIImageView];
[self.view addSubViews:iContainer];
}
return self;
}
-(void) layoutSubviews
{
CGRect myRect = self.frame;
iContainer.frame = myRect;
//Give the location to iLargerUIImageView as per your requirement.
iLargerUIImageView.frame = CGRectMake(...,...,...,...);
//Give the location to iSmallUIImageViewas per your requirement.
iSmallUIImageView.frame = CGRectMake(...,...,...,...);
}
-(void) dealloc
{
[iContainer release];
[iLargerUIImageView release];
[iSmallUIImageView release];
}
try this code:
UIImageView *backgroundImageView = (UIImageView *)[self viewWithTag:kBckGndImag];
if(!backgroundImageView){
UIImage *imageName = [UIImage imageNamed:kpointsChartBig];
backgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(15, 15, imageName.size.width, imageName.size.height)];
backgroundImageView.image=imageName;
[backgroundImageView setTag:kBckGndImag];
[pointImageView addSubview:backgroundImageView];
[backgroundImageView release];
}
UIImageView *foregroundImageView = (UIImageView *)[self viewWithTag:kForGndImage];
if(!foregroundImageView){
foregroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:kpointsColoredChartBig]];
foregroundImageView.contentMode = UIViewContentModeLeft;
foregroundImageView.clipsToBounds = YES;
[pointImageView addSubview:foregroundImageView];
[foregroundImageView release];
}

After creating a UIView with initWithFrame, how do I change the image?

I'm a bit lost here. I have a class subclassed from UIView called BalloonGuy. I initialize it like this.
- (id)initWithFrame:(CGRect)frame {
UIImage* loadedImage = [UIImage imageNamed:#"balloonguy.png"];
CGRect rect = CGRectMake(0, 0, loadedImage.size.width, loadedImage.size.height);
self = [super initWithFrame:rect];
image=[loadedImage retain];
self.opaque = YES;
self.backgroundColor = [UIColor clearColor];
return self;
}
I add it as a subview and everything is great.
What I can't do, however is change the image afterwards, ever. I won't list my failed attempts but what do I do?
I think you'll need to redraw your view when you change your image property, so overriding the property setter in this case may be a good idea:
- (void) setImage:(UIImage *) im {
[image release];
image = nil;
image = [im retain];
[self setNeedsLayout];
}

Need to override drawrect if your UIView is merely a container?

According to Apple's docs, "Subclasses need not override -[UIView drawRect:] if the subclass is a container for other views."
I have a custom UIView subclass that is indeed merely a container for other views. Yet the contained views aren't getting drawn. Here's the pertinent code that sets up the custom UIView subclass:
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
{
// Consists of both an "on" light and an "off" light. We flick between the two depending upon our state.
self.onLight = [[[LoyaltyCardNumberView alloc] initWithFrame:frame] autorelease];
self.onLight.backgroundColor = [UIColor clearColor];
self.onLight.on = YES;
[self addSubview:self.onLight];
self.offLight = [[[LoyaltyCardNumberView alloc] initWithFrame:frame] autorelease];
self.offLight.backgroundColor = [UIColor clearColor];
self.offLight.on = NO;
[self addSubview:self.offLight];
self.on = NO;
}
return self;
}
When I run the code that displays this custom UIView, nothing shows up. But when I add a drawRect method...
- (void)drawRect:(CGRect)rect
{
[self.onLight drawRect:rect];
[self.offLight drawRect:rect];
}
...the subviews display. (Clearly, this isn't the right way to be doing this, not only because it's contrary to what the docs say, but because it -always- displays both subviews, completely ignoring some other code in my UIView that sets the hidden property of one of the views, it ignores the z-ordering, etc.)
Anyway, the main question: why don't my subviews display when I'm not overriding drawRect:?
Thanks!
UPDATE:
Just to make sure that the problem doesn't lie in my custom subviews, I added in a UILabel as well. So the code reads:
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
{
// Consists of both an "on" light and an "off" light. We flick between the two depending upon our state.
self.onLight = [[[LoyaltyCardNumberView alloc] initWithFrame:frame] autorelease];
self.onLight.backgroundColor = [UIColor clearColor];
self.onLight.on = YES;
[self addSubview:self.onLight];
self.offLight = [[[LoyaltyCardNumberView alloc] initWithFrame:frame] autorelease];
self.offLight.backgroundColor = [UIColor clearColor];
self.offLight.on = NO;
[self addSubview:self.offLight];
self.on = NO;
UILabel* xLabel = [[[UILabel alloc] initWithFrame:frame] autorelease];
xLabel.text = #"X";
[self addSubview:xLabel];
}
return self;
The "X" doesn't display either.
UPDATE 2:
Here's the code that invokes my custom UIView (OffOnLightView):
// Container for all of the OffOnLightViews...
self.stampSuperView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)] autorelease];
[self.view addSubview:self.stampSuperView];
// Draw the stamps into the 'stamp superview'.
NSInteger numberOfCardSpaces = (awardType == None) ? 3 : 10;
for (NSInteger i = 1; i <= numberOfCardSpaces; i++)
{
OffOnLightView* newNumberView = [[[OffOnLightView alloc] initWithFrame:[self frameForStampWithOrdinal:i awardType:awardType]] autorelease];
newNumberView.on = (i <= self.place.checkInCount.intValue);
newNumberView.number = [NSString stringWithFormat:#"%d", i];
[self.stampSuperView addSubview:newNumberView];
}
Your subviews should have their frame initialized to the bounds of the parent uiview. Subviews are in a different coordinate system that is relative to the frame of the parent.
self.onLight = [[[LoyaltyCardNumberView alloc] initWithFrame:self.bounds] autorelease];
You should never call -drawRect: manually. If you need to force a redraw, call -setNeedsDisplay.
I would start by debugging (breakpoint or NSLog()) in the -drawRect: methods of the two subviews you are adding to make sure they are actually performing their drawing.
Also note how you're making both subviews the full size (frame) of the containing view, and setting their background colours to clear. I'm going to guess this is intentional, but it's possible they are displaying, but you just can't see anything due to them having a transparent background.