What piece am I missing to set an iOS background? - iphone

I have:
[A series of if statements sets backgroundImage to be something like [UIImageNamed #"Background-Default-Landscape"]; am I right to assume that the device will look for the file named Background-Default-Landscape#2x.png if it is a Retina display?]
UIImageView *backgroundView = [[UIImageView alloc] initWithImage:backgroundImage];
CGRect containerRect = CGRectZero;
containerRect.size = [backgroundImage size];
UIView *containerView = [[UIView alloc] initWithFrame:containerRect];
[containerView addSubview:backgroundView];
Right now my app is launching and once it loads displays a white screen, not a background specified (none of the backgrounds are solid white).
What am I missing to draw a background before I start putting things on the background, further below in the code?
Thanks,
--EDIT--
As far as code, I have:
- (void) renderScreen
{
int height = [[UIScreen mainScreen] bounds].size.height;
int width = [[UIScreen mainScreen] bounds].size.width;
UIImage *backgroundImage = nil;
if (height == 2048 || height == 2008 || height == 1024 || height == 1004 || height == 984)
{
backgroundImage = [UIImage imageNamed:#"Background-Default-Portrait"];
}
// Other such statements cut.
UIImageView *backgroundView = [[UIImageView alloc] initWithImage:backgroundImage];
CGRect containerRect = CGRectZero;
containerRect.size = [backgroundImage size];
UIView *containerView = [[UIView alloc] initWithFrame:containerRect];
[containerView addSubview:backgroundView];
[self.view addSubview:containerView];
Then below that are statements to draw on the background.
This method is called when the initial view loads and when it is rotated:
- (void)viewDidLoad
{
[super viewDidLoad];
[self renderScreen];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(renderScreen) name:UIDeviceOrientationDidChangeNotification object:nil];
}
The behavior is that the correct initial screen loads, then it fades to white and nothing interesting seems to happen after that.
--EDIT--
At the top, I have:
int height = [[UIScreen mainScreen] bounds].size.height;
int width = [[UIScreen mainScreen] bounds].size.width;
When I NSLog the height and width, for a retina device in landscape mode, I get a height of 1024 and a width of 768. The image displayed is a rotation of the portrait image; if I turn the device on the side the image neatly fills the whole screen but as-is the background displays a horizontally squeezed image.
Should I do anything different to be correctly obtaining height and width? I would expect for a device in landscape orientation the height would be 768 and the width would be 1024.

Every time renderScreen fires it will add two more subviews to the current controller's main view:
[containerView addSubview:backgroundView];
[self.view addSubview:containerView];
And this fires every time you rotate the device.
At least have the containerView as a property and replace it.
#property (nonatomic, strong) UIView *containerView;
and inside - (void) renderScreen
[self.containerView removeFromSuperview];
self.containerView = [[UIView alloc] initWithFrame:containerRect];
[self.view addSubview:self.containerView];
You could also add:
[self.view setNeedsDisplay];
So that the view is redrawn.

Related

Overlapping UITextView border

I need to support Landscape and Portrait orientation for my app, and I venture into using a single UIView.
When I first simulate the application, it displays the result without a problem. However, when I change orientation to landscape, the problem occurs.
The first time I run the application in portrait:
When I change the orientation to landscape:
Notice the lower left corner, near the Information tab.
When I change back the orientation to portrait:
It gets worse.
The code I am using,
- (void)updateLayoutForNewOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
CGFloat height = CGRectGetHeight([[UIScreen mainScreen] bounds]);
CGFloat width = CGRectGetWidth([[UIScreen mainScreen] bounds]);
if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
NSLog(#"Portrait");
[self iPhoneUserInterfacePortrait:width height:height];
}
else if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
NSLog(#"Landscape");
[self iPhoneUserInterfaceLandscape:width height:height];
}
}
- (void)iPhoneUserInterfacePortrait:(CGFloat)width height:(CGFloat)height
{
UITextView *descriptionTextView = [[UITextView alloc] initWithFrame:CGRectMake(0.0, 0.0, width - 100.0, height - 300.0)];
[self makeBorder:descriptionTextView];
[self setInformation:descriptionTextView];
[self.view addSubview:descriptionTextView];
}
- (void)iPhoneUserInterfaceLandscape:(CGFloat)width height:(CGFloat)height
{
UITextView *descriptionTextView = [[UITextView alloc] initWithFrame:CGRectMake(0.0, 0.0, width + 230, height - 368.0)];
[self makeBorder:descriptionTextView];
[self setInformation:descriptionTextView];
[self.view addSubview:descriptionTextView];
}
- (void)makeBorder:(UITextView *)descriptionTextView
{
descriptionTextView.layer.borderWidth = 3.0;
descriptionTextView.layer.cornerRadius = 15.0;
descriptionTextView.layer.borderColor = [[UIColor grayColor] CGColor];
[self.view addSubview:descriptionTextView];
}
You're adding several views while you want just one.
[self.view addSubview:descriptionTextView];
To get rid of this line, you could add field descriptionTextView to your ViewController subclass and change frame of that text view without adding/removing it from self.view.
Also you should try to play with AutoResizing masks to see if you can get needed results without actually changing frame manually.
And you should be careful with that constants: try your app on both 3.5 and 4.0 inch simulator devices.

UIScrollView scrolls too far after initial zoom

My UIScrollView is populated with a large content and then zoomed with "setZoomScale:animated", such that it fits into the scrollview frame. The view appears properly zoomed out, and properly positioned in the scrollview. However, the user is able to scroll outside the content (the scrollview background color shows). It seems that he can scroll as far as the original content size (as if the content was not zoomed out).
Strangely enough, after the user zooms manually the first time, everything works fine, and the scrollview is constrained to the content size again.
I have searched the web, and gone through the Apple docs and examples, but could not find anyone having the same problem. The Apple examples seem to show the same thing as I do.
My content is a custom view that is derived from UIView, and whose CALayer is replaced by a CATiledLayer (as in the Apple examples). The drawing I do myself in drawLayer:inContext:.
Here is a code snippet from MyScrollViewController:
- (void)loadView {
CGRect frame = [UIScreen mainScreen].applicationFrame;
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:frame];
scrollView.maximumZoomScale=1.0;
scrollView.delegate = self;
... setup theContentView ...
scrollView.contentSize = theContentView.bounds.size;
scrollView.contentInset = UIEdgeInsetsMake(20, 20, 20, 20);
[scrollView addSubview:theContentView];
self.view = scrollView;
double zoomScale = 0.5; // hardcoded for testing
[scrollView setZoomScale:zoomScale animated:NO];
NSLog(#"zoomscale=%g contentview=%# contentsize=%#", zoomScale, NSStringFromCGSize(theContentView.bounds.size), NSStringFromCGSize(scrollView.contentSize));
[scrollView release];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return theContentView;
}
The NSLog statement shows a correctly set contentSize and zoomscale...
Hoping there is something obvious that I am missing...
I ended up setting the zoomScale on the next runloop (instead of directly from loadView), which worked:
- (void) loadView {
CGRect frame = [UIScreen mainScreen].applicationFrame;
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:frame];
scrollView.maximumZoomScale=1.0;
scrollView.delegate = self;
... setup theContentView ...
scrollView.contentSize = theContentView.bounds.size;
scrollView.contentInset = UIEdgeInsetsMake(20, 20, 20, 20);
[scrollView addSubview:theContentView];
self.view = scrollView;
// set the zoom level on the next runloop invocation
[self performSelector:#selector(initialZoom) withObject:nil afterDelay:0];
[scrollView release];
}
- (void) initialZoom {
double zoomScale = 0.5; // hardcoded for testing
UIScrollView *scrollView = (UIScrollView *) self.view;
[scrollView setZoomScale:zoomScale animated:NO];
}
Another possibility, suggested by Maverick1st, is to set the zoomscale from viewDidAppear, rather than LoadView. That approach has the added advantage that it shows an animation of the zooming, indicating to the user that the view starts in a zoomed state.
- (void) viewDidAppear {
double zoomScale = 0.5; // hardcoded for testing
UIScrollView *scrollView = (UIScrollView *) self.view;
[scrollView setZoomScale:zoomScale animated:YES];
}
I'm new at this but you could try clipping subviews. I created a scroll view with interface builder, and there in the attributes inspector was a checkbox clip subviews, so i think you should do something like that, only programmatically. Hope that helps.

uiimageview aspectfit question

I've use a imagepicker to select image from my photo library, then i display that image in an uiimageview. Landscape photo works fine but there is some weirdness to the portrait image. The portrait image suppose to fill up the left and right empty space but it's not.
Cant figure out why the picture wont fill up the left and right space cause the imageview frame did specify the mainScreen bounds.
If i take away the aspectfit then the potrait image is nicely display but the landscape image is stretched to fill up the whole imageview.
My code is as follow:
CGRect frame = [[UIScreen mainScreen] bounds];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:frame];
UIImageView *selectedImageView = [[UIImageView alloc] initWithFrame:frame];
selectedImageView.image = image;
selectedImageView.contentMode = UIViewContentModeScaleAspectFit;
[scrollView addSubview:selectedImageView];
[selectedImageView release];
scrollView.delegate = self;
[self.view addSubview:scrollView];
[scrollView release];
Here is what it looks like:
Edit: My goal is to display the photo like it's been display in Photos album, start out as fitting in the view and allow zoom in to a certain limit.
Try out
UIImageView *logoImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"logo_bg.png"]];
[logoImageView setFrame:CGRectMake(0, 0, 320, [UIImage imageNamed:#"logo_bg.png"].size.height)];
[mainView addSubview:logoImageView];

I have a problem with a scrollView zooming the wrong imageView

Ok so this is kind of a strange issue, but I have got two scrollViews that each have a nested imageView so as to allow for panning and zooming of an image. The tow scrollView/imageView combo's are showing up just great, and because the image is bigger than my scrollView size, I can pan just great. Here is my viewDidLoad:
-(void) viewDidLoad
{
// set the image to be displayed, pic your own image here
imageView = [[MyImage alloc] initWithImage: [UIImage imageNamed: #"newBackground.png"]];
// yes we want to allow user interaction
[imageView setUserInteractionEnabled:YES];
// set the instance of our myScrollView to use the main screen
scrollView = [[MyScroll alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
// turn on scrolling
[scrollView setScrollEnabled: YES];
// set the content size to the size of the image
[scrollView setContentSize: imageView.image.size];
// add the instance of our myImageView class to the content view
[scrollView addSubview: imageView];
// flush the item
[imageView release];
// set max zoom to what suits you
[scrollView setMaximumZoomScale:1.0f];
// set min zoom to what suits you
[scrollView setMinimumZoomScale:0.25f];
// set the delegate
[scrollView setDelegate: self];
// scroll a portion of image into view (my image is very big) :)
//[scrollView scrollRectToVisible:CGRectMake(100, 100, 320, 440) animated:NO];
// yes to autoresize
scrollView.autoresizesSubviews = YES;
// set the mask
scrollView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
// set the view
//self.view =scrollView;
[scrollView setFrame:CGRectMake(0, 0, 320, 230)];
[self.view addSubview:scrollView];
imageView1 = [[MyImage alloc] initWithImage: [UIImage imageNamed: #"newBackground.png"]];
// yes we want to allow user interaction
[imageView1 setUserInteractionEnabled:YES];
// set the instance of our myScrollView to use the main screen
scrollView1 = [[MyScroll alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
// turn on scrolling
[scrollView1 setScrollEnabled: YES];
// set the content size to the size of the image
[scrollView1 setContentSize: imageView1.image.size];
// add the instance of our myImageView class to the content view
[scrollView1 addSubview: imageView1];
// flush the item
[imageView1 release];
// set max zoom to what suits you
[scrollView1 setMaximumZoomScale:1.0f];
// set min zoom to what suits you
[scrollView1 setMinimumZoomScale:0.25f];
// set the delegate
[scrollView1 setDelegate: self];
// scroll a portion of image into view (my image is very big) :)
//[scrollView scrollRectToVisible:CGRectMake(100, 100, 320, 440) animated:NO];
// yes to autoresize
scrollView1.autoresizesSubviews = YES;
// set the mask
scrollView1.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
// set the view
//self.view =scrollView;
[scrollView1 setFrame:CGRectMake(0,240,320,230)];
[self.view addSubview:scrollView1];
//[[self view] addSubview:scrollView];
}
No as for zooming, when I pinch to zoom on the FIRST scrollView/imageView pair, it works beautifully, no problems whatsoever. It zooms and pans no problem. BUT when I pinch to zoom my second scrollView, it pans the image of the SECOND, and zooms the image of the FIRST. SO my SECOND scrollView zooms the FIRST's image. Huh? I have no idea why that would be happening.
All I want is to have to separate images viewed that can be independently panned and zoomed.
Any thoughts as to what might be happening?
Thanks!
Your viewForZoomingInScrollView: method is probably returning the same image view for both scroll views. It needs to look at which scroll view is being passed in and return the corresponding image view.

uiscrollview not switching image subviews

I'm building a comic viewer app, that consists of two view controllers, the root viewcontroller basically displays a view where a user decides what comic they want to read by pressing a button. The second viewController actually displays the comic as a uiscrollview with a toolbar and a title at the top.
So the problem I am having is that the comic image panels themselves are not changing from whatever the first comic you go to if you select another comic after viewing the first one. The way I set it up, and I admit it's not exactly mvc, so please don't hate, anyway the way I set it up is each comic uiscrollview consists of x number of jpg images where each comic set's image names have a common prefix and then a number like 'funny1.jpg', 'funny2.jpg', 'funny3.jpg' and 'soda1.jpg', 'soda2.jpg', 'soda3.jpg', etc...
so when a user selects a comic to view in the root controller it makes a call to the delegate and sets ivars on instances of the comicviewcontroller that belongs to the delegate (mainDelegate.comicViewController.property) I set the number of panels in that comic, the comic name for the title label, and the image prefix.
The number of images changes(or at least the number that you can scroll through), and the title changes but for some reason the images are the same ones as whatever comic you clicked on initially.
I'm basing this whole app off of the 'scrolling' code sample from apple.
I thought if I added a viewWillAppear:(BOOL) animated call to the comicViewController everytime the user clicked the button that would fix it but it didn't, after all that is where the scrollview is laid out.
Anyway here is some code from each of the two controllers:
RootController:
-(IBAction) launchComic2{
AppDelegate *mainDelegate = [(AppDelegate *) [UIApplication sharedApplication] delegate];
mainDelegate.myViewController.comicPageCount = 3;
mainDelegate.myViewController.comicTitle.text = #"\"Death by ETOH\"";
mainDelegate.myViewController.comicImagePrefix = #"etoh";
[mainDelegate.myViewController viewWillAppear:YES];
[mainDelegate.window addSubview: mainDelegate.myViewController.view];
comicViewController:
-(void) viewWillAppear:(BOOL)animated {
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
// 1. setup the scrollview for multiple images and add it to the view controller
//
// note: the following can be done in Interface Builder, but we show this in code for clarity
[scrollView1 setBackgroundColor:[UIColor whiteColor]];
[scrollView1 setCanCancelContentTouches:NO];
scrollView1.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView1.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
scrollView1.scrollEnabled = YES;
// pagingEnabled property default is NO, if set the scroller will stop or snap at each photo
// if you want free-flowing scroll, don't set this property.
scrollView1.pagingEnabled = YES;
// load all the images from our bundle and add them to the scroll view
NSUInteger i;
for (i = 1; i <= self.comicPageCount; i++)
{
NSString *imageName = [NSString stringWithFormat:#"%#%d.jpg", self.comicImagePrefix, i];
NSLog(#"%#%d.jpg", self.comicImagePrefix, i);
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[scrollView1 addSubview:imageView];
[imageView release];
}
[self layoutScrollImages]; // now place the photos in serial layout within the scrollview
}
- (void)layoutScrollImages
{
UIImageView *view = nil;
NSArray *subviews = [scrollView1 subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curXLoc = 0;
for (view in subviews)
{
if ([view isKindOfClass:[UIImageView class]] && view.tag > 0)
{
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, 0);
view.frame = frame;
curXLoc += (kScrollObjWidth);
}
}
// set the content size so it can be scrollable
[scrollView1 setContentSize:CGSizeMake((self.comicPageCount * kScrollObjWidth), [scrollView1 bounds].size.height)];
}
Any help would be appreciated on this.
Nick
So what I ended up doing is just making multiple instances of the comic controller inside the delegate instead of just re-using the one. Will update this if I run into problems.
Nick