Friday, August 27, 2010

Easy way lazyload image on UITableViewCell

This is sample article lazyload image on UITableViewCell. The libary for use this article
http://allseeing-i.com/ASIHTTPRequest/ and the sample code from Apple
ThumbImageView.h

#import "ASIHTTPRequest.h"

@protocol ThumbImageViewDelegate;




@interface ThumbImageView : UIImageView {
id delegate;
NSString *imageName;
CGSize imageSize;
CGRect home;
BOOL dragging;
CGPoint touchLocation; // Location of touch in own coordinates (stays constant during dragging).
}

@property (nonatomic, assign) id delegate;
@property (nonatomic, retain) NSString *imageName;
@property (nonatomic, assign) CGSize imageSize;
@property (nonatomic, assign) CGRect home;
@property (nonatomic, assign) CGPoint touchLocation;

- (void)goHome;
- (void)moveByOffset:(CGPoint)offset;
- (id)initWithImageAtUrl:(NSURL*)theUrl;

@end



@protocol ThumbImageViewDelegate

@optional
- (void)thumbImageViewWasTapped:(ThumbImageView *)tiv;
- (void)thumbImageViewStartedTracking:(ThumbImageView *)tiv;
- (void)thumbImageViewMoved:(ThumbImageView *)tiv;
- (void)thumbImageViewStoppedTracking:(ThumbImageView *)tiv;

@end


ThumbImageView.m
#import "ThumbImageView.h"
#import "MoMagIO.h"

#define DRAG_THRESHOLD 10
#define ACTIVITYVIEW_TAG 123

float distanceBetweenPoints(CGPoint a, CGPoint b);

@interface ThumbImageView(PrivateMethods)

-(void)addLoadingCircle;
-(void)removeLoadingCircle;
-(void)downloadImageWithURL:(NSURL*)theUrl;

@end


@implementation ThumbImageView


@synthesize delegate;
@synthesize imageName;
@synthesize imageSize;
@synthesize home;
@synthesize touchLocation;

- (id)initWithImageAtUrl:(NSURL*)theUrl{

self = [super init];
if (self) {
[self setUserInteractionEnabled:YES];
[self setExclusiveTouch:YES];
self.image = nil;
// Add loading circle
[self addLoadingCircle];
// Asyncronous download image
[self downloadImageWithURL:theUrl];
}
return self;
}

-(void)addLoadingCircle{

UIActivityIndicatorView *indicatorView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
indicatorView.center = CGPointMake((152/2),(195/2));
indicatorView.tag = ACTIVITYVIEW_TAG;
[self addSubview:[indicatorView autorelease]];
[indicatorView startAnimating];
}

-(void)removeLoadingCircle{

UIActivityIndicatorView *indicatorView = (UIActivityIndicatorView*)[self viewWithTag:ACTIVITYVIEW_TAG];
[indicatorView stopAnimating];
[indicatorView removeFromSuperview];
}
-(void)downloadImageWithURL:(NSURL*)theUrl{
NSLog(@"Url for download %@",theUrl);
NSString *pathToSave = [[MoMagIO getCacheDirPath] stringByAppendingPathComponent:[[theUrl path] lastPathComponent]];
//
if(imageName != pathToSave){
[imageName release];
imageName = [pathToSave retain];
}
NSFileManager *fm = [NSFileManager defaultManager];
if([fm fileExistsAtPath:self.imageName]){
UIImage *img = [[UIImage alloc] initWithContentsOfFile:imageName];
if(img){
self.image = img;
[self setNeedsDisplay];
}
[img release];
[self removeLoadingCircle];
}else {

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:theUrl];
[request setDelegate:self];
request.didFailSelector = @selector(downloadDidFailed:);
request.didFinishSelector = @selector(downloadDidCompleted:);
request.downloadDestinationPath = imageName;
[request startAsynchronous];
}
}
-(void)downloadDidFailed:(ASIHTTPRequest *)request{
#ifdef DEBUG
NSLog(@"ThumbImageView:-(void)downloadDidFailed:(ASIHTTPRequest *)request %@",[request error]);
#endif
NSBundle *bundle = [NSBundle mainBundle];
NSString *root = [[bundle resourcePath] stringByAppendingPathComponent:@"cover_preload.jpg"];
UIImage *img = [[UIImage alloc] initWithContentsOfFile:root];
if(img){
self.image = img;
[self setNeedsDisplay];
}
[img release];
[self removeLoadingCircle];
}
-(void)downloadDidCompleted:(ASIHTTPRequest *)request{
UIImage *img = [[UIImage alloc] initWithContentsOfFile:imageName];
if(img){
self.image = img;
[self setNeedsDisplay];
}
[img release];

[self removeLoadingCircle];
}

