UIButtons don't respond to touch after set frame on autorotate - iphone

Hello in my app i have some uiButtons added as subviews to a view like in the picture below.
alt text http://img99.imageshack.us/img99/5244/portraitc.png
when the user rotates the phone in landscape the views and buttons must change position to this:
alt text http://img193.imageshack.us/img193/5931/landscapeq.png
initially when the view is in portrait mode the buttons respond to touches. If i tilt the phone the buttons move, everything looks ok like in the second image and the buttons respond to touches. If i tilt the phone back to portrait mode, the buttons move back they look ok but they don't respond to touches. If i change back to landscape the buttons work...
my buttons are created like this:
nextNewsP = [[UIButton alloc] initWithFrame:CGRectMake([[UIScreen mainScreen] bounds].size.width - 40, 10, 25, 25)];
[nextNewsP setImage:[UIImage newImageFromResource:#"next_arrow.png"] forState:UIControlStateNormal];
[nextNewsP addTarget:self action:#selector(nextNewsAction:) forControlEvents:UIControlEventTouchUpInside];
[nextNewsP setShowsTouchWhenHighlighted:TRUE];
[bottomTools addSubview:nextNewsP];
[nextNewsP release];
previousNewsP = [[UIButton alloc] initWithFrame:CGRectMake([[UIScreen mainScreen] bounds].size.width - 85, 10, 25, 25)];
[previousNewsP setImage:[UIImage newImageFromResource:#"previous_arrow.png"] forState:UIControlStateNormal];
[previousNewsP addTarget:self action:#selector(previousNewsAction:) forControlEvents:UIControlEventTouchUpInside];
[previousNewsP setShowsTouchWhenHighlighted:TRUE];
[bottomTools addSubview:previousNewsP];
[previousNewsP release];
bottomTools is a view and is added also as a subview like this:
[self.view addSubview:bottomTools];
[bottomTools release];
and my shouldAutorotateToInterfaceOrientation function looks like this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
[UIView beginAnimations:#"moveViews" context: nil];
if(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
NSLog(#"set frames for portrait");
closeView.frame = CGRectMake([[UIScreen mainScreen] bounds].size.width - 30, 2, 23, 25);
newsInfo.frame = CGRectMake(10, 10, [[UIScreen mainScreen] bounds].size.width - 10, 22);
internetActivityIndicator.frame = CGRectMake([[UIScreen mainScreen] bounds].size.width - 55, 5, 18, 18);
industryLabel.frame = CGRectMake([[UIScreen mainScreen] bounds].size.width/2.0 - [industryTitle sizeWithFont:[UIFont systemFontOfSize:14]].width/2, 3, [industryTitle sizeWithFont:[UIFont systemFontOfSize:14]].width, 22);
bottomTools.frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.height-40, [[UIScreen mainScreen] bounds].size.width, 40);
nextNewsP.frame = CGRectMake([[UIScreen mainScreen] bounds].size.width - 40, 10, 25, 25);
previousNewsP.frame = CGRectMake([[UIScreen mainScreen] bounds].size.width - 85, 10, 25, 25);
}
else
{
NSLog(#"set frames for landscape");
closeView.frame = CGRectMake([[UIScreen mainScreen] bounds].size.height - 30, 2, 23, 25);
newsInfo.frame = CGRectMake(10, 10, [[UIScreen mainScreen] bounds].size.height - 10, 22);
internetActivityIndicator.frame = CGRectMake([[UIScreen mainScreen] bounds].size.height - 55, 5, 18, 18);
industryLabel.frame = CGRectMake([[UIScreen mainScreen] bounds].size.height/2.0 - [industryTitle sizeWithFont:[UIFont systemFontOfSize:14]].width/2, 3, [industryTitle sizeWithFont:[UIFont systemFontOfSize:14]].width, 22);
bottomTools.frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.width-40, [[UIScreen mainScreen] bounds].size.height, 40);
nextNewsP.frame = CGRectMake([[UIScreen mainScreen] bounds].size.height - 40, 10, 25, 25);
previousNewsP.frame = CGRectMake([[UIScreen mainScreen] bounds].size.height - 85, 10, 25, 25);
}
[UIView commitAnimations];
return YES;
}
did you ever had a similar problem?
thank you in advance,
Sorin

I am actually still struggling with the same problem (a year later ... need iOS 3.0 compatibility). The rotation part was easy. However, the views and buttons don't seem to process touch and move/drag events. I've verified that the window (UIWindow) is receiving the touch events and at the right locations.
It's as if the last 1/3 of the screen (i.e. 480-320) doesn't propagate events to receivers after a rotation to landscape from portrait.
The example in the link by slf doesn't help since the rotated view controller doesn't have responders.
I just figured it out after some view digging. So, I was rotating the viewController.view and doing a bunch of setNeedsLayout on subviews of viewController.view. However, what I needed to do was [self.navigationController.view setNeedsLayout]. That one call fixed everything for me. For whatever reason, the navigationController.view wasn't passing touch events to the part of the subviews that were previously hidden (as far as the frame/bound is concerned). That actually fixed a number of other issues as well.

I think your problem is in your frame adjustment. My gut tells me it has something to do with the logic being inside shouldAutorotateToInterfaceOrientation because that happens before the rotation is actually done. Try doing your math the way they do it in this article and see if that helps.

I've fixed the problem I was having .. I basically needed to do [self.navigationController.view setNeedsLayout].
The way I understand this (which maybe incorrect is that self.navigationController.view.frame was same as self.view.frame and both were equal to (x=0,y=0,width=320,height=480). I then rotated self.view by M_PI/2 and did a number of frame manipulation on select self.view.subviews to get everything to animate/position/scale correctly.
That worked out okay but the navigation controller was not willing to acknowledge touch events to parts of self.view there were to the right of 320. In essence, if this self.navigationController.view.clipsToBounds were true, it might not even have shown that part of self.view.
Anyway, setting setNeedsLayout on the navigation controller's view resolved the issue. I hope this helps someone else. I suspect that was also the problem SorinA was having with buttons not getting touch events.

Related

Change Brightness of UIScreen

I am changing UIScreen brightness using value of UISlider i tried this code
self.Slide = [[UISlider alloc] initWithFrame:CGRectMake(13, 0, 244, 23)];
[self.Slide addTarget:self action:#selector(sliderHandler:) forControlEvents:UIControlEventValueChanged];
self.Slide.minimumValue = 0.0f;
self.Slide.maximumValue = 1.0f;
[self.Slide setValue:0.0f];
self.Slide.value = [[UIScreen mainScreen] brightness];
[self.view addSubview:self.Slide];
and method called is
- (void)sliderHandler:(UISlider *)sender {
[[UIScreen mainScreen] setBrightness:sender.value];
}
the method is call but brightness is not changing ......
and how can i set UISlider value to 0 initial ?
thanks....
Please use this code and as for the slider value set maximum and minimum value as given in the code below UISlider Brightness
Whereas the below code would work too.
- (void)viewDidLoad
{
UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0,0,300,40)];
[slider addTarget:self action:#selector(sliderHandler:) forControlEvents:UIControlEventValueChanged];
slider.minimumValue = 0.f;
slider.maximumValue = 1.0f;
slider.value = [[UIScreen mainScreen] brightness];
[[self view]addSubview:slider];
[super viewDidLoad];
}
- (void)sliderHandler:(UISlider *)sender
{
//NSLog(#"value:%f", sender.value);
[[UIScreen mainScreen] setBrightness:sender.value];
}
EDIT :
You could try this way too. Add a UIVIew of clear color to the view and increase the alpha component of this view upon the slider value changed event. By doing this , the view gets darkened and we get a feeling that the brightness of the app is reduced. This solution may not be very appropriate, but works just fine.

Make UIView move down if iPhone is iPhone 5

I am currently creating an app which contains a pickerView and a tapbar within a view. The view is placed on the bottom of the screen. The tapbar is always visible. If I tap a button on the tapbar, the view will move up and show the pickerView.
My Problem is:
The view does not move down to the bottom of the iPhone 5 screen. I placed this code in different locations:
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if (screenSize.height > 480.0f){
[UIView beginAnimations:Nil context:Nil];//tells the compiler to start a new animation
[UIView setAnimationDuration:0.6];//in seconds
self.hiddenView.frame = CGRectMake(0, 504, 320, 260);//move the picker to a specific position (504 = 568 - statusbar(20) - tapbar(44))
[UIView commitAnimations];//tells the compiler to start the animations
}
such as in the:
-(void)viewDidLoad{}
-(void)viedWillAppear{}
-(void)viewDidAppear{}
I am clueless. Does anyone know how to make it the right way?
UPADTE
Ok thanks for all the answers, but my animation works fine. My problem is that it is executed every time (checked using breakpoints) won't fire (the view won't move down). So I asked WHERE I have to put my code in order to work properly. Not if the code was correct, because it is. I know there are different ways to check if it is an iPhone 5 and to animate things, but again: this code is working and not the actual problem. I hope you understand my problem better now.
Use this below code.
if([[UIScreen mainScreen] bounds].size.height == 568)
{
//This is for iphone 5 view
//add your code here.
UIView *view=[[UIView alloc]initWithFrame:CGRectMake(0, 150, 100, 100)];
}
else
{
//This is for iphone 4 view
//add your code here.
UIView *view=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
}
This condition for iphone 5 .
There is no need to comparision of height for different ios:
Try this for hide your view:
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
[UIView beginAnimations:Nil context:Nil];//tells the compiler to start a new animation
[UIView setAnimationDuration:0.6];//in seconds
self.hiddenView.frame = CGRectMake(0, screenSize.height, 320, 260);//move the picker to a specific position
[UIView commitAnimations];//tells the compiler to start the animations
To show your view:
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
[UIView beginAnimations:Nil context:Nil];//tells the compiler to start a new animation
[UIView setAnimationDuration:0.6];//in seconds
self.hiddenView.frame = CGRectMake(0, screenSize.height-260, 320, 260);//move the picker to a specific position
[UIView commitAnimations];//tells the compiler to start the animations
Update
you can take a bool variable or can use selected state of your tapButton
Like:
-(IBAction) tapbuttonClicked:(UIButton *)sender
{
[sender setSelected:!sender.isSelected];
if(sender.isSelected)
{
//code to show your view...
}
else
{
//code to hide....
}
}
Ok since apparently nobody correctly understood my question (or didn't actually read it to the end?), I had to find an answer for myself. If somebody encounters the same problem here is how I solved it.
Just place your code into the -(void)viewDidLayoutSubviews{} function. It will execute as soon as the view is fully loaded.
-(void)viewDidLayoutSubviews{
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if (screenSize.height > 480.0f){
[UIView beginAnimations:Nil context:Nil];//tells the compiler to start a new animation
[UIView setAnimationDuration:0.0];//in seconds
self.hiddenView.frame = CGRectMake(0, 504, 320, 260);//move the picker to a specific position
[UIView commitAnimations];//tells the compiler to start the animations
}
}
My favorite way of doing such things is using + (UIView) animateWithDuration: animations:
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if (screenSize.height > 480.0f){
[UIView animateWithDuration:0.60f animations:^(void){
self.hiddenView.frame = CGRectMake(0, 504, 320, 260);//move the picker to a specific position (504 = 568 - statusbar(20) - tapbar(44))
}];
}
This should do the trick for you. Also, you can look at animateWithDuration: animations: completion: or even animateWithDuration: delay: options: animations: completion:
Hope this helps.
Add The following line of code:
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
At yourProjectName-perfix.pch file
This is useful for recognize that device is iPhone4 or iPhone5. by give condition such like
if (IS_IPHONE_5)
{
//// write code/setFrame for iPhone5;
}
eles
{
//// write code/setFrame for iPhone4;
}
Use it anyWhere in your project:

Imageview not display Proper For Iphone 5 Retina

I am developing one app in that app display 20 array Images to Image view Scroll horizontally.
give scroll view to that imageview like this
scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
for (m = 0; m <=19; m++)
{
rnd = arc4random_uniform(arr.count);
NSString *imageName=[FrontsCards objectAtIndex:rnd];
fullImageName=[NSString stringWithFormat:#"%#",imageName];
int padding=0;
CGRect imageViewFrame=CGRectMake(scrollView.frame.size.width*m+padding, scrollView.frame.origin.y, scrollView.frame.size.width-2*padding, scrollView.frame.size.height);
ImgView=[[UIImageView alloc]initWithFrame:imageViewFrame];
[ImgView setImage:[UIImage imageNamed:fullImageName]];
[scrollView addSubview:ImgView];
}
this imageview not display images Properly for iphone 5 simulator. below black edge add.
how may i solve that issue.how to remove that black edge.how to fit that image to Iphone 5 simulator.
how may manage my ImageView to Iphone 4 or Iphone 5.
Iphone 5 size is 568 and Iphone 4 size is 480.
scrollView=[[UIScrollView alloc]init];
if ([[UIScreen mainScreen] bounds].size.height == 568)
{
// For Iphone5
scrollView.frame = CGRectMake(0, 0, 320, 568)
}
else if ([[UIScreen mainScreen] bounds].size.height == 480)
{
//For Iphone 4 or others
scrollView.frame = CGCGRectMake(0, 0, 320, 480)
}
this will really helpful to you.
Iphone 5 screen size is 568 and you have had codded height to 480. So it is not working for iphone5.
DO following
scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, [[UIScreen mainScreen] bounds].size.height)];
Depending on devise scroll view height will change.
Try This
scrollView=[[UIScrollView alloc]init];
if ([[UIScreen mainScreen] bounds].size.height == 568) scrollView.frame = CGRectMake(0, 0, 320, 568)
else if ([[UIScreen mainScreen] bounds].size.height == 480) scrollView.frame = CGRectMake(0, 0, 320, 480)
So, it will help you to fill scrollview in iPhone-5 screen too.
Hopefully, it'll work for you.
Thanks.
scrollView=[[UIScrollView alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
use this to make the UIScrollView dynamic
Use macro to check whether it is iPhone 5 or not.
#define IS_IPHONE ( [[[UIDevice currentDevice] model] isEqualToString:#"iPhone"] | [[[UIDevice currentDevice] model] isEqualToString:#"iPhone Simulator"])
#define IS_HEIGHT_GTE_568 [[UIScreen mainScreen ] bounds].size.height >= 568.0f
#define IS_IPHONE_5 ( IS_IPHONE && IS_HEIGHT_GTE_568 )
scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, IS_IPHONE_5?568:480)];
You need to create design for iPhone 4 and iPhone 5.
Create a class which make decision which iPhone is connected and
make function on it which accept CGRect and return required size of CGRect
you can get device size by
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
CGSize result = [[UIScreen mainScreen] bounds].size;
if (result.height < 500)
{
currentDeviceHeight=460;
//You can use use iPhone 4 image
}
else
{
currentDeviceHeight=548;
// here you can use iPhone 5 image
}
}
else
{
// iPad
}

Why doesn't the UIView frame not set?

Am trying something so trivial! Can't believe it's not working! Maybe am overlooking something!
Am having a home page in my iPhone app. I want to now add a subview which will be initially out of the screen (i.e. hidden to the right i.e. its frame.origin.x will be the screen width), and then I want to animate its entry into the page with a flip-horizontal and show the subview partially (only half-screen approximately).
[self.mySubview.view setFrame:CGRectMake([[UIScreen mainScreen] bounds].size.width, 0.0,
[[UIScreen mainScreen] bounds].size.width,
[[UIScreen mainScreen] bounds].size.height)];
[self.view addSubview:self.mySubview.view];
NSLog(#"frame before x %f", self.mySubview.view.frame.origin.x);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[self.mySubview.view setFrame:CGRectMake([[UIScreen mainScreen] bounds].size.width*(2/5), 0.0,
[[UIScreen mainScreen] bounds].size.width,
[[UIScreen mainScreen] bounds].size.height)];
[UIView commitAnimations];
NSLog(#"frame x %f", self.mySubview.view.frame.origin.x);
Am trying to run this on an iPad. But the subview's frame is not getting set to 768.0 initially. Also, the animation is not happening. Before and after the animation, the subview's frame.origin.x is only 0.0. Where could I have gone wrong? Please help. I tried varying the autosizing arrows in the storyboard (removing them, adding them) ... nothing seems to work!
Try This
Someviewcontroller *c = initWithNibName
c.view.frame = CGRectMake(0, 0, 200, 200);
[self addSubView:c];
Try this:
self.mySubview
instend of
self.mySubview.view

What is difference between self.view.frame and self.superview.frame and how to use them?

I would like to know that what is difference between these both lines of code?
self.view.frame = CGRectMake(0, 0, 320, 480);
self.view.superview.frame = CGRectMake(0, 0, 800, 900);
and I want to change the view frame when my orientation will change, because it will change the position of labels, and I want them in middle of screen, can anyone guide me ?
I am using following delegate method, for orientation, but it is not working with
self.view.frame
but it is working ok with following line
self.view.superview.frame
See the following code
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
//return (interfaceOrientation == UIInterfaceOrientationPortrait);
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
NSLog(#"LEFT");
self.view.frame = CGRectMake(100, 0, 480, 320);
NSLog(#"Show self.view.frame: %#", NSStringFromCGRect(self.view.frame));
// self.view.superview.frame = CGRectMake(-50, -70, 800, 900);
[button setFrame:CGRectMake(340, 320, 100, 30)];
}
if (interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
NSLog(#"RIGHT");
self.view.frame = CGRectMake(0, 0, 320, 480);
NSLog(#"Show self.view.frame: %#", NSStringFromCGRect(self.view.frame));
//self.view.superview.frame = CGRectMake(10, 90, 800, 900); //It is working if I will uncomment it
[button setFrame:CGRectMake(250, 300, 100, 30)];
}
if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
self.view.frame = CGRectMake(0, 0, 320, 480);
//self.view.superview.frame = CGRectMake(0, 0, 800, 900);//It is working if I will uncomment it
[button setFrame:CGRectMake(250, 400, 100, 30)];
}
return YES;
}
self.view is the view of self (if we are talking about viewControllers).
self.view.superview is the view that is holding self.view.
So, in short, if you add a view to the window the superview of that view will be the window.
Setting the frame will fail if the autoresize mask isn't set correctly.
As a generic statement, the first line is trying set the frame of the current viewController's view that this code is written in.
The second line is trying to set the frame of the parent view of the view of the current viewController's view.
What this exactly means, and which one you should be using I'm afraid depends on the view hierarchy you have set up in your application.