My UIScrollView shifts after dismissing Modal View - objective-c

I've got a UIScrollView on my main ViewControler. When it initially loads from startup the UIScrollview is placed correctly but when I go to a modal view and then dismiss that modal view the UIScrollView shifts up several pixels from the position that my UIScrollView was at when I loaded the modal view (the amount of shift seems to be relative to the position of the UIScrollView). So in other words if my UIScrollView was all the way to the top it loads correctly if I was scrolled all the way to the bottom when I go to a modal view and then go back it seems to have shifted up approximately 20 to 30 pixels cutting the top of the content off in my UIScrollView.
I cant figure out why its loading differently depending on the amount I've scrolled before loading the modal view.
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat scrollFrameHeight = [[UIScreen mainScreen] applicationFrame].size.height;
CGFloat scrollFrameWidth = [[UIScreen mainScreen] applicationFrame].size.width;
scrollView.frame = CGRectMake(0, 0, scrollFrameWidth, scrollFrameHeight);
}
FYI... I've tried using static numbers in place of my variables and I still get the strange shift.

Related

How to programmaticaly add an UIActivityIndicatorView to a view on the bottom right corner

I'm trying to programmatically add and position an UIActivityIndicatorView to the bottom right corner of my main view. My app can rotate.
Right now in my viewDidLoad-method I have this code:
[super viewDidLoad];
UIActivityIndicatorView *iv = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[iv startAnimating];
int margin = 14;
iv.frame = CGRectMake(
self.view.frame.size.width - iv.frame.size.width - margin,
self.view.frame.size.height - iv.frame.size.height - margin,
iv.frame.size.width,
iv.frame.size.height );
iv.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[self.view addSubview:iv];
When the app is starting in portrait, the activity-indicator is positioned correctly. As soon as I rotate the device (or start the app in landscape) the positioning of the activityindicator is wrong.
How can this be fixed?
You also need a flexible top margin, so that the view will slip to up or down as the height of the main view changes. Also, the parent view needs  to autoresizesSubviews set to YES (which is default YES, so you are probably ok).
distanceLabel.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleTopMargin);
On your view controller, override the method shouldAutorotateToInterfaceOrientation and correct the position when orientation changes.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;

I would like to implement a half UITableView half MapView UIView with a button in the middle

