I have encountered this bug several times. I have a application with a navigation controller (navbar hidden). when a button is "pressed" i want to push another view with a tabbarviewcontroller. When the new view is pushed, it's 20 pixels lower than it should (and part of the tabbar is not visible).
If I enter modal-view controller from the tabbarviewcontroller and then i dismiss it, the tabbarviewcontroller is shown properly.
I put the status bar in every view to be unspecified (thought that was the problem) and i un-checked the autoresize subviews from each view.
in your code use bounds property instead of application frame . in my it worked hope to work in case too.......:)
This sounds like it might be related to a known NIB/XIB file bug (for more information see: http://forums.bignerdranch.com/viewtopic.php?f=51&t=125)
As the linked forum topic suggests, for a workaround simply use the following:
- (void)viewDidLoad {
[super viewDidLoad];
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
[[self view] setFrame:appFrame];
}
thank you for your answers. i did it somehow, playing with the tabbar's frame a bit.
[self.tabBarController.view setFrame:CGRectMake(0, 0, 320, 460)];
[self.view addSubview:tabBarController.view];
[self.view bringSubviewToFront:tabBarController.view];
i remember trying this a while ago and not working. now it did.
also, medling with bounds helped a bit.
Related
I'm doing a cool CA3DTransform while a UIScrollview is scrolling in the scrollViewDidScroll delegate method. It works perfectly when you use your finger to scroll, so when scrolling manually everything is perfect.
But, when I set scrollview contentoffset programmatically like:
[scrollView setContentOffSet:CGPointMake(0,460) animated:YES];
It still calls the delegate method scrollviewdidscroll, so the same animation methods are called, so I still see the correct animation, BUT, somehow parts of the view are missing during and after the animation! I've tried to set the layer.zPosition on all things and it doesn't seem to help. It should be fine since manually scrolling does work without parts of views going missing... Somehow calling this method programmatically differs and I have no idea why!
Post your question in this way is not very clear, considering that with the delegate scrollViewDidScroll, I can print me the code, either manually or programmatically.
...
UIScrollView *sv = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 10, 320, 200)];
[sv setContentSize:CGSizeMake(640, 200)];
sv.delegate = self;
[sv setContentOffset:CGPointMake(320, 0) animated:YES];
[self.view addSubview:sv];
...
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(#"---%#---", NSStringFromCGPoint(scrollView.contentOffset));
}
In this simple example, you can see that the delegate actually works.
Excuse the simplicity of the answer, but the only question you ask is hard to give you help.
I had a similar problem (in the context of using a scrollview for a slideshow) but solved it by using scrollRectToVisible:NO (NO for no animations), and wrapped that inside a UIView animation block where I also put my animation code.
I hope someone can help... This issue has been discussed here and I have tried the solutions suggested but to no avail.
My problem is best illustrated using the example project which can be downloaded from this URL:
http://www.hitsalive.com/tmp/VCTest.zip
In the example project I have a main UIViewController with two buttons used to call two other UIViewControllers - one using presentModalViewController and the other using "addSubView" (using the AppDelegate). Individually both buttons and UIViewControllers work fine.
However, if I first call the modal viewcontroller, then dismiss it (using dismissModalViewControllerAnimated: YES) and then display the second (addSubView) UIViewController, then all elements and subviews in the second UIViewController (such as the button in the example) get displaced downwards vertically by 20 pixels. And the displacement happens with a momentary delay.
This issue does not happen with SDK 3.2 and below -- just iOS4.
Any help would be appreciated, especially with reference to the example project above.
add [aViewControllerTwo setWantsFullScreenLayout:YES]; to your - (void)flipToViewControllerTwo after ViewControllerTwo *aViewControllerTwo = [[ViewControllerTwo alloc] initWithNibName:#"ViewControllerTwo" bundle:[NSBundle mainBundle]];
In order to solve this you need to do the following with the view controller that appears shifted: add a frame, then set the position of this frame appropriately. Set this frame to the view of the ViewController.
shiftedViewController* ShiftedViewController = [[ShiftedViewController alloc] init ];
CGRect theFrame = [shiftedViewController.view frame];
theFrame.origin.y = 20;
theFrame.origin.x=0;
[shiftedViewController.view setFrame: theFrame];
[self presentModalViewController:shiftedViewController
animated:YES];
I've got three ViewControllers set up to handle three views. The problem that I'm having is that in the simulator the orientation is LandscapeRight (which is what I want), and the first view shows up correctly in that landscape view, but when I move onto the second and third views, they show up rotated 90 degrees counter-clockwise with the upper-left corner of the view in the lower left corner of the phone's screen. I've been trying to debug this for a few days and the closest that I've gotten to a clue is tracing it the following way:
The following is in my app delegate's applicationDidFinishLaunching:
NSLog(#"1");
[window addSubview:welcomeController.view];
NSLog(#"2");
[window addSubview:goalController.view];
NSLog(#"3");
[window addSubview:planningController.view];
NSLog(#"4");
[window bringSubviewToFront:welcomeController.view];
NSLog(#"5");
Each of my ViewControllers implement something similar to the following (the only change being the controller's name switched out in the string passed to NSLog):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
NSLog(#"called for WelcomeController");
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
With that, I get the following output on the Console:
a
called for WelcomeController
called for WelcomeController
called for WelcomeController
called for WelcomeController
2
called for GoalController
3
called for PlanningController
4
5
I find it interesting that shouldAutorotateToInterfaceOrientation is called 4 times for the first view that's added, while the other two only get called once. I expect that this is probably because it's got to do some setup at first (and I believe that the simulator starts off in portrait mode, so it's might be calling it while doing the rotation), but I find the correlation a bit suspicious.
I've switched the order around so that the addSubview is called for the goalController first and the welcomeController second. In this case, it's the goalController which displays in the correct landscape orientation (it's normally the welcome controller). This would seem to eliminate my XIB files and the ViewControllers themselves. I'm not sure why the first view where addSubview is called is special. I also tried using insertSubview at index 0 with the same results.
Ran into the same problem, and apparently adding subviews to a UIWindow doesn't work the way I expected it to. I managed to solve the problem after adding a "dummy" UIViewController that is the ONLY subview in the UIWindow. After adding that one, it works perfectly to add multiple subviews to the dummy-controller, all with the correct orientation.
So the only code in the "dummy" controller class is the "shouldAutorotateToInterfaceOrientation" function. This should also match the same function in all the other subviews.
Hope it helps.
I had a similar issue. Not sure why either. But the workaround was to call this on every view after the first one:
[planningController.view setFrame:CGRectMake(0, 0, 480, 300)];
and before -addView. I'm curious if this helps you out. If I am not the only one with this problem and this workaround, then maybe there's a reason.
This is far far far from ideal. But you can hack the second views transform so it is rotated correctly. This works for me because my app is only ever in landscape mode. It may not be ideal if you want to change orientation.
[window addSubview:firstController.view];
[window addSubview:secondController.view];
CGAffineTransform rotate = CGAffineTransformMakeRotation(M_PI/2.0);
[backgroundViewController.view setTransform:rotate];
CGRect contentRect = CGRectMake(0, 0, 1024, 768);
backgroundViewController.view.bounds = contentRect;
[backgroundViewController.view setCenter:CGPointMake(768/2, 1024/2)];
I think I have a solution for this that appears to work. Add a view, and then immediate remove it, repeat for each view, then add all three. Like this:
[window addSubview:welcomeController.view];
[welcomeController.view removeFromSuperview];
[window addSubview:goalController.view];
[goalController.view removeFromSuperview];
[window addSubview:planningController.view];
[planningController.view removeFromSuperview];
[window addSubview:welcomeController.view];
[window addSubview:goalController.view];
[window addSubview:planningController.view];
It seems to work, at least in the simulator.
Using this method to hide the status bar:
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
When setting "hidden" back to NO, the tap-to-scroll-to-top (in UIWebView, UITableView, whatever) doesn't work any more, and requires a restart of the app to get the functionality back.
Is this a bug (I filed a rdar anyhow) or have I missed a step? Should I perhaps expect this behavior since the statusBar "loses touch" somehow with the respective view?
You could try setting the ScrollsToTop property to true again after re-showing it:
[currentView setScrollsToTop:YES];
If that's not working, are you definitely only showing one view? If there is more than one scrolling view a scrollViewDidScrollToTop message is ignored...
In iOS 5.0 you can access the scrollview property of the UIWebView
webView.scrollView.scrollsToTop = YES;
The following fix by Alex worked for me. Thanks!
((UIScrollView *)[[webView subviews] objectAtIndex:0]).scrollsToTop = NO;
Being in a hurry this fix worked great, however given more time I might've subclassed the UIWebView and accessed the protected UIScrollView member directly.
The worry I have with Alex' method is that it assumes that UIScrollView is at index zero of the subviews (encapsulation allows private members to change). Which suggests another solution still:
for (UIView* v in [webView subviews])
{
if ([v isKindOfClass:[UIScrollView class]])
{
(UIScrollView *)v.scrollsToTop = NO;
}
}
I was having a similar problem where the scroll-to-top functionality was lost. Turns out this will only work when you have only one active view at a time (within the same scroll view). In my case I had a table view and another view which would fade in/out. Adding a removeFromSuperview at the end of the animation did the trick.
The answer was in the UIScrollView.h file comments:
/*
this is for the scroll to top gesture. by default, a single scroll visible scroll view with this flag set will get the call. if there is more than one visible with this
flag set or the delegeat method returns NO, the view isn't scrolled
*/
#property(nonatomic) BOOL scrollsToTop; // default is YES. if set, special gesture will scroll to top of view after consulting delegate
You can use the following code to have the UIWebView ignore scrollToTop without the extra UIScrollView:
((UIScrollView *)[[webView valueForKey:#"_internal"] valueForKey:#"scroller"]).scrollsToTop = NO;
I had a similar problem after playing a Youtube video within my app. scrollsToTop was still set to YES but tapping the status bar had no effect.
I finally realised that my app window was no longer the key window. After adding the following line to a UIWindow subclass (which I already had for other reasons) everything worked as it should again:
if (![self isKeyWindow]) [self makeKeyWindow];
I just ran across a similar behavior in the app I'm currently working on. In its case, if you load a YouTube video from within a UIWebView, scroll to top stops working for the rest of the application's life cycle. I kind of assume this might happen after loading the movie player as well, but haven't confirmed. That functionality has been around a lot longer and probably has fewer bugs.
When there are multiple scrollview, you can also set scrollUpToTop to NO for the others scrollview. cf:
setScrollsToTop with multiple UIScrollView classes and/or subclasses(UITableView)
I want to add my case, I add an UIWebView on an UIScrollView, as h4xxr had answered on the top:
If there is more than one scrolling view a scrollViewDidScrollToTop message is ignored
So, I get a simply way to make it work on webView: just set the scrollView·s scrollsToTop property false.
And when tap the status bar, it won`t got intercepted by the scrollView, and the webView scrolls to the top!
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = self.view.bounds;
scrollView.scrollsToTop = false; //igore scrollView`s scrollsToTop
[self.view addSubview:scrollView];
UIWebView *webView = [[UIWebView alloc] init];
webView.frame = scrollView.bounds;
[scrollView addSubview:webView];
This is probably a really basic question, but when I make my ABPeoplePickerNavigationController instance (addBookViewer)visible by running,
[self presentModalViewController:addBookViewer animated:YES]
the contact view pops up, but is cut off by the top most bar of the display (the bar showing the AT&T signal strength, clock and battery charge). Is there a way to programatically change the addBookViewer so that it is not cut off by the static status bar?
Thanks,
Dave
It looks like ABPeoplePickerNavigationController inherits from UIViewController. Perhaps you could try editing the view's frame before presenting it:
addBookViewer.view.frame = CGRectMake(0, 20, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height - 20);
I suspect it is because the view controller that you are calling presentModalViewController:animated: on has a frame that is also being covered, but you don't notice, probably have plenty of head room, make sure you have the status bar in your nib file so that it is laid out correctly.