- (id)initWithImage:(UIImage *)image {
self = [super initWithImage:image];
if (self) {
[self setUserInteractionEnabled:YES];
[self setExclusiveTouch:YES];
}
return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// store the location of the starting touch so we can decide when we've moved far enough to drag
touchLocation = [[touches anyObject] locationInView:self];
if ([delegate respondsToSelector:@selector(thumbImageViewStartedTracking:)])
[delegate thumbImageViewStartedTracking:self];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
// we want to establish a minimum distance that the touch has to move before it counts as dragging,
// so that the slight movement involved in a tap doesn't cause the frame to move.
/**CGPoint newTouchLocation = [[touches anyObject] locationInView:self];
if (dragging) {
float deltaX = newTouchLocation.x - touchLocation.x;
float deltaY = newTouchLocation.y - touchLocation.y;
[self moveByOffset:CGPointMake(deltaX, deltaY)];
}
else if (distanceBetweenPoints(touchLocation, newTouchLocation) > DRAG_THRESHOLD) {
touchLocation = newTouchLocation;
dragging = YES;
}**/
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (dragging) {
[self goHome];
dragging = NO;
} else if ([[touches anyObject] tapCount] == 1) {
if ([delegate respondsToSelector:@selector(thumbImageViewWasTapped:)])
[delegate thumbImageViewWasTapped:self];
}
if ([delegate respondsToSelector:@selector(thumbImageViewStoppedTracking:)])
[delegate thumbImageViewStoppedTracking:self];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[self goHome];
dragging = NO;
if ([delegate respondsToSelector:@selector(thumbImageViewStoppedTracking:)])
[delegate thumbImageViewStoppedTracking:self];
}

- (void)goHome {
float distanceFromHome = distanceBetweenPoints([self frame].origin, [self home].origin); // distance is in pixels
float animationDuration = 0.1 + distanceFromHome * 0.001;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:animationDuration];
[self setFrame:[self home]];
[UIView commitAnimations];
}
- (void)moveByOffset:(CGPoint)offset {
CGRect frame = [self frame];
frame.origin.x += offset.x;
frame.origin.y += offset.y;
[self setFrame:frame];
if ([delegate respondsToSelector:@selector(thumbImageViewMoved:)])
[delegate thumbImageViewMoved:self];
}

@end

float distanceBetweenPoints(CGPoint a, CGPoint b) {
float deltaX = a.x - b.x;
float deltaY = a.y - b.y;
return sqrtf( (deltaX * deltaX) + (deltaY * deltaY) );
}

Then use it
// Left photo
ThumbImageView *thumbViewLeft = [[[ThumbImageView alloc] initWithImageAtUrl:url] autorelease];
thumbViewLeft.userInteractionEnabled = YES;
thumbViewLeft.exclusiveTouch = NO;
thumbViewLeft.layer.borderWidth = 1.0f;
thumbViewLeft.layer.borderColor = [[UIColor lightGrayColor] CGColor];
[thumbViewLeft setDelegate:self];
CGRect frame = [thumbViewLeft frame];
frame.origin.y = IMAGE_PADDING;
frame.origin.x = xPosition;
frame.size = CGSizeMake(imageWidth,IMAGE_HEIGHT);
[thumbViewLeft setFrame:frame];
[thumbViewLeft setHome:frame];
thumbViewLeft.tag = LEFT_IMAGE;
//image =[[UIImage alloc] initWithContentsOfFile:[root stringByAppendingPathComponent:@"cover_preload.jpg"]];
//[thumbViewLeft setImage:[ImagePopulate image:image fitInSize:thumbViewLeft.frame.size]];
//[image release];
[cell.contentView addSubview:thumbViewLeft];
xPosition += (frame.size.width + IMAGE_PADDING);


Happy with programming

1 comment:

Anonymous said...

If you absolutely have right now to hear in relation to Hardiplank, you might remain unsure why
is this it's get a very hot selection for siding content material. They're legal .
be worried this as well greatly the second making cookies animal meat but stews.
By way of the start up phase, the science right behind photovoltaic stove tops described wheat constructed with pressboard as well as a metal
aluminum foil. It wasn't so that the 1990's because Cuisinart branched away and started bragging other products that will execute life in the kitchen easier.

Finished so far, I've found your home worktop works best myself in which wheeled away clay-based. It's Twelve environments
which they can display to opportune cooking food to foodstuff.


Feel free to visit my web-site toaster glass walls (toasterovenpicks.com)