Well, this is what I want to do in my app: I would like to implment a UIView with a map on the top half of the screen and a tableview on the other half with two buttons in the middle. If I press one of the buttons the map will get fullscreen and if I press the other one the tableView will fit all the screen.
Any suggestion?
In one view controller like a UINavigationController create an MKMapView with a frame the size of the top half of the view and add it as subview of your view controller. Then I would create a UIToolbar to hold your buttons and make the top of it's frame line up with bottom of the MKMapView. Finally create a UITableView with it's frame just below the others (make sure you hook up it's delegates).
Then assign the target of your UIBarButtonItem that makes the map go fullscreen to a method that animates the frames of all three views like this:
[UIView animateWithDuration:0.24
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:(void (^)(void)) ^{
self.toolbar.frame = CGRectMake(0, MAP_HEIGHT_FULLSCREEN, 320, TOOLBAR_HEIGHT);
self.mapView.frame = CGRectMake(0,0,320,MAP_HEIGHT_FULLSCREEN);
self.tableView.frame = CGRectMake(0, MAP_HEIGHT_FULLSCREEN+TOOLBAR_HEIGHT, 320, MAP_HEIGHT_FULLSCREEN-MAP_HEIGHT);
}
completion:^ (BOOL finished){}
];
Create both views how you are planning, On one button click, change the frame of one view to fit the full screen, if you click the other button, do the same thing to the other view.

How to keep UIView at relative distance from other after resizing?

I have five UIView on a UIScrollView. All of them with the same width. Each view has other subviews that resize its height according to the content assigned, thus making the parent UIView and the UIScrollView resizable as well. I am trying to keep the 5 UIView separated from each other at a certain "Padding" distance even after resizing. What I do right now is set the position of the origin.y and the height of each UIView when layoutSubviews is called. Is there an easier way to do this?
I have tried to set their position on creation like: CGRectMake(0, aboveView.frame.origin.y + aboveView.frame.size.height + Padding, width, 0) and setting its autoresizingMask to UIViewAutoresizingMaskTopMargin. Hoping that when I call sizeToFit on the main UIView, all the UView will set their positions relative to the view above them.
Overriding layoutSubviews is the right way to do this. UIKit doesn't have any built-in layout management that can do it for you.
However, you might not realize that UIScrollView sends itself layoutSubviews each time it scrolls - on every frame of the scrolling. That may be a lot more often than you need! You don't want to do a lot of work in a UIScrollView's layoutSubviews if you can avoid it.
To avoid doing extra layout, I suggest you set up your view hierarchy like this:
UIScrollView
ContainerView with layoutSubviews method
content view 1
content view 2
content view 3
content view 4
content view 5
Use a standard UIScrollView. Give it one subview, which is a custom UIView subclass (I called it ContainerView in my example). The ContainerView has your five content views as its subviews.
When you assign new content to one of your five content views, send sizeToFit to that content view. If the view's size changes, UIKit should automatically send layoutSubviews to its superview - the ContainerView. The ContainerView's layoutSubviews method adjusts the position of its subviews to maintain the padding between them, and then sets the contentSize of its parent - the UIScrollView.
- (void)layoutSubviews {
CGRect myFrame = CGRectZero;
for (UIView *subview in self.subviews) {
CGRect frame = subview.frame;
if (myFrame.size.height > 0) {
frame.origin.y = myBounds.size.height + Padding;
subview.frame = frame;
}
myFrame = CGRectUnion(myFrame, frame);
}
self.frame = myFrame;
UIScrollView *scrollView = self.superview;
scrollView.contentSize = myFrame.size;
}
This way, you don't do any extra work just because the scroll view scrolled. You only lay out your content views when the content actually changes.

Releasing invisible buttons with images in UIScrollView

I have main UIScrollView with lots off buttons which i create like this:
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom]
every button have an image:
UIImage *fileImage = [UIImage imageNamed:#"sun.png"];
[myButton setBackgroundImage:fileImage forState:UIControlStateNormal];
Buttons count could be more than 500. So i need to remove from UIscrollView invisible buttons with images to save memory ?
I believe in this method i need to calculate when UIscrollview is stopped scrolling and for example 20 images are invisible, then i need to remove them and reduce scroller contentOffset.
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
float bottomEdge = scrollView.contentOffset.y + scrollView.frame.size.height;
}
Maybe some one could give me tips on this. Or even have a good bookmarked tutorial.
I created a similar thing to this using UIViews in a UIScrollView. When the UIScrollView loads, I set the contentView size of the scrollView to be the size of all the views but only loaded the views that can be seen, then when the user scrolls i added the previous/next views and removed the hidden views.
This question helped me: How to implement UIScrollView with 1000+ subviews? especially akosma's answer

Full-screen UIImageView aligning to bottom

With the following code:
UIImageView *largeImageView = [[UIImageView alloc] initWithImage:theImage];
[largeImageView setContentMode:UIViewContentModeScaleAspectFit];
largeImageView.frame = [[UIScreen mainScreen] applicationFrame];
[viewController.view addSubview:largeImageView];
viewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:viewController animated:YES];
I would expect the image to be at the top of the View, not the bottom. I double-checked the origin x and y, and they are 0,0.
Here is a screenshot: http://cl.ly/8F3J
Thanks to Tommy for providing some thinking out loud and debugging help, I figured out what I was doing wrong. I changed around the order of operations and added the imageview as a subview after I pushed the viewcontroller on the nav stack. This fixed the issue as my view controller had it's new view from the nav controller.
largeImageView is a subview of viewController.view, so its coordinates are relative to that of its superview. Probably you want something more like:
// the bounds of viewController.view contain its correct size, but
// have an origin of (0, 0)
largeImageView.frame = viewController.view.bounds;
[viewController.view addSubview:largeImageView];
What's probably happening at the minute is that you're getting a frame much larger than the view controller's view size, then the fact that UIViewContentModeScaleAspectFit will be adding some space at the top and bottom of the view as necessary (assuming your image is proportionally wider than the target view) is pushing the image off the bottom of the screen.