Save and load a UIScrollView position - iphone

Im creating an app that uses a UIScrollView that scrolls through images and a segmented control that loads a new view and allows a new layer of images (bit like Photoshop layering) - For some reason when I click back on the layer, it remembers the position but creates a new layer.... How can I stop this from happening, so once a layer has been selected and an image chosen, when the user returns it goes to the last loaded position?
Also, as a side thing... I cannot use my gesture recognition or UIAlertView when the UIScrollView is loaded? Does anyone know why?
Here is my code.... And thanks in advance:)
- layerControl:(NSInteger)index
{
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
scroll.pagingEnabled = YES;
NSInteger viewCount = 15;
for (int i = 0; i < viewCount; i++) {
CGFloat yOrigin = i * self.view.frame.size.width;
UIImageView *filterViewOverlay = [[UIImageView alloc] initWithFrame:CGRectMake(yOrigin, 0, self.view.frame.size.width, self.view.frame.size.height)];
[filterViewOverlay setImage:[filterManager objectAtIndex:i]];
[scroll addSubview:filterViewOverlay];
[filterViewOverlay release];
}
scroll.contentSize = CGSizeMake(self.view.frame.size.width * viewCount, self.view.frame.size.height);
[self.view addSubview:scroll];
[scroll release];
switch (index)
{
case 0: scroll = self.scroll1;
case 1: scroll = self.scroll2;
case 2: scroll = self.scroll3;
case 4: scroll = self.scroll4;
case 5: scroll = self.scroll5;
}
/* if (scroll == nil)
{
[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
scroll.pagingEnabled = YES;
NSInteger viewCount = 15;
for (int i = 0; i < viewCount; i++) {
CGFloat yOrigin = i * self.view.frame.size.width;
UIImageView *filterViewOverlay = [[UIImageView alloc] initWithFrame:CGRectMake(yOrigin, 0, self.view.frame.size.width, self.view.frame.size.height)];
[filterViewOverlay setImage:[filterManager objectAtIndex:i]];
[scroll addSubview:filterViewOverlay];
//[filterViewOverlay release];
}
scroll.contentSize = CGSizeMake(self.view.frame.size.width * viewCount, self.view.frame.size.height);
[self.view addSubview:scroll];
[scroll autorelease]; */
}
}
//Method to add a filter to the page
- (void)addFilter:(id)sender
{
UISegmentedControl *filterController = (UISegmentedControl *)sender;
[self layerControl:[filterController selectedSegmentIndex]];
}
- (UIImage*)saveImages
{
UIImage *image = [UIImage imageNamed:#"UrbanPhoto##1"];
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

Try saving the value of UIScrollView.contentOffset before the user action, and then restoring that value after the action is completed.

Related

Dragging in UIScrollview increases its subviews count

I am a beginner in iOS. i have created a UIScrollview with 5 images and set its width, height and size change according to orientation. After adding all 5 images the scroll view subview count is 5. But when start dragging the count increases to 7. I don't know where the blank view is added.
CODE
-(void)addImageWithName:(NSString*)imageString atPosition:(int)position {
UIImage *image = [UIImage imageWithContentsOfFile:imageString];
imageView = [[UIImageView alloc] initWithImage:image];
// imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
imageView.frame = CGRectMake(position*scrollview.frame.size.width*2, 0, scrollview.frame.size.width *2,scrollview.frame.size.height );
imageView.tag = 1000 + position +1;
[scrollview addSubview:imageView];
}
-(void)imageLoad:(NSInteger)startImage
{
int Index = -1;
for (UIImageView *subview in scrollview.subviews)
{
[subview removeFromSuperview];
}
for (int i = startImage; i < startImage+5; i++) {
Index++;
fullPath = [dataPath stringByAppendingString:[NSString stringWithFormat:#"/image%d.jpg",i]];
[self addImageWithName:fullPath atPosition:Index];
scrollview.contentSize = CGSizeMake(i*scrollview.frame.size.width, 0);
}
}
When you start scrolling, the scrollbar views are added temporarily as subviews.

How to load remote Images and save to a NSMutableArray

I am trying to Load 5 or 6 remotes images to a scrollview and swipe horizontal. I can get the URLs form my webserver (JSON output) , I'm trying to do this using AFnetworking for performances issues .
so far I can get the URL and load one picture to a UIImageview like this (Using Storyboard )
Jsonobject *items = [posterNSMarray objectAtIndex:0]; //load one url only
NSlog (#"Object url %#", items.pUrl); // picture URL
[self.imageview setImageWithURl :[NSURL URLWithString:items.pUrl] placeholderImage :[UIImage imageNamed:#"placeholder"]];
[EDITED QUESTION]
my question is how do I get all the images and save it to a NSMutableArray
Thanks for your help .
[EDIT]
Based upon your comments below, I might actually choose then a different methodology
Bring in All of your images. At this point you can use either UIImageView or UIButton actually to obtain the tap (from the scrollview) you wish. Assign the UIImages to your choice of UIButton or UIImageView, and the place them on your scrollview as you wish. You will have to dynamically create the actions for each Button or ImageView. Your action creation should then bring up another View to be place atop you scrollview, or another viewcontroller that you animate to, etc... In a View Controller you will have your UIImageView as full screen. At this point you can implement your own UIGestureRecognizers to implement the double taps, etc...
I would use a UIListView. Here is a great link to custom UIListView implementation.
http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html
I would load your images into an NSMutableArray, to be used by the drawing routine of the custom UITableView.
As for swiping, you can capture the swipe events, then you can do with the list items as you please (i.e. delete, edit, etc... from your image array).
Another link:
http://www.icodeblog.com/2009/05/24/custom-uitableviewcell-using-interface-builder/
From your question and comments it seems like you want to load a UIScrollView with multiple images and then swipe through each one. It also sounds like you want to be able to tap one and have it launch a blown up image for the user to view.
I wrote some of these functions for an old project (they are a little rough) but you may be able to use them as they are how I accomplished what I think you were asking.
-(void)setupPictures
{
imageSectionSlider = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, IMAGE_HEIGHT)];
imageSectionSlider.showsVerticalScrollIndicator = NO;
imageSectionSlider.showsHorizontalScrollIndicator = NO;
imageSectionSlider.pagingEnabled = YES;
imageSectionSlider.bounces = NO;
UIView* tilesHolder = [[UIView alloc]initWithFrame:CGRectMake(0, 0, (([[thisStory imageList]count] * (self.frame.size.width))), IMAGE_HEIGHT)];
tilesHolder.userInteractionEnabled = YES;
for (int count = 0; count < [[thisStory imageList]count]; count++)
{
[tilesHolder addSubview:[self createImageTile:[[thisStory imageList]objectAtIndex:count] Count:count Rect:CGRectMake( 320*count , 0, 320, IMAGE_HEIGHT)]];
}
[imageSectionSlider setContentSize:CGSizeMake( tilesHolder.frame.size.width , tilesHolder.frame.size.height)];
[imageSectionSlider addSubview:tilesHolder];
[tilesHolder release];
}
-(UIView*)createImageTile:(ImageItem*)input Count:(int)count Rect:(CGRect)rect
{
UIView* imageTile = [[UIView alloc]initWithFrame:rect];
[imageTile setTag:count];
UIImageView* image = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, imageTile.frame.size.width, imageTile.frame.size.height - 45)];
[image setImage:[input imageData]];
image.contentMode = UIViewContentModeScaleAspectFill;
image.clipsToBounds = YES;
image.userInteractionEnabled = YES;
image.tag = count;
UIGestureRecognizer* featureImageGesRec = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(countTaps:)];
[image addGestureRecognizer:featureImageGesRec];
[featureImageGesRec release];
[imageTile addSubview:image];
[image release];
return [imageTile autorelease];
}
- (void)countTaps:(NSObject*)sender {
tapCount++;
if (tapCount == 1) {
//do something with single tap
}
else if (tapCount == 2)
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self doubleTap:sender];
}
}
-(void)doubleTap:(NSObject*)sender
{
UITapGestureRecognizer* item = (UITapGestureRecognizer*)sender;
tapCount = 0;
//FullSizeImage
ImageItem* selectedItem = [[thisStory imageList]objectAtIndex:item.view.tag];
ExpandedView* pictureView = [[ExpandedView alloc]initWithImage:[selectedItem imageData]];
[thisParent.navigationController pushViewController:pictureView animated:YES];
[pictureView release];
}
Just pass your async loaded image here in this line...
[tilesHolder addSubview:[self createImageTile:/*Image*/ Count:count Rect:CGRectMake( 320*count , 0, 320, IMAGE_HEIGHT)]];
if you use AFNetworking Conect, you use Image Request concept :-
try this code:-
- (void)setupPage
{
scrollPage = 0 ;
scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0.0f,0, 320,367)];
[scrollView setBackgroundColor:[UIColor clearColor]];
[scrollView setDelegate:self];
[self.view addSubview:scrollView];
NSUInteger nimages = 0;
CGFloat cx = 0;
CGFloat cy = 0;
for (; nimages < [stealArr count]; nimages++)
{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f,320.0f,367)];
CGRect rect = imageView.frame;
rect.size.height = 331;
rect.size.width = 320.0f;
rect.origin.y = 0.0f;
rect.origin.x = 0.0f+cx;
imageView.frame = rect;
[imageView setBackgroundColor:[UIColor clearColor]];
imageView.contentMode = UIViewContentModeScaleToFill;
[scrollView addSubview:imageView];
[imageView setImageWithURL:[NSURL URLWithString:#"http://i.imgur.com/r4uwx.jpg"] placeholderImage:[UIImage imageNamed:#"placeholderImage"]];
cx += scrollView.frame.size.width;
cy += scrollView.frame.size.height;
}
pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 331.0f, 320, 36)] ;
[pageControl setCurrentPage:0] ;
[pageControl addTarget: self action: #selector(pageControlClicked:) forControlEvents: UIControlEventValueChanged] ;
[pageControl setDefersCurrentPageDisplay: YES];
[pageControl setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:pageControl];
pageControl.numberOfPages = [stealArr count];
[scrollView setContentSize:CGSizeMake(cx,[scrollView bounds].size.height)];
[scrollView setPagingEnabled:TRUE];
}
when Your are scroll the page
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
// which a scroll event generated from the user hitting the page control triggers updates from
// the delegate method. We use a boolean to disable the delegate logic when the page control is used.
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = scrollView.frame.size.width;
scrollPage = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = scrollPage;
be to unload the views+controllers which are no longer visible
}
for Paging
- (void)pageControlClicked:(id)sender
{
UIPageControl *thePageControl = (UIPageControl *)sender ;
// we need to scroll to the new index
[scrollView setContentOffset: CGPointMake(scrollView.bounds.size.width * thePageControl.currentPage, scrollView.contentOffset.y) animated: YES] ;
}

