I'm trying to display a loading icon while my iPhone app downloads a network resource, but I can't figure out how to make it show up correctly.
I searched around and found some details on the UIActivityView class, but the available example source code didn't work, and the documentation is kind of terse.
Could someone provide a simple example on how to use this class?
Assuming you've got a view controller set up, and would like to add a UIActivityIndicator to it, here's how you could do it:
(assume you've got a member variable called indicator, which you can use later to clean up)
For your interface (.h file):
UIActivityIndicator *indicator;
For your implementation (.m file):
Start the Animation
CGRect b = self.view.bounds;
indicator = [[UIActivityIndicator alloc] initWithActivityIndicatorStyle:
UIActivityIndicatorStyleWhite];
//center the indicator in the view
indicator.frame = CGRectMake((b.size.width - 20) / 2, (b.size.height - 20) / 2, 20, 20);
[self.view addSubview: indicator];
[indicator release];
[indicator startAnimating];
Stop the Animation
[indicator removeFromSuperview];
indicator = nil;
Ben answer looks pretty similar to what I'm doing - your guess about the thread is probably accurate. Are you using NSURLConnection to handle your downloading? If so, are you using the synchronous or asynchronous version? If it's the synchronous version and you're simply starting and stopping the animation around the synchronous call, then the UI isn't updating until after the you've stopped the animation.
Related
My app is loading an online plist on launch, which is needed to display the data in the tableview which will be shown. Depending on the internet connection, loading the plist can take rather long (4-5 seconds) and the launch screen is shown this entire time. Now, I'd like to put an activity indicator in the status bar (while launch screen is still up) so that the user knows the app is busy loading.
I'm loading the plist and creating arrays etc. in ViewDidLoad, and I'm not sure on how to achieve what I've sketched above.
Do you have any thoughts on this matter? Thanks.
I would reconsider your approach if I were you. Unless you've specifically put in measures to avoid it, it's likely that your code to download the plist will be being called before applicationDidFinishLaunching: returns. This is not good because if it takes a long time then the watchdog might kill your app even before it's actually properly launched. Not a good thing.
You should really be kicking off the download in a background thread and just stick a spinner in your actual view. So something like this:
- (void)viewDidLoad {
...
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
spinner.center = CGPointMake(self.view.bounds.size.width / 2.0f, self.view.bounds.size.height / 2.0f);
[spinner startAnimating];
[self.view addSubview:spinner];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do your downloading of your plist, etc
dispatch_async(dispatch_get_main_queue(), ^{
[spinner removeFromSuperview];
});
});
}
I have seen many times waiting panels (panels with a uiactivityindicatorview) black/dark with some transparency and white labels.
Like this one :
I guess it is a standard element.
Where can I find it?
Try This. it's the best solution I came across to show the activity. MBProgressHUD
MBProgressHUD looks nice. You might want to check out http://code.google.com/p/toast-notifications-ios/ too.
There's no iOS component that does this.
If you don't want to include an external library just for this one component then you can do it using UI components.
/* Warning, typed from memory */
// Create the UIView that's the background
UIView *pleaseWaitView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 80)];
[pleaseWaitView setBackgroundColor:[UIColor colorWithWhite:0.5 alpha:0.5]];
[[pleaseWaitView layer] setCornerRadius:5.0f];
// And create an activity indicator
UIActivityIndicator *i = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[i startAnimating];
[pleaseWaitView addSubview:i];
[i release];
// Add it to the main view (in the middle)
[pleaseWaitView setCenter:CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2)];
[self.view addSubview:pleaseWaitView];
You can add a UILabel with whatever text you want (in your case, 'Authenticating') in the same way as you added the activity indicator.
The tricky part is setting the corner radius - you will probably need this at the top of your .m file :
#import <QuartzCore/QuartzCore.h>
NB You can do this in interface builder as well if you want (apart from the corner radius bit!) ;)
I answered a question that included an overlay like this. I included the code and the overlay image you need to do it with. Take a look at this answer and take a look at the screen shot it created. I use this overlay as I send email in the background so you will want to edit the code to do your function but the overlay code is already in place.
Locking the Fields in MFMailComposeViewController
Happy Coding!
Check out DSActivityView. I've successfully used it in a few of my projects.
As by now there is no standard UIElement for that in iOS.
But checkout this library:
I have a server that provides a JSON with certain parameters and the name of an image. Then I get the image with the name provided. All this is done in one function called loadingOfImageAndInformation. I use the MBProgressHUD as follows:
[HUD showWhileExecuting:#selector(loadingOfImageAndInformation)
onTarget:self withObject:nil animated:YES];
Which should show the progress thingy when this method is currently running. Now, inside the method I use a ASIHTTPRequest to retrieve all the data I need. Which means that sometime it will jump from that method to the request methods (to retrieve the image and assign it to the UIImageView on the requestLoadDone).
Now, the problem is that the MBProgressHUD thingy only shows until the parameters are shown (the image description I put on a label, the description I got from JSON) and not until the parameters AND image are shown. So basically the loader disappears BEFORE the image is on the imageView.
This is the code in question:
- (void) loadingHudAlert {
NSString *loadingMessage = NSLocalizedString(#"Please Wait",
#"Message displayed when the loading spinner is on");
HUD = [[MBProgressHUD alloc] initWithView:self.view];
HUD.minShowTime = 1.0;
[self.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = loadingMessage;
[HUD showWhileExecuting:#selector(loadingOfImageAndInformation)
onTarget:self withObject:nil animated:YES];
}
The ASIHTTPRequest does all request on an asynchronous mode. Without a queue.
Thank you for your feedback!!!!
I solved it using a boolean, if the method requestLoadDone is finished the bool turns to be NO and while the boolean is YES the loadingOfImageAndInformation will run (which means will run until the image is correctly retrieved.) I haven't posted this as an answer since maybe someone has a better solution.
So you're saying that the HUD disappears before the image is shown at your imageview, don't you? Maybe this is more due to how cocoa processes this stuff than MBProgressHUD problem.
How are you assigning the image? Have you tried?
[yourimageview setNeedsDisplay];
What I'm trying to say is that, if this is how cocoa manages the imageviews showing stuff, maybe you can try to "force" the reload or displaying to be done before.
I'm creating an iPhone app and am wondering how to have a progress animation when you're loading data? I see this a lot in applications such as Tweetie, but haven't been able to figure it out myself.
If you are talking about loading data over a network, ASIHTTPRequest provides a way to pass a reference to a UIProgressView that it will update with accurate progress for both downloads and uploads. I highly recommend it.
If you only want the small network spinner in the statusbar you activate it with
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
...and deactivate
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
In an app I wrote for our company that performs a very long sync (by accessing a web service), I display an UIActivityIndicatorView.
On the same view, I also included a label that displays "Fetching X of Y..." The label is updated via an NSTimer. The call looks like:
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(updateLabel:) userInfo:nil repeats:YES];
In addition, in order for the UI to actually update, I had to spin off the code to fetch data from the webservice into its own thread.
Do you mean a progress bar, or an activity indicator? For an occurring activity, you can use UIActivityIndicatorView.
The flow will look a little like this.
UIActivityIndivatorView *activity = [[UIActivityIndivatorView alloc] init];
//attach activity to a view or a bar
//begin activity
[activity startAnimating];
//here will be the functionality for your data gathering progress
//once your progress or activity is done
[activity stopAnimating];
Hope this helps.
I don't want to just use a UIActivityIndicatorView, I want the spinning animation that you see in the Maps application while you are doing a CoreLocation lookup.
Do I have to create my own animation, or is there an easy way?
I'm referring to the standard Apple "Maps" application. Specifically I'm referring to the animation that occurs in the button in the UIToolbar at the bottom of the page, when you press the button to find your location.
There are two components to this animatio, first the "button push" animation, and then the spinning "busy" animation. I presume the latter is done with a UIActivityIndicatorView, but I was hoping that the whole thing was packaged together into a single control of some sort.
You might be thinking of the network activity indicator, which can be set like
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
EDIT: Thanks for the clarification:
The Map app is using a UIBarButtonItem with a UIActivityIndicatorIndicator as the custom view. You can do something along the lines of:
UIActivityIndicatorView *indicator =
[[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithCustomView:indicator];
[indicator startAnimating];
[indicator release];
Hey, why don't you just put an indicator view on top of a button and display it only when a location is in progress? I did exactly that and it does work perfectly!