In my storyboard I have a view with a UIWebView which is filling the entire area except from tab and navigation bar. The controller for the view is implements the protocol UIWebViewDelegate. The controller is set as delegate for the UIWebView:
#pragma mark - UIWebViewDelegate
- (void) webViewDidStartLoad:(UIWebView *)webView {
NSLog(@"webViewDidStartLoad");
}
- (void) webViewDidFinishLoad:(UIWebView *)webView {
NSLog(@"webViewDidFinishLoad");
}
While the UIWebView is loading I'll show an black background with an image stating that it is loading. How can I do that?
EDIT1:
I'm trying to add the default ActivityIndicatorView
instead of a static image. But this just gives me a black background with a small white area. What is the problem?
UIImageView *loadingImageView = [[UIImageView alloc] initWithFrame:webView.frame];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
UIImage *spacer = [UIImage imageNamed:@"spacer"];
UIGraphicsBeginImageContext(spinner.frame.size);
[spacer drawInRect:CGRectMake(0,0,spinner.frame.size.width,spinner.frame.size.height)];
UIImage* resizedSpacer = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
loadingImageView.image = resizedSpacer;
[loadingImageView setBackgroundColor:[UIColor blackColor]];
[loadingImageView setContentMode:UIViewContentModeCenter];
self.loadingImageView = loadingImageView;
In your controller .h
@property (nonatomic, retain) UIImageView *loadingImageView;
In your controller .m
@synthesize loadingImageView;
- (void)viewDidLoad {
...
UIImageView *theLoadingImageView = [[UIImageView alloc] initWithFrame:webView.frame];
theLoadingImageView.image = [UIImage imageNamed:@"your_image.png"];
self.loadingImageView = theLoadingImageView;
[theLoadingImageView release];
...
}
- (void) webViewDidStartLoad:(UIWebView *)webView {
[self.view addSubview:self.loadingImageView];
}
- (void) webViewDidFinishLoad:(UIWebView *)webView {
[self.loadingImageView removeFromSuperview];
}
EDIT 1:
If you would like to show an ActivityIndicatorView instead of a static image, here is a little helper class that I love to use:
LoadingIndicator.h
#import <UIKit/UIKit.h>
@interface LoadingIndicator : UIView {
UIActivityIndicatorView *activityIndicator;
UILabel *labelMessage;
}
@property(retain) UIActivityIndicatorView *activityIndicator;
@property(retain) UILabel *labelMessage;
- (id)init;
- (void)show:(NSString *)theMessage;
- (void)hide;
- (void)refreshPosition;
@end
LoadingIndicator.m
#import "LoadingIndicator.h"
#import <QuartzCore/QuartzCore.h>
@implementation LoadingIndicator
@synthesize labelMessage, activityIndicator;
- (id)init {
if (self = [super initWithFrame:CGRectMake(25, 130, 270, 100)]) {
// Vue
self.backgroundColor = [UIColor blackColor];
self.alpha = 0.80;
self.layer.cornerRadius = 5;
// Label : message
UILabel *theLabelMessage = [[UILabel alloc] initWithFrame:CGRectMake(15, 65, 240, 20)];
theLabelMessage.backgroundColor = [UIColor clearColor];
theLabelMessage.textColor = [UIColor whiteColor];
theLabelMessage.text = NSLocalizedString(@"Loading", @"Loading");
theLabelMessage.textAlignment = UITextAlignmentCenter;
theLabelMessage.font = [UIFont boldSystemFontOfSize:16];
theLabelMessage.adjustsFontSizeToFitWidth = YES;
self.labelMessage = theLabelMessage;
[self addSubview:theLabelMessage];
[theLabelMessage release];
// Activity Indicator
UIActivityIndicatorView *theActivityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
theActivityIndicator.frame = CGRectMake(115, 15, 40, 40);
self.activityIndicator = theActivityIndicator;
[self addSubview:theActivityIndicator];
[theActivityIndicator release];
}
return self;
}
- (void)show:(NSString *)theMessage {
self.labelMessage.text = theMessage;
[self.activityIndicator startAnimating];
self.hidden = NO;
[self.superview bringSubviewToFront:self];
[self refreshPosition];
}
- (void)hide {
[self.activityIndicator stopAnimating];
self.hidden = YES;
}
- (void)refreshPosition {
self.center = self.superview.center;
}
- (void)dealloc {
self.labelMessage = nil;
self.activityIndicator = nil;
[super dealloc];
}
@end
Then in your view.h
#import <UIKit/UIKit.h>
#import "LoadingIndicator.h"
@interface YourView : UIView {
LoadingIndicator *loadingIndicator;
}
@property(retain) LoadingIndicator *loadingIndicator;
- (void)showLoadingIndicator:(NSString *)theMessage;
- (void)hideLoadingIndicator;
@end
In your view.m
#import "YourView.h"
@implementation YourView
@synthesize loadingIndicator;
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
...
// Add your UIWebView etc
...
// Loading Indicator
LoadingIndicator *theLoadingIndicator = [[LoadingIndicator alloc] init];
theLoadingIndicator.hidden = YES; // Hidden by default
self.loadingIndicator = theLoadingIndicator;
[self addSubview:theLoadingIndicator];
[theLoadingIndicator release];
...
}
return self;
}
- (void)showLoadingIndicator:(NSString *)theMessage {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self.loadingIndicator performSelectorOnMainThread:@selector(show:) withObject:theMessage waitUntilDone:NO];
[pool release];
}
- (void)hideLoadingIndicator {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self.loadingIndicator performSelectorOnMainThread:@selector(hide) withObject:nil waitUntilDone:NO];
[pool release];
}
- (void)dealloc {
self.loadingIndicator = nil;
[super dealloc];
}
@end
Finally in your WebView delegate:
- (void) webViewDidStartLoad:(UIWebView *)webView {
[(YourView *)self.view showLoadingIndicator:@"Loading"];
}
- (void) webViewDidFinishLoad:(UIWebView *)webView {
[(YourView *)self.view hideLoadingIndicator];
}
This will look something like this: