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.
Related
I'm creating a custom view (a subclass of UIView), the purpose of which is to hold together a static background image, a static border/frame overlay, and several smaller images that can be rotated, stretched, and dragged around the view (before the whole view is exported as an image).
I'm stuck on displaying this custom view from within another view. The images are coming from the iPhone camera, which has a very high resolution, and the only things I have been able to manage so far are cutting off the majority of the image or having my view go over the end of the screen. I need to be able to display it alongside menu items and so on, without editing the image (so that it can be sent on in its full form).
I am also adding the image to a fullscreen view, and it still will not change size.
I am initialising the view with as follows
- (id)initWithImage:(UIImage *)image
{
self = [super init];
if (self) {
[self setClipsToBounds:YES];
[self setAutoresizesSubviews:YES];
[self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
_image = image;
_imageView = [[UIImageView alloc] initWithImage:_image];
[_imageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[self addSubview:_imageView];
}
return self;
}
And I add it to another view with
self.card = [[SGImageCard alloc] initWithImage:[SGCardDataController cardImage]];
[self.cardPlaceHolder setAutoresizesSubviews:YES];
[self.cardPlaceHolder setContentMode:UIViewContentModeScaleAspectFit];
[self.cardPlaceHolder addSubview:self.card];
That view has also been set up in Interface Builder, and set there to autoresize its subviews and to cliptobounds (sometimes -- I have tried both ways). I have added my view in viewdidload (when the placeholder does not have its frame, for a reason I don't know), and also later, when it does (and it doesn't work either way).
What am I missing? (Have I even gone about this the right way?)
I finally solved this by setting the AutoResizeMasks to
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleRightMargin | UIViewAutoResizingFlexibleBottomMargin
And also setting the ContentModes to
UIViewContentModeScaleAspectFit
I have a view tableview which display custom cells. Those cells have a UIImageView which need to be scaled if the device is in landscape mode.
I set the autoresizingMask of the tableView to UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth, did the same for my custom cells and the UIImageView.
My problem is that setting autoresizingMask for the UIImageView changes the frame of the view without any rotation of the device needed.
This is my initialisation code for my UIImageView.
- (UIImageView *)bigImageView
{
if (!_bigImageView)
{
_bigImageView = [[UIImageView alloc] initWithFrame:(CGRect){2, [self.header getHeight], 272, 272}];
[_bigImageView setImage:[UIImage imageNamed:#"square.png"]];
[_bigImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[_bigImageView setBackgroundColor:[UIColor redColor]];
}
return _bigImageView;
}
The width should be 272 but changes automatically to 232.
The result expected with autoresizingMask should be:
But I get:
The ratio is not respected anymore.
This happens because every cell starts with a height of 44 points. You can check that in the init.
Maybe you can correct the size of the cell elements in drawRect: or in layoutSubviews.
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
I have set up all my views in portrait mode, then set the autoresize mask accordingly so that it will auto resize the views as the orientation changes.... however, this seems to work OK for views that are already displayed. If I load any new views whilst in landscape mode I get inverted width and height values on the loaded view's frame.
Do I have to calculate the frame size based on orientation for each of the main views?
e.g., instead of
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0,0,500, 100)];
I would have to do:
CGRect frame;
if([UIDevice orientation] == UIDeviceOrientationLandscape){
frame = CGRectMake(0,0,100,500)
}else{
frame = CGRectMake(0,0,500,100)
}
UIView* view = [[UIView alloc] initWithFrame:frame];
It seems a bit long-winded to me, given that the autorotation once a view is loaded works perfectly!
How do you manage view frames?
thanks
I manage my view frames using [[UIScreen mainScreen] applicationFrame];.
It is also very useful when building universal apps as you can use it to design views that will display correctly on both devices.
I've got a scroll view, in which I have an imageview displaying a 960x960 image, but it scrolls to something close to 4x that. I've tried to log the widths of all possible views and everything claims that it's 960x960 (or smaller, I think I logged the screen width once...?)
I need this image to stop scrolling at the bottom right corner of the image rather than entering deadspace. Any help would be greatly appreciated.
Heck, even telling me what the name of the object is that is larger than my scrollView.contentSize would put me on the right track...
//Test-Image is just a 960 by 960 image that's numbered around the edges 1-10 so you can tell if it's being moved
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Test-Image.png"]];
self.imageView = tempImageView;
[tempImageView release];
scrollView.contentSize = CGSizeMake(imageView.frame.size.width, imageView.frame.size.height);
//Tested with this, results the same.
//[scrollView setContentSize:CGSizeMake(960, 960)];
NSLog(#"What is my scrollView's height attribute?...%f", scrollView.contentSize.height);
// Returns 960
NSLog(#"What is in scrollView's width attribute?...%f", scrollView.contentSize.width);
// Returns 960
scrollView.contentOffset = CGPointMake(480, 480);
scrollView.maximumZoomScale = 8.0;
scrollView.minimumZoomScale = 0.25;
// Commenting clipsToBounds out doesn't seem to have any effect
scrollView.clipsToBounds = YES;
scrollView.delegate = self;
[scrollView addSubview:imageView];
Unfortunately, I do not have a specific answer.
Reference. Try [scrollView addSubview: self.imageView]; instead of [...addSubview: imageView];
Content Size. Try setting the content size after adding the ImageView.
[scrollView setContentSize: CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];
Delegate. Did you use and set the scrollview's delegate property (oIWScroll.delegate = self;)?
Clipping. It should not matter.
ScrollView Frame. Make sure the frame of the scrollview is equal to or smaller than [UIScreen mainScreen].applicationFrame.
Framing. When I had a situation similar to what you described, one of the the things I did was to create a container UIView, add it to the scroll view and stuff the objects into the container view. But you really should not have to do that for one image.
I also set the contentMode = UIViewContentModeTop.
I hope these suggestions help.