UIImageView doesn't follow origin.x position

I am trying to add set of imageviews on a UIScrollView. My problem is that the imageviews are overlapping with each other even though I increase the x value. What's also weird is that this problem is only for devices with ios 4.2.1, but works on simulator 4.2 and other device ios.
Here is my code:
- (void)addScrollView {
[self setImages];
scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
scrollView.delegate = self;
[scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setCanCancelContentTouches:NO];
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
[self addSubview:scrollView];
NSUInteger nimages;
CGFloat cx = 0;
for (nimages = 1; nimages < [imagesArray count] ; nimages++) {
UIImage *image = [UIImage imageNamed:[imagesArray objectAtIndex:nimages]];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect rect = imageView.frame;
rect.origin.x = cx;
rect.origin.y = 0;
rect.size.width = 320;
rect.size.height = 480;
imageView.frame = rect;
[scrollView addSubview:imageView];
[imageView release];
cx += rect.size.width;
}
[scrollView setContentSize:CGSizeMake(cx, [scrollView bounds].size.height)];
}
Called from here:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self addScrollView];
UIImage *handImg;
UIImageView *longhand = [[UIImageView alloc] init];
minuteHand = [[UIView alloc] initWithFrame:CGRectMake(0, 55, 320, 480)];
handImg = [UIImage imageNamed:#"clock_long_hand.png"];
longhand.image = handImg;
/************** TRY COMMENT OUT HERE **************/
longhand.frame = CGRectMake(155 - (handImg.size.width / 2), 240 - handImg.size.height, handImg.size.width, handImg.size.height);
[minuteHand addSubview:longhand];
[self addSubview:minuteHand];
/************** END COMMENT OUT HERE **************/
[longhand release];
}
return self;
}
UPDATE:
This code is in a UIView subclass which is why I use [self...] instead of [self.view...].
I tried experimenting and found that when I comment out the indicated parts, the scrollview works fine. But when it is included, this is when the imageviews are overlapped.
I know that the scrollview's content size is correct because its indicator continues to scroll, with just a plain black background.
I am really confused why this works on some ios and not on others. Hope you can help.
This might have something to do with autoresizing mask. The width actual images, I mean .png files is bigger than 320, right?

