I'm creating a UIWebView with a blank page using the following code.
- (void)loadView {
[super loadView];
UIWebView *wv = [[[UIWebView alloc] initWithFrame:self.view.bounds] autorelease];
wv.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:wv];
}
When rotating the device from portrait to landscape or vice versa the page's content becomes bigger than the webview's bounds and black areas appear. What might be the problem?
It looks like self.view (the webview's parent view) may not have the correct autoresizing masks. A subview's autoresizing mask will only fill up to the container bounds. If the webview's parent view does not have it's autoresizing mask setup correctly, then the webview's autoresizing masks won't look correct, either. You seem to be setting up the webview properly (not using CGRectZero on initWithFrame without ever setting an initial size), so your current implementation should work barring nothing else has been setup funny in your view controller.
webView.scalesPageToFit = YES;
See also: UIWebView+SFHFStringMetrics
Related
I have this code inside a UIViewController subclass:
- (id)init {
self = [super init];
if (self) {
self.view.frame = [PDToolbox screenFrame];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.view.backgroundColor = [UIColor redColor];
}
return self;
}
The only thing I have in terms of any rotation methods is this:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return YES;
}
Yet after the screen is rotated to landscape, doing an NSLog on the view shows this:
<UIView: 0x10061640; frame = (0 0; 320 480); transform = [0, -1, 1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x10061670>>
I don't understand why it's doing this transform thing, and not just rotating like normal? It means any views i place on top of it after the rotation and set to be the size of the view end up at a 320x480 position.
EDIT:
People aren't understanding. So I put a view on top of it, the same size as the UIView, using:
UIView *anotherView = [UIView alloc] initWithFrame:controller.view.bounds];
[controller.view addSubview:anotherView];
If I add anotherView in in portrait, anotherView appears in portrait, with the frame 320x480.
If i add anotherView in in landscape, anotherView appears in landscape, but still with the frame 320x480, becaus that's what the controller.view's frame is still, for some unknown reason.
What does your view/controller hierarchy look like? It looks to me like something is setting a 90° rotation transformation on your view, rather than changing the view's frame. If you're not doing that yourself, it's likely a parent view or view controller.
Frame and bounds are very different things. You should read Apple's guide to View Geometry - it contains a lot of information that's been invaluable to me.
Your bounds is always going to be 320x480 because someone is setting your transform (which affects the frame, but not the bounds).
Make sure your view controller's view's superview has autoresizesSubviews set to YES and that any subviews added have appropriate autoresizingMasks.
I have made a custom UIView which is shown when the user hits a button in the navigationbar. I make my view's in code. In my loadview I set the autoresizing masks and the view loads correct on screen. However the UIView which is shown when the user taps the button does not resize even when I have set the autoresizing masks.
UIView *blackView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 416.0)];
blackView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Do I need to use self.view.frame.size.width and self.view.frame.size.height instead? And if I do why? Does not resizing masks work outside of loadView?
Thank you for your time:)
the autoresizingMask affects how a view will behave when its superviews frame changes. if all you are doing is showing theblackViewwhen you tap a button, thenblackView` will have whatever frame you initially set for it.
If this isn't enough info, please post some more code around how you are configuring and displaying blackView and it's superview and explain more about what situations you are expecting blackView to resize in. Rotation is one of them, if that's what you're concerned with.
First things first, I hope you've done this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Let's say the view that needs resizing is: view2
The view that has view2 as a subview is: view1
While creating view1 you would declare it as:
view1 = [[UIView alloc] init];
[view1 setNeedsLayout];
Now in view1's .m file you need to overload the layoutSubviews method as shown:
- (void)layoutSubviews
{
CGRect frame = view2.frame;
// apply changes to frame
view2.frame = frame;
}
In case view1 is a view controller's view, you need to do that same thing as above in the willRotate method as shown
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
CGRect frame = view2.frame;
// apply changes to frame
view2.frame = frame;
}
This is a tried and tested method that I use to handle orientation changes.
What I wanted to achieve here is simply fit the image width to the screen on both orientations and use UIScrollView to just allow scroll vertically to see the whole image.
Both viewController and view are created pragmatically.
The image loaded is larger than screen on both width and height.
Here is the related code in my viewController:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void)loadView {
UIScreen *screen = [UIScreen mainScreen];
CGRect rect = [screen applicationFrame];
self.view = [[UIView alloc] initWithFrame:rect];
self.view.contentMode = UIViewContentModeScaleAspectFill;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
UIImage *img=[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"image" ofType:#"png"]];
UIImageView *imgView =[[UIImageView alloc] initWithImage:img];
[img release];
imgView.contentMode = UIViewContentModeScaleAspectFill;
imgView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:imgView];
[imgView release];
}
I tried all combinations for both contentMode above, did not give me correct result.
The most close I am getting now: I manually resize imgView in loadView, portrait mode would display correctly since app always starts with portrait mode, but in landscape mode, the width fits correctly, but image is centered vertically rather than top aligned.
If I add the imgView to a scrollView, in landscape mode it looks like contentSize is not set to full image size. but when I scroll bounce I can see the image is there in full size.
Questions:
why I need to resize it manually?
in landscape mode how and where I can 'move' the imgView, so imgView.frame.origin is (0,0) and works correctly with a scroll view?
Update
I added:
imgView.clipsToBounds = YES;
and find out in landscape mode the image bounds is smaller than screen in height.
So the question becomes how to have the image view keeps original ratio (thus shows the full image always) when rotated to landscape? Do I need to manually resize it after rotation again?
Instead of manually take care of orientation change and change view details. I plan to follow Apple document and make separate view controllers for each orientations.
see P42 # ViewControllerProgrammingGuide:
Creating an Alternate Landscape Interface
Here in the code you are not using any scrollView.
You need to add that imageView to ScrollView. and set the scrollView frame as same as the main view and contentSize to imageView or image Size.
If you are using scroll view in the app, then have you also resized the scroll view and the subviews as well, your code if fine just try to resize the subviews as well.
I use the following code to do so.
self.homescroll.autoresizingMask=UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;// | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleLeftMargin;
self.homescroll.autoresizesSubviews=YES;
[self.homescroll setNeedsLayout];
[self.view addSubview:homescroll];
Just resize the subviews as well.
I'm trying to display transparent UINavigationBar on top of Scrollview.
This is actual result of code that I have written...
where as I'm expecting view to be displayed like below image, which happens after I slightly scroll the image.
Code :
- (void) loadView {
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
pagingScrollView.pagingEnabled = YES;
pagingScrollView.backgroundColor = [UIColor blackColor];
pagingScrollView.showsVerticalScrollIndicator = NO;
pagingScrollView.showsHorizontalScrollIndicator = NO;
pagingScrollView.contentSize = CGSizeMake(pagingScrollViewFrame.size.width * [self imageCount],
pagingScrollViewFrame.size.height);
pagingScrollView.delegate = self;
self.wantsFullScreenLayout = YES;
pagingScrollView.scrollsToTop = YES;
self.view = pagingScrollView;
}
question is how do I make view to load as I expected without user interacting to it?
any suggestion or help is appreciated..
EDIT: I'm creating view totally from CODE
It seems like you're trying to do this in code not in the IB. If so, you have to put your code in the viewDidLoad of the Application Delegate (e.g. MyProgramAppDeligate class or whatever). If you want it in some certain views, put it in the viewDidLoad of the UINavigationController class/subclass.
Does this satisfy your requirement?
self.navigationController.navigationBar.translucent = YES;
self.navigationController.navigationBar.tintColor = [UIColor blackColor];
And to make your statusbar translucent.
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:YES];
[self setWantsFullScreenLayout:YES];
I have this inside my willWillAppear and I reset it in my viewWillDisappear.
You have to set
self.navigationController.navigationBar.translucent = YES;
As soon as you do this, the 0,0 coordinate is behind your navigation bar not below it and your view shifts behind the bar.
It may be a conflict between IB and your code. I would add the line of code suggested by Ortwin in the viewDidLoad method and then double check you've set the navBar to translucent in IB.
The code you have posted has nothing to do with the opacity of the navigation bar. Show where you are setting the configuration of the components of the view. There you could just set the alpha of the navigation bar. Alternatively if you are using nibs, just set the alpha in IB.
Since you say that it works fine after the user (you) slightly scrolls the image, the problem might be that the UINavigationBar's drawRect: method does not get called after the UIScrollView is loaded.
Suggestion: Can you explicitly call setNeedsDisplay on the navigation bar after the view is loaded?
Have you tried setting the frame of the scroll view with an Y origin of 0 after setting the nav bar to transparent?
EDIT: I mean, you don't say what's the frame used in your code.
In viewDidLoad, try moving the origin up 32 pixels and grow the height by 32 pixels as well:
pagingScrollView.frame = CGRectMake(pagingScrollView.frame.origin.x, pagingScrollView.frame.origin.y-32, pagingScrollView.frame.size.width, pagingScrollView.frame.size.height+32);
In viewWillAppear scroll the content to the correct location.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UIScrollView *scrollView = (UIScrollView *)self.view;
[scrollView setContentSize:CGSizeMake(320,568)];
[scrollView scrollRectToVisible:CGRectMake(0, 548, 320, 20) animated:NO];
}
I'm using a UIWebView with text in it. When the iPhone is rotated to landscape, text doesn't fill the now wider UIWebView width. I'm using P (paragraph) tags, which should not affect content filling landscape's width. The line breaks that are visible in portrait remain the same in landscape. In Interface Builder, I haven't changed anything. In the IB Inspector, Web View Size has all solid bars under AutoSizing, which means it should fill to the landscape width right?
Here is a tweak though not a good thing to do, and something should be handled by apple itself
As you've noticed that things workfine when WebView is initialized in portrait and then you turn it to landscape. So.. what you can do is always initialize your webview with portrait bounds, add a selector which calls back after 2~3 seconds and sets the frame of webView according to your requirement.
Now as the contents started loading when the frame size of your webview were according to portrait (say 320,460) so converting your webview to landscape will automatically adjust your web view if you have this line in your code
[webViewObjet_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
Below is the snippet of code
- (id) initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
webViewObjet_ = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
.....
}
}
- (void) webViewDidStartLoad:(UIWebView *)webView
{
.....
[self performSelector:#selector(chuss) withObject:nil afterDelay:3];
// call the function chuss after 3 second
}
- (void) chuss
{
webViewObjet_.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
[webViewObjet setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
}
Now tried around with the same problem, finally did it after looking detailed at "WhichWayIsUp"-Sample from Apple.
To keep it short:
1) Disable in the View Inspector the |--| and <-->
2) `switch the View Mode from the Webview to "Aspect Fill"
Et voila ;)
Keep the vibes,
Maniac
I have the same problem. Reloading does not work, the only thing that seems to help a bit is to add the following line to the code:
self.view.autoresizingMask =
UIViewAutoresizingFlexibleWidth;
(I place it in the willAnimateFirstHalfOfRotationToInterfaceOrientation function)
It still keeps a small white margin at the right, but its far better than the default. Note: you should apply this on the self.view and not on the UIWebView instance, that won't work.
Waiting for a solution from Apple..
Pieter
This will sound strange, but it works:
If the UIWebView is inside a UINavigationController, it will all work just fine. I had the same problem, so I just wrapped it up in a UINavigationController and the problem was gone.
For some reason, UINavigationController makes rotations work like a charm.