I am using AsyncImageView classes to apply lazy loading on UITableView. And want to apply activity indicator on image view until the image is loaded on cell. Below is my code i am trying.
// AsyncIamgeView.m
- (void)connectionDidFinishLoading:(NSURLConnection*)theConnection {
//[connection release];
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
indicator.center = CGPointMake(15, 15);
connection=nil;
if ([[self subviews] count]>0) {
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImage *imgData = [UIImage imageWithData:data];
UIImageView* imageView = [[UIImageView alloc]init];
[imageView addSubview:indicator];
[indicator startAnimating];
if(imgData == nil)
{
imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"NoImagenew.png"]];
//[indicator stopAnimating];
}
else{
imageView = [[UIImageView alloc] initWithImage:imgData];
// [indicator stopAnimating];
}
//imageView.contentMode = UIViewContentModeScaleAspectFit;
//imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth || UIViewAutoresizingFlexibleHeight );
//[imageView sizeToFit];
[self addSubview:imageView];
imageView.frame = self.bounds;
//imageView.frame = CGRectMake(0, 0, 85, 94);
[imageView setNeedsLayout];
[self setNeedsLayout];
//[data release];
data=nil;
}
// cellForRowAtIndexPath method.
asyncImageView = [[AsyncImageView alloc]initWithFrame:CGRectMake(1, 3, 85, 54)];
[asyncImageView loadImageFromURL:[NSURL URLWithString:imageUrlString]];
[cell.contentView addSubview:asyncImageView];
This code shows activity indicator but when image is loaded after that not before loading images. Please guide for above.
You have to create AsyncImageView object instead of UIImageView, then it will automatically add indicator to your view
AsyncImageView *imageView = [[AsyncImageView alloc] initWithFrame:CGRectMake(1, 3, 85, 54)];
[cell addSubview:imageView];
//cancel loading previous image for cell
[[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget:imageView];
//load the image
imageView.imageURL = [imageURLs objectAtIndex:indexPath.row];
Here is an example of this
Currently you are adding activity indicator when your image is downloaded.
Here is the simple idea, hope you can implement this in your code
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// This method is called when your connection receives a response
// add your activity indication here and start animating
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// This method is called when your image is downloaded.
// remove your activity indicator or stop animating here
}
Hope u downloaded AsyncImageView from https://github.com/nicklockwood/AsyncImageView. By default, it has the feature to show activity indicator. You just dont need to add or remove any code by yourself to get this feature works. Just call loadImageWithURL.
I think u are using asynimageview classs, In that by default you will get the loader in the cell itself .
AysncImageView already has a loader.
You won't see it if your background is black since it loads the default activity indicator.
So, just set the activityIndicatorStyle property for your AsyncImageView object based on your background.
In my case, my background was black, so I used the following code :
asyncImgView.activityIndicatorStyle = UIActivityIndicatorViewStyleWhite;
Related
im using the followng method , to display image when a timestamp detecetd , am using
dispatch_async(dispatch_get_main_queue(), to do UIImageView , its never works its should open a new screen full size image that it ,
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *myImage = [UIImage imageNamed:#"img.jpg"];
UIImageView *myImageView = [[UIImageView alloc] initWithImage:myImage];
[myImageView setFrame:CGRectMake(0, 0, 100, 200)];
[myImageView release];
;
});
my full code
- (void) onPayload:(PayloadEvent *) event
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *header = #"[OnPayload] ";
if (event.payloadType == TYPE_IDENTIFIED)
{
if ((event.contentID != -1) && (event.timeStamp == -1))
{
[mUI performSelectorOnMainThread: #selector(Trace:) withObject:[NSString stringWithFormat:#"%# StaticID detected: %x\t\tConfidence: %f\n", header,(int)event.contentID, event.confidence] waitUntilDone:NO];
}
if ((event.timeStamp != -1) && (event.contentID == -1))
{
[mUI performSelectorOnMainThread: #selector(Trace:) withObject:[NSString stringWithFormat:#"%# Timestamp detected: %f\t\tConfidence: %f\n", header, event.timeStamp, event.confidence] waitUntilDone:NO];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *myImage = [UIImage imageNamed:#"img.jpg"];
UIImageView *myImageView = [[UIImageView alloc] initWithImage:myImage];
[myImageView setFrame:CGRectMake(0, 0, 100, 200)];
[myImageView release];
; });
You never add myImageView to any view as a subview.
Try to use this one in your code.
[self.view addSubview:myImageView];
You are creating an ImageView, assigning an Image to it and releasing the ImageView. In other words, you're not displaying the ImageView anywhere.
If you can't do something like [self.view addSubview:imageView], it means that you're not running this code on a UIViewController subclass.
You basically need to add this ImageView you're creating as a subview for the current view before releasing it.
In which class are you running this code? Do you know which View Controller is currently being displayed?
I have set up a subview "popup" in my application and I want to show a navController if the user taps a button on the subview popup. I've set up the button so far, but if I tap the button the navigationController appears under my popup!? I've searched for some solution but I didn't found any. The whole controller is actually displayed in a folder which you can find here: https://github.com/jwilling/JWFolders So the viewDidLoad belong to the folder and the rootview.
I tried to make it as a subview of the popup but that doesn't work too. Does anyone know how to treat that? I've set up the popup programmaticaly and the navigationController too.
Thanks in advance.
My code:
The navController setup:
- (IBAction)dothis:(id)sender {
MWPhotoBrowser *browser = [[MWPhotoBrowser alloc] initWithDelegate:self];
// Set browser options.
browser.wantsFullScreenLayout = YES;
browser.displayActionButton = YES;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:browser];
[self presentModalViewController:navController animated:YES];
NSMutableArray *photos = [[NSMutableArray alloc] init];
MWPhoto *photo;
photo = [MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"star" ofType:#"png"]];
photo.caption = #"The star is soo beateful...";
[photos addObject:photo];
self.photos = photos;
}
- (MWPhoto *)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index {
if (index < _photos.count)
return [_photos objectAtIndex:index];
return nil;
}
- (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser {
return _photos.count;
}
The popup code:
-(IBAction)mehr:(id)sender {
//the popup size and content
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 280, 440)];
CGRect welcomeLabelRect = contentView.bounds;
welcomeLabelRect.origin.y = 20;
welcomeLabelRect.size.height = 40;
UILabel *welcomeLabel = [[UILabel alloc] initWithFrame:welcomeLabelRect];
//an simple activityindicator
activityindi = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityindi.frame = CGRectMake(120, 200, 40, 40);
[activityindi startAnimating];
[contentView addSubview:activityindi];
//The Imageview
CGRect infoimagerect = CGRectMake(5, 70, 270, 200);
UIImageView *infoimage = [[UIImageView alloc] initWithFrame:infoimagerect];
//and the Button
cubut = [UIButton buttonWithType:UIButtonTypeCustom];
[cubut addTarget:self
action:#selector(dothis:)
forControlEvents:UIControlEventTouchUpInside];
[cubut setTitle:nil forState:UIControlStateNormal];
cubut.frame = CGRectMake(5, 70, 270, 200);
//retrieving data from parse.com
PFQuery *query = [PFQuery queryWithClassName:#"My-Application"];
[query getObjectInBackgroundWithId:#"My-ID"
block:^(PFObject *textdu, NSError *error) {
if (!error) {
//hide the Button if there is no image
cubut.hidden=YES;
//the headline of popup
UIFont *welcomeLabelFont = [UIFont fontWithName:#"copperplate" size:20];
welcomeLabel.text = [textdu objectForKey:#"header"];
welcomeLabel.font = welcomeLabelFont;
welcomeLabel.textColor = [UIColor whiteColor];
welcomeLabel.textAlignment = NSTextAlignmentCenter;
welcomeLabel.backgroundColor = [UIColor clearColor];
welcomeLabel.shadowColor = [UIColor blackColor];
welcomeLabel.shadowOffset = CGSizeMake(0, 1);
welcomeLabel.lineBreakMode = UILineBreakModeWordWrap;
welcomeLabel.numberOfLines = 2;
[contentView addSubview:welcomeLabel];
//the image from parse
if (!error) {
PFFile *imageFile = [textdu objectForKey:#"image"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
UIImage *image = [UIImage imageWithData:data];
infoimage.image = image;
infoimage.contentMode = UIViewContentModeScaleAspectFit;
//show the button when the image appears
cubut.hidden = NO;
[contentView addSubview:infoimage];
//stop the activityindicator
[activityindi stopAnimating];
}
}];
}
} else {
//show some text
welcomeLabel.text = #"No connection!";
[welcomeLabel sizeToFit];
//hide the button
cubut.hidden = YES;
[contentView addSubview:infoLabel];
//stop the activityindicator
[activityindi stopAnimating];
}
}];
//add the content to the KNGModal view
[[KGModal sharedInstance] showWithContentView:contentView andAnimated:YES];
}
My viewDidLoad
- (void)viewDidLoad
{
but.hidden = YES;
PFQuery *query = [PFQuery queryWithClassName:#"myapp"];
[query getObjectInBackgroundWithId:#"Rgq5vankdf"
block:^(PFObject *textu, NSError *error) {
if (!error) {
but.hidden = NO;
but.color = [UIColor colorWithRed:0.90f green:0.90f blue:0.90f alpha:1.00f];
} else {
//if failure
but.hidden = YES;
mol.text = #"No Connection";
}
}];
[super viewDidLoad];
}
Pictures:
The button to open the folder:
The folder itself:
The popup:
Thanks in advance.
From the so far discussion and debugging the code you want to have the photo browser on the pop-up with a navigation controller.
So here is the sample code which implements this functionality, have a look at it.
I have used the same KGModal sample code and extended as per the requirement. I have used Xib to have a view with navigation bar.
To dismiss the pop-up from any where in the app you can use the below line, as it is shared instance.
[[KGModal sharedInstance] hideAnimated:YES];
Update:
The reason for showing the photo browser with in folderView is, you are trying to present the photoBrowser within the folderView, so it was presenting within the folderView of very small height & not able to see any photo.
So my suggestion is, as the user taps on pop-up to view photoBrowser you just remove pop-up and present the photoBrowser from the viewController class, as other than this class everything is handled through views.
I have made the changes as per above & works fine, to the code given by you, download the code here and have a look at it.
Let me know if it fulfills your needs.
Thanks
I noticed this line of code:
[[KGModal sharedInstance] showWithContentView: contentView andAnimated: YES];
And I can only think that, since it is a singleton, it adds the contentView on the UIApplication's key window. If that is the case, then a modal view controller will always be below the popup. You can solve this by adding a new method to the KGModal class
- (void) showWithContentView: (UIView*) contentView
inViewController: (UIViewController*) controller
andAnimated: (BOOL) animated;
the method should show the popup in the specified controller's view; you should use that method instead.
Edit
After some more digging, I found that KGModal displays the popup on another window. The quickest fix would be to dismiss the popup, then show the nav controller.
I have an image picker to pick multiple images from the photo library. The picked photos are resized and saved to file in imagePickerController:didFinishPickingMediaWithInfo:. It takes a few seconds.
Could I put an indicator on the view?
I have tried to use addSubview:indicatorView in imagePickerController:didFinishPickingMediaWithInfo: method. But indicatorView doesn't appear. It gets dismissed with the imagePickerView.
You should add the UIActivityIndicatorView at the top of the view hierarchy or it will get dismissed with the UIPickerViewController, unless you use a callback after the resize operation and in the callback you dismiss the UIImagePickerController.
Or you could use a progress HUD like SVProgressHUD.
Hope this helps =)
We did a little chat session and solved this way:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
UIView *primaryImage = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,460)];
primaryImage.backgroundColor = [UIColor redColor];
primaryImage.alpha =0.9;
UIView *secondaryImage = [[UIView alloc] initWithFrame:CGRectMake(0,0,70,70)];
secondaryImage.center = CGPointMake(160, 240);
secondaryImage.backgroundColor = [UIColor blackColor];
secondaryImage.alpha = 0.9;
secondaryImage.layer.cornerRadius = 12;
[primaryImage addSubview:secondaryImage];
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
indicator.center = CGPointMake(35, 35);
[indicator setHidesWhenStopped:NO];
[secondaryImage addSubview:indicator];
[indicator startAnimating];
[indicator release];
[secondaryImage release];
[picker.view addSubview:primaryImage];
[primaryImage release];
});
// Put here the code to resize the image
dispatch_async(dispatch_get_main_queue(), ^{
// Dismiss the picker controller
});
});
I have a tableview, and when i click on a row, it navigates to another view; The code for the navigation part is shown below;
ShowImageController *showImageController = [[HowItWorksViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:showImageController animated:YES];
The other view contains an image, i have added the image to its viewDidLoad. and here's the code for that
UIImageView *imageView=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"hello.png"]];
[imageView setFrame:CGRectMake(o, o, 200, 300)];
[[self view] addSubview:imageView ];
The problem is When i click on the row it takes a long time (extremely slow), to navigate to the other screen.
note: Rows which didn't have an image in the other view navigated well with no issue. Why is this happening ? and how can i fix it ?
Try loading the images in a asynk task or nsoperationqueue :)
Definitely sounds like the images are big and therefore taking a while to load. I suggest you either use smaller images or if you have no control over them you might want to try loading the images in the background. Here is some code to get you started with loading them in the background:
- (void)decodeImageInBackgroundThread:(UIImage*)decodedImage forImageView:(UIImageView*)imageView {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
CGImageRef originalImage = [decodedImage CGImage];
CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(originalImage));
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData(imageData);
if (imageData != NULL) {
CFRelease(imageData);
}
CGImageRef image = CGImageCreate(CGImageGetWidth(originalImage),
CGImageGetHeight(originalImage),
CGImageGetBitsPerComponent(originalImage),
CGImageGetBitsPerPixel(originalImage),
CGImageGetBytesPerRow(originalImage),
CGImageGetColorSpace(originalImage),
CGImageGetBitmapInfo(originalImage),
imageDataProvider,
CGImageGetDecode(originalImage),
CGImageGetShouldInterpolate(originalImage),
CGImageGetRenderingIntent(originalImage));
if (imageDataProvider != NULL) {
CGDataProviderRelease(imageDataProvider);
}
dispatch_async(dispatch_get_main_queue(), ^{
[imageView setImage:[UIImage imageWithCGImage:image]];
CGImageRelease(image);
});
});
}
Which you can then use like this:
- (void)viewDidLoad {
...
UIImage *image = [UIImage imageNamed:#"hello.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:nil];
[imageView setFrame:CGRectMake(0.0f, 0.0f, 200.0f, 300.0f)];
[[self view] addSubview:imageView];
[self decodeImageInBackgroundThread:image forImageView:imageView];
}
Why doesn't the cell show anything in this code:
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[cell.imageView addSubview:spinner];
[spinner startAnimating];
cell.textLabel.text=#"Carregando...";
[spinner release];
I'm doing this inside tableView:cellForRowAtIndexPath:.
I tried size to fit, create a frame to cell.imageView and a same size frame to the spinner, but nothing works.
What´s wrong with this code?
Thank you..!
A slight modification of the method from Thiago:
I think adding the spinner directly to the cell view felt a little hacky, so I used a 1x1 transparent png as the image view and resized it to be whatever my spinner size is:
UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"NoReuse"] autorelease];
cell.textLabel.text = #"Loading...";
UIActivityIndicatorView *spinner = [[[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] autorelease];
// Spacer is a 1x1 transparent png
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();
cell.imageView.image = resizedSpacer;
[cell.imageView addSubview:spinner];
[spinner startAnimating];
return cell;
That gives a cell that looks like this:
I found the answer...
David Maymudes was partialy right... It´s necessary to have a "background" to the cell.imageView... But must be a image, not just a frame. So just create a UIImage as a "white background" and set in cell.imageView.image. The code will be:
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
UIImage *whiteback = [[UIImage alloc] initWithContentsOfFile:#"whiteback.png"];
cell.imageView.image = whiteback;
[cell.imageView addSubview:spinner];
[spinner startAnimating];
cell.textLabel.text=#"Carregando...";
[whiteback release];
[spinner release];
The whiteback.png is just a 25x25 pixels white square...
Thanks for everyone help... See you...
I think the cell's imageView will probably have a zero-size rectangle, because you haven't put a picture in it. So the spinner is inside but invisible.
So instead of putting the spinner within the imageView, just put it within the cell...
[cell addSubview:spinner];
spinner.frame = CGRectMake(145, 0, 30, 30); // if you want it centered horizontally...
you could also do
cell.accessoryView = spinner;
to put the spinner over at the far right of the cell.