iphone: how to add text above and below the image in the scrollvew?

I would like to add a page number above the image such as "1 of 50" and description of the image below the image in the scrollview.
I have looked at this LINK but still couldn't figure out how to make it happen.
here is my sample code of the images scrollview. Im trying to find a sample that can add text and scroll with the images
NSUInteger i;
for (i = 1; i <= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"images%d.jpg", i];
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[scrollView1 addSubview:imageView];
[imageView release];
}
UPDATE:
const CGFloat kScrollObjHeight = 320;
const CGFloat kScrollObjWidth = 280.0;
const NSUInteger kNumImages = 50;
- (void)layoutScrollImages
{
UIImageView *view = nil;
NSArray *subviews = [scrollView1 subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curXLoc = 0;
for (view in subviews)
{
if ([view isKindOfClass:[UIImageView class]] && view.tag > 0)
{
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, 0);
view.frame = frame;
curXLoc += (kScrollObjWidth);
}
}
- (void)viewDidLoad {
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
// 1. setup the scrollview for multiple images and add it to the view controller
//
// note: the following can be done in Interface Builder, but we show this in code for clarity
[scrollView1 setBackgroundColor:[UIColor blackColor]];
[scrollView1 setCanCancelContentTouches:NO];
scrollView1.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView1.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
scrollView1.scrollEnabled = YES;
// pagingEnabled property default is NO, if set the scroller will stop or snap at each photo
// if you want free-flowing scroll, don't set this property.
scrollView1.pagingEnabled = YES;
// load all the images from our bundle and add them to the scroll view
NSUInteger i;
for (i = 1; i <= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"creative%d.jpg", i];
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[scrollView1 addSubview:imageView];
[imageView release];
}
[self layoutScrollImages];
I wanted to put this but unable to find the correct position or right offset to display at the top
UILabel * topLabel = [[UILabel alloc] init];
topLabel.text = [NSString stringWithFormat:#"%d of %d", i, kNumImages];
rect.origin.x = offset;
rect.size.height = 30; // however large you need the label to be
topLabel.frame = rect;
offset += 30;
I would think something like this would work:
float offset = 0;
for (NSUInteger i = 1; i <= kNumImages; i++)
{
// load up the image
NSString *imageName = [NSString stringWithFormat:#"images%d.jpg", i];
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// image.size is important here and used to determine placement
CGRect rect = imageView.frame;
rect.size = image.size;
// create top label, just basic will need to configure other settings like font
UILabel * topLabel = [[UILabel alloc] init];
topLabel.text = [NSString stringWithFormat:#"%d of %d", i, kNumImages];
rect.origin.x = offset;
rect.size.height = 30; // however large you need the label to be
topLabel.frame = rect;
offset += 30; // adding the label height
// set image frame since we now know the location below top label
rect.size = image.size;
rect.origin.x += offset;
imageView.frame = rect;
imageView.tag = i;
offset += image.size.height; // adding image height
// add bottom label below image
UILabel * bottomLabel = [[UILabel alloc] init];
bottomLabel.text = imageName; // just a sample description
rect.origin.x += offset;
rect.size.height = 30; // however large you need the label to be
bottomLabel.frame = rect;
offset += 30; // adding the label height
[scrollView1 addSubview:topLabel];
[scrollView1 addSubview:imageView];
[scrollView1 addSubview:bottomLabel];
[imageView release];
[topLabel release];
[bottomLabel release];
offset += 20; // arbitrary spacing between images
}

How can I make a UIScrollView image gallery? (iPhone SDK)

I've been struggling with trying to get my UIImageView to change its image when the UIScrollView is scrolled, kind of like the Photos.app.
Here's my code:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (scrollView.contentOffset.x > 296){
self.currentDBNum++;
self.currentDoorbell = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[[self.doorbells objectAtIndex:currentDBNum] objectForKey:#"Image"] ofType:#"jpg"]];
self.doorbellPic.image = currentDoorbell;
self.currentSoundPath = [[NSBundle mainBundle] pathForResource:[[doorbells objectAtIndex:currentDBNum] objectForKey:#"Sound"] ofType:#"caf"];
}
}
Any hints? Thanks. (The images have a width of 296.)
There are two ways that accomplish your task:
Try to learn Three20 TTPhotoViewController that will do exactly the same as the photo.app that you see in your iphone.
If you want to do it yourself then from my experience, you have to add multiple UIImageView with the correct position (x,y,width,height) to the UIScrollView. Remember to initialize the scroll view with the right content-size so that it's scrollable. An example: image1 is (0,0,320,480), image2 is (320,0,320,480), image3 is (640,0,320,480), etc... then your scroll view content size will be the x's value of the last item + the width of the last item.
Antohny,
I do not have my own source code right with me, but I can suggest you the following link:
http://github.com/andreyvit/ScrollingMadness
I think it will give you an idea so you can implement it without hitting the corners.
you can do it by using following code:
UIImageView *tempImageView ;
int initialXPos = 0;
int initialYPos = 30;
view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 800)];
int arraycounter=0;
for (int i=0; i<numrows; i++)
{
for (int j=0; j<numImagesPerColumn; j++)
{
NSURL *url=[NSURL URLWithString:[aPhoto.childphotos objectAtIndex:arraycounter]];
UIImage *image1;
CGRect image1Frame;
image1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
image1Frame = CGRectMake(initialXPos,initialYPos, 80, 80);
tempImageView = [[UIImageView alloc] initWithFrame:image1Frame];
tempImageView.image=image1;
tempImageView.tag = 0;
initialXPos = initialXPos + 80 + 4;
[view addSubview:tempImageView];
arraycounter=arraycounter+1;
}
initialXPos=0;
initialYPos = initialYPos + 86;
}
scrollView.maximumZoomScale = 4.0;
scrollView.minimumZoomScale = 0.75;
scrollView.clipsToBounds = YES;
scrollView.delegate = self;
[scrollView addSubview:view];
[scrollView addSubview:title];
[scrollView addSubview:des];
[self.view addSubview:scrollView ];
u try this
-(void)getButtonRowSize:(int)_rowsize Count:(int)_count
{
[scrollView setFrame:CGRectMake(0, 0, 320, 480)];
[scrollView setContentSize:CGSizeMake(320,((320-_rowsize*IMAGEGAP)/_rowsize)*(_count/_rowsize +1)+(_count/_rowsize)*IMAGEGAP)];
for(int i=0;i<_count;i++)
{
[scrollView addSubview:[self getButtonRowSize:_rowsize Count:_count currentPos:i]];
}
}
-(UIButton *)getButtonRowSize:(int)_rowsize Count:(int)_count currentPos:(int)_pos
{
UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake((_pos%_rowsize)*((320-(_rowsize+1)*IMAGEGAP)/_rowsize)+(_pos%_rowsize +1)*IMAGEGAP,(_pos/_rowsize)*((320-(_rowsize+1)*IMAGEGAP)/_rowsize)+(_pos/_rowsize +1)*IMAGEGAP,((320-(_rowsize+1)*IMAGEGAP)/_rowsize),((320-(_rowsize+1)*IMAGEGAP)/_rowsize))];
[button setBackgroundImage:[self resizingImagewithimagename:[UIImage imageNamed:#"add image file name"] Length:((320-(_rowsize+1)*IMAGEGAP)/_rowsize)] forState:UIControlStateNormal];
return button;
}