Ok, I'm adding a loading screen to UITableViewController just like in the YouTube, AppStore or iTunes apps. And I'm doing it like this:
[self.view addSubview:[[LoadingView alloc] initWithFrame:self.view.bounds]];
dispatch_queue_t downloadQueue = dispatch_queue_create("downloader", NULL);
dispatch_async(downloadQueue, ^{
//load data
dispatch_async(dispatch_get_main_queue(), ^{
[[self.view.subviews lastObject] removeFromSuperview];
//reload data graphicaly
});
});
dispatch_release(downloadQueue);
And LoadingView
is a subclass of UIView
that has a white background a spinner (UIActivityIndicatorView
) and a label: "Loading…". Now I want to place this two thing in the center and make them somewhat "rock solid", so when you init that View on viewDidLoad
and then it's superview resizes due to the presence of navigation bar and tab bar everything stays nicely centered. Oh and I want it to handle the rotation… etc.
Now here is how I've tried to do it:
#define LABEL_WIDTH 80
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setBackgroundColor:[UIColor whiteColor]];
UIActivityIndicatorView* spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
UIView *innerView = [[UIView alloc] initWithFrame:CGRectMake(0,
0,
spinner.frame.size.width + 5 + LABEL_WIDTH,
spinner.frame.size.height)];
innerView.center = self.center;
CGRect transitionFrame = spinner.frame;
transitionFrame.origin.x = innerView.frame.origin.x;
transitionFrame.origin.y = innerView.frame.origin.y;
spinner.frame = transitionFrame;
transitionFrame.origin.x = transitionFrame.origin.x+5+spinner.frame.size.width;
transitionFrame.size.width = LABEL_WIDTH;
UILabel *label = [[UILabel alloc] initWithFrame:transitionFrame];
label.text = @"Loading…";
[innerView addSubview: spinner];
[spinner startAnimating];
[innerView addSubview: label];
innerView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin);
[self addSubview:innerView];
self.autoresizingMask = (UIViewAutoresizingFlexibleWidth|
UIViewAutoresizingFlexibleHeight);
}
return self;
}
So the label and the spinner are set as subviews of some other view and that view is centered in our LoadingView
and has all struts and springs unset, so after resizing it should stay in the middle. And LoadingView
has all struts and springs set so it will change size together with it's superview…
But it all isn't working as intended, and I feel like I'm on the bad path and my code is wrong. Can someone help me a bit and explain what I should take a look at?
Seems that
innerView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin);
was bad idea to center inner views.
I solved it by redefining layoutSubviews
method.
The code itself can be found at https://github.com/Uko/UILoadingView/blob/master/UILoadingView.m