My main motive is to create a screen just like the iPad image gallery. Images are coming from a server and can be in numbers like5 or 50 or 100. i have followed Ray Wenderlich's tutorial and gone through it step by step (http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content) but still facing the issue.
I have a main scroll view (the outer) in which I want to have these images, so that I can zoom in / out each image with scrolling (and paging) feature and also when I double tap the image it should zoom to 2x and and second time double it should return to normal.
For that I have an inner scroll view which will hold an UIImageview for each image. So that each image can zoom in / out. But when I load the image I can only see the first image and other images are not displayed. when I set background color of each scroll view and the image view too I got to know that problem is with them but I can't figure out what it is:
Where is the problem in my code, I have searched a lot on internet but could not figure out, and I have tried many other samples.
Below is my code
.h file
#import <UIKit/UIKit.h>
#interface SliderViewController : UIViewController<UIScrollViewDelegate,MFMailComposeViewControllerDelegate,UIPrintInteractionControllerDelegate,UIAlertViewDelegate,UIPopoverControllerDelegate,ButtonPressedDelegate>
{
NSMutableArray *thumbsArray;
int index;
int count;
UIView *containerView;
bool isEmpty;
NSString *firstName;
NSString *lastName;
NSMutableArray *annotatedThumbsArray;
}
#property(nonatomic,retain) NSMutableArray *thumbsArray;
#property(nonatomic, assign) int index;
#property(nonatomic, assign) int count;
#property(nonatomic,retain) NSString *firstName;
#property(nonatomic,retain) NSString *lastName;
#property(nonatomic,retain) NSMutableArray *annotatedThumbsArray;
#property(nonatomic,retain) UIPopoverController *popover_controller;
#property(nonatomic,retain) IBOutlet UIScrollView *scrollView;
#property(nonatomic,retain) IBOutlet UIPageControl *pageControl;
#end
.m file:
#import "SliderViewController.h"
#import "AppDelegate.h"
#define VIEW_FOR_ZOOM_TAG (10)
#interface SliderViewController ()
{
UITapGestureRecognizer *singleFingerTap;
CGRect rect;
}
#property (nonatomic, strong) NSMutableArray *pageImages;
#property (nonatomic, strong) NSMutableArray *pageViews;
- (void)loadVisiblePages;
- (void)loadPage:(NSInteger)page;
- (void)purgePage:(NSInteger)page;
#end
implementation SliderViewController
#synthesize pageImages,pageControl,libid,libname,thumbsArray,index,count,imageNameLabel,imageNameView,footerView,navBar,firstName,lastName,annotatedThumbsArray;
#synthesize drawingViewController,popover_controller;
#synthesize pageViews = _pageViews;
#synthesize scrollView = _scrollView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
#pragma mark - view cycle
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"THUMBSSSSS%#",thumbsArray);
pageImages = [[NSMutableArray alloc]init];
isEmpty = false;
self.scrollView.backgroundColor = [UIColor greenColor];
NSInteger pageCount = self.thumbsArray.count;
// Set up the page control
self.pageControl.currentPage = index;
self.pageControl.numberOfPages = pageCount;
// Set up the array to hold the views for each page
_pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < pageCount; ++i)
{
[_pageViews addObject:[NSNull null]];
}
self.navBar.topItem.title = [NSString stringWithFormat:#"%# %#",self.firstName,self.lastName];
singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(viewTapped:)];
[self.view addGestureRecognizer:singleFingerTap];
rect = CGRectZero;
}
- (void)centerScrollViewContents
{
CGSize boundsSize = self.scrollView.bounds.size;
CGRect contentsFrame = [self.scrollView viewWithTag:202].frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
} else {
contentsFrame.origin.x = 0.0f;
}
if (contentsFrame.size.height < boundsSize.height)
{
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
}
else
{
contentsFrame.origin.y = 0.0f;
}
[self.scrollView viewWithTag:202].frame = contentsFrame;
}
-(void)setViewContents
{
// Set up the content size of the scroll view
CGSize pagesScrollViewSize = self.scrollView.frame.size;
self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.thumbsArray.count, pagesScrollViewSize.height);
[self.scrollView setContentOffset:CGPointMake(index*pagesScrollViewSize.width, 0.0f)];
self.scrollView.delegate = self;
self.navBar.topItem.title = [NSString stringWithFormat:#"%# %#",firstName,lastName];
// Load the initial set of pages that are on screen
[self loadVisiblePages];
[self centerScrollViewContents];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self setViewContents];
[self performSelectorOnMainThread:#selector(showHeaderFooterViews) withObject:nil waitUntilDone:YES];
}
- (void)loadVisiblePages
{
// First, determine which page is currently visible
CGFloat pageWidth = self.scrollView.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
// Update the page control
self.pageControl.currentPage = page;
// Work out which pages you want to load
isEmpty = false;
NSInteger firstPage = page - 1;
NSInteger lastPage = page + 1;
// Purge anything before the first page
for (NSInteger i=0; i<firstPage; i++) {
[self purgePage:i];
}
for (NSInteger i=firstPage; i<=lastPage; i++) {
[self loadPage:i];
}
for (NSInteger i=lastPage+1; i<self.thumbsArray.count; i++) {
[self purgePage:i];
}
thumbnail *tempThumb = [[thumbnail alloc]init];
tempThumb = [thumbsArray objectAtIndex:page];
NSString *image_name = [[NSString alloc]initWithFormat:#"%#",tempThumb.name];
tempThumb = nil;
[self.imageNameLabel setText:[NSString stringWithFormat:#"%#(%d/%d)",image_name,pageControl.currentPage+1,pageControl.numberOfPages]];
}
-(void)purgePage:(NSInteger)page
{
if(page < 0 || page >= self.thumbsArray.count+self.annotatedThumbsArray.count)
{
// If it's outside the range of what you have to display, then do nothing
return;
}
// Remove a page from the scroll view and reset the container array
UIView *pageView = [_pageViews objectAtIndex:page];
if ((NSNull*)pageView != [NSNull null])
{
[pageView removeFromSuperview];
[_pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
}
}
- (void)loadPage:(NSInteger)page
{
#try
{
if (page < 0 || page >= self.thumbsArray.count)
{
// If it's outside the range of what we have to display, then do nothing
return;
}
// Load an individual page, first checking if you've already loaded it
UIView *pageView = [_pageViews objectAtIndex:page]; // page views holds
if ((NSNull*)pageView == [NSNull null] || isEmpty)
{
CGRect frame = self.scrollView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
frame = CGRectInset(frame, 10.0f, 0.0f);
thumbnail *tempThumb = [[thumbnail alloc]init];
tempThumb = [thumbsArray objectAtIndex:page];
NSString *image_name = [[NSString alloc]initWithFormat:#"%#",tempThumb.name];
tempThumb = nil;
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentDir = [path objectAtIndex:0];
NSString *docsPath = [documentDir stringByAppendingPathComponent:[NSString stringWithFormat:#"downloaded/%#",libid]];
UIImage *fullImage = [[UIImage alloc]init];
NSString *imagePath;
if(page<(thumbsArray.count-annotatedThumbsArray.count))
{
imagePath = [docsPath stringByAppendingPathComponent:image_name];
}
else
{
documentDir = [documentDir stringByAppendingPathComponent:libid];
imagePath = [documentDir stringByAppendingPathComponent:image_name];
}
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:imagePath];
if(fileExists)
{
NSLog(#"file NAMEEEE: - %#",image_name);
fullImage = [UIImage imageWithContentsOfFile:imagePath];
}
else
{
NSLog(#"FILE NOT FOUND");
fullImage = [UIImage imageNamed:#"noimage.jpg"];
isEmpty = true;
}
UIImageView *newPageView = [[UIImageView alloc] initWithImage:fullImage];
[newPageView setUserInteractionEnabled:YES];
newPageView.contentMode = UIViewContentModeScaleAspectFit;
newPageView.frame = frame;
newPageView.backgroundColor = [UIColor blueColor];
newPageView.tag = VIEW_FOR_ZOOM_TAG;
// ******* add each image view into a scroll view so that it can be zoomed and also can be swiped
UIScrollView *pageScrollView = [[UIScrollView alloc] initWithFrame:frame];
pageScrollView.tag = 202;
pageScrollView.minimumZoomScale = 1.0f;
pageScrollView.maximumZoomScale = 2.0f;
pageScrollView.zoomScale = 1.0f;
// pageScrollView.contentSize = newPageView.bounds.size;
pageScrollView.delegate = self;
pageScrollView.showsHorizontalScrollIndicator = NO;
pageScrollView.showsVerticalScrollIndicator = NO;
pageScrollView.backgroundColor = [UIColor yellowColor];
[self.scrollView addSubview:pageScrollView];
[pageScrollView addSubview:newPageView];
[self.scrollView bringSubviewToFront:pageScrollView];
NSLog(#"frame --> %f", frame.origin.x);
NSLog(#"frame --> %f", newPageView.frame.origin.x);
NSLog(#"frame --> %f", pageScrollView.frame.origin.x);
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(viewDoubleTapped:)];
doubleTapRecognizer.numberOfTapsRequired = 2;
doubleTapRecognizer.numberOfTouchesRequired = 1;
[newPageView addGestureRecognizer:doubleTapRecognizer];
}
}
#catch (NSException *exception)
{
NSLog(#"crash in - loadPage = %#", exception);
}
#finally {
// NSLog(#"finally-");
}
}
#pragma mark - double tapped
-(void)viewDoubleTapped:(UITapGestureRecognizer*)recognizer
{
//TODO: code for 2x zooming in / out
}
#pragma mrak - view tapped
-(void) viewTapped:(UITapGestureRecognizer*)recognizer
{
if([self.footerView isHidden])
{
[self performSelectorOnMainThread:#selector(showHeaderFooterViews) withObject:nil waitUntilDone:YES];
}
}
- (void)showHeaderFooterViews
{
[self.imageNameView setHidden:NO];
[self.footerView setHidden:NO];
[self performSelector:#selector(hideHeaderFooterViews) withObject:nil afterDelay:5.0];
}
- (void)hideHeaderFooterViews
{
NSLog(#"hide header footer called ");
[self.imageNameView setHidden:YES];
[self.footerView setHidden:YES];
}
#pragma mark - back button (cross button ) pressed
- (IBAction)backButtonPressed:(id)sender
{
#try
{
AppDelegate* myAppDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
int l = [[[myAppDelegate window].rootViewController childViewControllers] count];// to access the previous controller
FolderViewController *parentVC = (FolderViewController *)((UITabBarController *)[[[myAppDelegate window].rootViewController childViewControllers] objectAtIndex:l-2]); // accessing FolderviewC
[parentVC loadThumbnails];
[self.view removeFromSuperview];
[self removeFromParentViewController];
}
#catch (NSException *exception) {
NSLog(#"crash in SliderVC: backButtonPressed - %#", exception);
}
#finally {
}
}
#pragma mark - scroll view delegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// Load the pages that are now on screen
[self loadVisiblePages];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
if(scrollView.tag == 202)
return [scrollView viewWithTag:VIEW_FOR_ZOOM_TAG];
return nil;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
NSLog(#"view zoomed");
[self centerScrollViewContents ];
}
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
{
NSLog(#"Beginning zooming");
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale{
NSLog(#"Zooming Did End");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)swipeRight:(id)sender
{
if (!((self.scrollView.contentOffset.x+self.scrollView.frame.size.width) >= self.scrollView.contentSize.width))
{
[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x+self.scrollView.frame.size.width, self.scrollView.contentOffset.y)];
[self loadVisiblePages];
}
}
- (IBAction)swipeLeft:(id)sender
{
if (!((self.scrollView.contentOffset.x-self.scrollView.frame.size.width) < 0))
{
[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x-self.scrollView.frame.size.width, self.scrollView.contentOffset.y)];
[self loadVisiblePages];
}
}
NOTE: I have saved my images which I am getting from server in Documents directory and accessing back them from my loadPage: method (is this the right place to access these images?)
Related
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am using a view controller that consists of a horizontal scroll view and page controller to display a number of images in a carrousel fashion. The controller is passed an array of images and displays them starting with the first image. I obtained the code snippet from a third party tutorial and have spent the last day trying to understand it and change its functionality. I have been trying to make the carrousel start at the middle of the array of images, (i.e. if there are nine images start at image five and allow for scrolling both ways) but have had no luck in modifying the existing code. I have played around with the loadPage and loadVisiblePages methods but have had little luck. Here are the .m and .h files.
PeekPagedScrollViewController.m
#import "PeekPagedScrollViewController.h"
#interface PeekPagedScrollViewController ()
#property (nonatomic, strong) NSMutableArray *pageViews;
- (void)loadVisiblePages;
- (void)loadPage:(NSInteger)page;
- (void)purgePage:(NSInteger)page;
#end
#implementation PeekPagedScrollViewController
#synthesize scrollView = _scrollView;
#synthesize pageControl = _pageControl;
#synthesize gallaryType = _gallaryType;
#synthesize pageImages = _pageImages;
#synthesize pageViews = _pageViews;
#synthesize startPoint = _startPoint;
#pragma mark -
- (void)loadVisiblePages
{
// First, determine which page is currently visible
CGFloat pageWidth = self.scrollView.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
// Work out which pages we want to load
NSInteger firstPage = page - 1;
NSInteger lastPage = page + 1;
// Purge anything before the first page
for (NSInteger i=0; i<firstPage; i++) {
[self purgePage:i];
}
for (NSInteger i=firstPage; i<=lastPage; i++) {
[self loadPage:i];
}
for (NSInteger i=lastPage+1; i<self.pageImages.count; i++) {
[self purgePage:i];
}
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)loadPage:(NSInteger)page
{
if (page < 0 || page >= self.pageImages.count)
{
// If it's outside the range of what we have to display, then do nothing
return;
}
// Load an individual page, first seeing if we've already loaded it
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView == [NSNull null])
{
CGRect frame = self.scrollView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
frame = CGRectInset(frame, 10.0f, 0.0f);
UIImageView *newPageView = [[UIImageView alloc] initWithImage:[self.pageImages objectAtIndex:page]];
newPageView.contentMode = UIViewContentModeScaleAspectFit;
newPageView.frame = frame;
[self addTapHandler:newPageView actionSelector:#selector(handleSingleTap:)];
[self.scrollView addSubview:newPageView];
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
}
}
- (void)purgePage:(NSInteger)page
{
if (page < 0 || page >= self.pageImages.count)
{
// If it's outside the range of what we have to display, then do nothing
return;
}
// Remove a page from the scroll view and reset the container array
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView != [NSNull null])
{
[pageView removeFromSuperview];
[self.pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
}
}
- (void)addTapHandler:(UIView *)pageView actionSelector:(SEL)actionSelector
{
[pageView setUserInteractionEnabled:YES];
UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:actionSelector];
[pageView addGestureRecognizer:tapper];
}
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
if (_gallaryType == 0)
{
NSString *messageString = #"Use as profile image?";
UIAlertView *imageAlertView = [[UIAlertView alloc] initWithTitle:#"Select Image" message:messageString delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil];
[imageAlertView show];
}
else if (_gallaryType == 1)
{
NSString *messageString = #"Use as cover photo?";
UIAlertView *imageAlertView = [[UIAlertView alloc] initWithTitle:#"Select Image" message:messageString delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil];
[imageAlertView show];
}
}
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1)
{
// add yes button text here
}
}
#pragma mark -
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setTranslatesAutoresizingMaskIntoConstraints:YES];
self.title = #"Paged";
NSInteger pageCount = self.pageImages.count;
// Set up the array to hold the views for each page
self.pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < pageCount; ++i)
{
[self.pageViews addObject:[NSNull null]];
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Set up the content size of the scroll view
CGSize pagesScrollViewSize = self.scrollView.frame.size;
self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.pageImages.count, pagesScrollViewSize.height);
// Load the initial set of pages that are on screen
[self loadVisiblePages];
}
- (IBAction)back:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.scrollView = nil;
self.pageControl = nil;
self.pageImages = nil;
self.pageViews = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// Load the pages which are now on screen
[self loadVisiblePages];
}
#end
PeekPagedScrollViewController.h
#import <UIKit/UIKit.h>
#interface PeekPagedScrollViewController : UIViewController <UIScrollViewDelegate, UIAlertViewDelegate>
#property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
#property (nonatomic, strong) IBOutlet UIPageControl *pageControl;
#property (nonatomic, strong) NSArray *pageImages;
#property (nonatomic) NSInteger *gallaryType;
#property (nonatomic) NSInteger *startPoint;
- (IBAction)back:(id)sender;
#end
Thanks
just take scroll view
set its content size/// that is how much it is going to scroll
scrollView.contentSize = CGSizeMake(scrollView.bounds.size.width*imageArray.count,scrollView.frame.size.height);
// and then set the starting point
scrollView.contentOffset = CGPointMake(currentpage * scrollView.bounds.size.width, 0);
I think you only need to scroll to a particular page. The rest of the thing will automatically happens. Try like this
CGRect frame = self.scrollView.frame;
frame.origin.x = (frame.size.width * page);
frame.origin.y = 0;
[self.scrollView scrollRectToVisible:frame animated:YES];
Here page is the page number(eg 5)
There are a few threads out there related to this issues, but could not find a solid solution. Any help would be appreciated. This code works great if you give it one image. Zooms in perfect. You give it two images it scrolls threws the images fine but when you go to zoom in it always zooms into the first image? Not sure why the viewForZoomingInScrollView method doesn't figure out which view you are on. Code posted below
PagedScrollViewController.h
#import <UIKit/UIKit.h>
#interface PagedScrollViewController : UIViewController <UIScrollViewDelegate>
#property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
#property (nonatomic, strong) IBOutlet UIPageControl *pageControl;
#property (nonatomic, strong) IBOutlet UIButton *cancelButtonClicked;
#property (nonatomic, strong) IBOutlet UILabel *headerTitle;
#property (nonatomic, strong) IBOutlet NSString *headerTitleS;
#property (nonatomic, strong) IBOutlet NSMutableArray *pageImages;
#property (nonatomic, strong) IBOutlet UITextView *caption;
#property (weak, nonatomic) IBOutlet UINavigationBar *navigationBar;
#property (nonatomic, strong) NSMutableArray *captionArray;
-(IBAction)cancelButtonClicked:(id)sender;
#end
PagedScrollViewController.m
#interface PagedScrollViewController ()
#property (nonatomic, strong) NSMutableArray *pageViews;
- (void)loadVisiblePages;
- (void)loadPage:(NSInteger)page;
- (void)purgePage:(NSInteger)page;
#end
#implementation PagedScrollViewController
#synthesize scrollView = _scrollView;
#synthesize pageControl = _pageControl;
#synthesize pageImages = _pageImages;
#synthesize pageViews = _pageViews;
#synthesize cancelButtonClicked = _cancelButtonClicked;
#synthesize headerTitle = _headerTitle;
#synthesize headerTitleS = _headerTitleS;
#synthesize caption = _caption;
#synthesize captionArray = _captionArray;
- (void)loadVisiblePages {
// First, determine which page is currently visible
CGFloat pageWidth = self.scrollView.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth)
/ (pageWidth * 2.0f));
// Update the page control
self.pageControl.currentPage = page;
NSObject *captionObject = [self.captionArray objectAtIndex:page];
NSString *captionString = [NSString stringWithFormat:#"%#", [captionObject
valueForKey:#"caption"]];
self.caption.text = captionString;
// Work out which pages we want to load
NSInteger firstPage = page - 1;
NSInteger lastPage = page + 1;
// Purge anything before the first page
for (NSInteger i=0; i<firstPage; i++) {
[self purgePage:i];
}
for (NSInteger i=firstPage; i<=lastPage; i++) {
[self loadPage:i];
}
for (NSInteger i=lastPage+1; i<self.pageImages.count; i++) {
[self purgePage:i];
}
}
- (void)loadPage:(NSInteger)page {
if (page < 0 || page >= self.pageImages.count) {
// If it's outside the range of what we have to display, then do nothing
return;
}
// Load an individual page, first seeing if we've already loaded it
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView == [NSNull null]) {
CGRect frame = self.scrollView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
UIImageView *newPageView = [[UIImageView alloc] initWithImage:[self.pageImages
objectAtIndex:page]];
newPageView.contentMode = UIViewContentModeScaleAspectFit;
newPageView.frame = CGRectMake((page*320), 0, 310, 320);
self.scrollView.maximumZoomScale = 1.3;
self.scrollView.contentSize = CGSizeMake(320*[self.pageImages count],389);
self.scrollView.frame = CGRectMake(320*(self.pageControl.currentPage), 44, 310,
370);
[self.scrollView addSubview:newPageView];
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
}
}
- (void)purgePage:(NSInteger)page {
if (page < 0 || page >= self.pageImages.count) {
// If it's outside the range of what we have to display, then do nothing
return;
}
// Remove a page from the scroll view and reset the container array
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView != [NSNull null]) {
[pageView removeFromSuperview];
[self.pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
}
}
-(UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView {
self.scrollView.contentSize = CGSizeMake(320*[self.pageImages count],389);
return [self.scrollView.subviews objectAtIndex:self.pageControl.currentPage];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView.delegate = self;
self.headerTitle.text = self.headerTitleS;
// Set up the image we want to scroll & zoom and add it to the scroll view
NSInteger pageCount = self.pageImages.count;
// Set up the page control
self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = pageCount;
// Set up the array to hold the views for each page
self.pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < pageCount; ++i) {
[self.pageViews addObject:[NSNull null]];
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Load the initial set of pages that are on screen
[self loadVisiblePages];
}
- (void)viewDidUnload {
[super viewDidUnload];
self.scrollView = nil;
self.pageControl = nil;
self.pageImages = nil;
self.pageViews = nil;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self loadVisiblePages];
}
-(IBAction)cancelButtonClicked:(id)sender{
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
This is what I found to work. Supports multiple images with paging and zooming. Enjoy!
#define VIEW_FOR_ZOOM_TAG (1)
#implementation SVViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIScrollView *mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
mainScrollView.pagingEnabled = YES;
mainScrollView.showsHorizontalScrollIndicator = NO;
mainScrollView.showsVerticalScrollIndicator = NO;
CGRect innerScrollFrame = mainScrollView.bounds;
for (NSInteger i = 0; i < 3; i++) {
UIImageView *imageForZooming = [[UIImageView alloc] initWithImage:[UIImage imageNamed:
[NSString stringWithFormat:#"page%d", i + 1]]];
imageForZooming.tag = VIEW_FOR_ZOOM_TAG;
UIScrollView *pageScrollView = [[UIScrollView alloc] initWithFrame:innerScrollFrame];
pageScrollView.minimumZoomScale = 1.0f;
pageScrollView.maximumZoomScale = 2.0f;
pageScrollView.zoomScale = 1.0f;
pageScrollView.contentSize = imageForZooming.bounds.size;
pageScrollView.delegate = self;
pageScrollView.showsHorizontalScrollIndicator = NO;
pageScrollView.showsVerticalScrollIndicator = NO;
[pageScrollView addSubview:imageForZooming];
[mainScrollView addSubview:pageScrollView];
if (i < 2) {
innerScrollFrame.origin.x += innerScrollFrame.size.width;
}
}
mainScrollView.contentSize = CGSizeMake(innerScrollFrame.origin.x +
innerScrollFrame.size.width, mainScrollView.bounds.size.height);
[self.view addSubview:mainScrollView];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return [scrollView viewWithTag:VIEW_FOR_ZOOM_TAG];
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate {
return NO;
}
#end
I am trying to make practice app where i can scroll images with page control. I am able to scroll images and able to include the page control. But the problem i face is i am not able to interlink the two. Meaning to say when I scroll the images, the page control is not affected and when i change the page control, the scrolling of the images is unaffected.
I am referring to this website: http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIScrollViewDelegate>
#property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
#property (nonatomic, strong) IBOutlet UIPageControl *pageControl;
#property (nonatomic, strong) NSArray *pageImages;
#property (nonatomic, strong) NSMutableArray *pageViews;
- (void)loadVisiblePages;
- (void)loadPage:(NSInteger)page;
- (void)purgePage:(NSInteger)page;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize scrollView = _scrollView;
#synthesize pageControl = _pageControl;
#synthesize pageImages = _pageImages;
#synthesize pageViews = _pageViews;
- (void)loadPage:(NSInteger)page {
if (page < 0 || page >= self.pageImages.count) {
// If it's outside the range of what you have to display, then do nothing
return;
}
// 1
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView == [NSNull null]) {
// 2
CGRect frame = self.scrollView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
// 3
UIImageView *newPageView = [[UIImageView alloc] initWithImage:[self.pageImages objectAtIndex:page]];
newPageView.contentMode = UIViewContentModeScaleAspectFit;
newPageView.frame = frame;
[self.scrollView addSubview:newPageView];
// 4
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
}
}
- (void)loadVisiblePages {
// First, determine which page is currently visible
CGFloat pageWidth = self.scrollView.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
// Update the page control
self.pageControl.currentPage = page;
// Work out which pages you want to load
NSInteger firstPage = page - 1;
NSInteger lastPage = page + 1;
// Purge anything before the first page
for (NSInteger i=0; i<firstPage; i++) {
[self purgePage:i];
}
// Load pages in our range
for (NSInteger i=firstPage; i<=lastPage; i++) {
[self loadPage:i];
}
// Purge anything after the last page
for (NSInteger i=lastPage+1; i<self.pageImages.count; i++) {
[self purgePage:i];
}
}
- (void)purgePage:(NSInteger)page {
if (page < 0 || page >= self.pageImages.count) {
// If it's outside the range of what you have to display, then do nothing
return;
}
// Remove a page from the scroll view and reset the container array
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView != [NSNull null]) {
[pageView removeFromSuperview];
[self.pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// Load the pages that are now on screen
[self loadVisiblePages];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 1
self.pageImages = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"1.jpeg"],
[UIImage imageNamed:#"2.jpeg"],
[UIImage imageNamed:#"3.jpeg"],
nil];
NSInteger pageCount = self.pageImages.count;
// 2
self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = pageCount;
// 3
self.pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < pageCount; ++i) {
[self.pageViews addObject:[NSNull null]];
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// 4
CGSize pagesScrollViewSize = self.scrollView.frame.size;
self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.pageImages.count, pagesScrollViewSize.height);
// 5
[self loadVisiblePages];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The third image is not appearing and still not able to link the pagecontrol and the scrolling of the images. Need some guidance on this...
In loadVisiblePages , change this line:
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
with this line:
NSInteger page = self.scrollView.contentOffset.x / self.scrollView.frame.size.width;
Hope this helps.
Cheers!
EDIT: I think you haven't set [scrollView setDelegate:self]; in viewDidLoad
I need some help to implement the function that change the page on pagecontroller. I have a UIPageController , the number of pages is variable.
Here is my code :
.h**
#property (nonatomic, retain) IBOutlet UIScrollView *vosvehiculeScrollView;
#property (nonatomic, retain) IBOutlet UIPageControl *pageControlVehiculePossedee;
- (IBAction) changePage:(id) sender;
- (void) loadScrollViewWithPage: (int) page;
.m*
- (void)viewDidLoad
{
[super viewDidLoad];
[self getVehicules];
vosvehiculeScrollView.pagingEnabled = YES;
vosvehiculeScrollView.showsHorizontalScrollIndicator = NO;
vosvehiculeScrollView.showsVerticalScrollIndicator = NO;
vosvehiculeScrollView.scrollsToTop = NO;
pageControlVehiculePossedee.numberOfPages=[vehiculesPossede count];
pageControlVehiculePossedee.currentPage=0;
[self loadScrollViewWithPage:0];
votreVehiculeLabel.text=#"Votre véhicule";
vehiculesPossedesArray = [[NSMutableArray alloc] initWithObjects:#"Annee modele", #"Transmission",#"Carburant", nil];
}
- (void) loadScrollViewWithPage: (int) page {
if (page < 0) return;
if (page >= [vehiculesPossede count]) return;
tableViewVehiculesPossedes=[[UITableView alloc] initWithFrame:CGRectMake(3, 80, 315, 171) style:UITableViewStyleGrouped];
tableViewVehiculesPossedes.bounces=NO;
tableViewVehiculesPossedes.backgroundColor=[UIColor clearColor];
[tableViewVehiculesPossedes setDelegate:self];
[tableViewVehiculesPossedes setDataSource:self];
[self.vosvehiculeScrollView addSubview:tableViewVehiculesPossedes];
nameVehiculeLabel.text=[[vehiculesPossede objectAtIndex:page] valueForKey:#"modele"];
self.transmissionString=[[vehiculesPossede objectAtIndex:page]valueForKey:#"transmision"];
self.carburantString=[[vehiculesPossede objectAtIndex:page] valueForKey:#"carburant"];
self.anneeModelString=[[vehiculesPossede objectAtIndex:page] valueForKey:#"modele_annee"];
self.anneeString=[[vehiculesPossede objectAtIndex:page]valueForKey:#"annee"];
if(page==0){
NSLog(#"0");
}
else NSLog(#"1");
}
- (IBAction) changePage:(id) sender
{
NSLog(#"page changed");
/* CGRect frame;
frame.origin.x = self.vosvehiculeScrollView.frame.size.width * self.pageControlVehiculePossedee.currentPage;
frame.origin.y = 0;
frame.size = self.vosvehiculeScrollView.frame.size;
NSLog(#"current page %d",pageControlVehiculePossedee.currentPage);
[self.vosvehiculeScrollView scrollRectToVisible:frame animated:YES];*/
[self loadScrollViewWithPage:1];
pageControlUsed = YES;
}
and I get Program received signal: “EXC_BAD_ACCESS”. How should I implement the changePage method to make it ok? Please help..
Thanks in advance...
I did as follow
- (IBAction)actionBtnNext:(id)sender
{
if (pageNumber == kNumberOfPages-2) {
pageNumber = kNumberOfPages-2;
}
else {
pageNumber++;
}
CGFloat pageWidth = scrollView.frame.size.width*pageNumber;
[scrollView setContentOffset:CGPointMake(pageWidth,0.0) animated:YES];
}
Let me know if you do have any questions.
Regards
I have looked at a few guides for CAKeyFrameAnimation and I am failing to see how to trigger them. The only thing I can think of is that I have to use it as a return, but that doesn't make much sense to me.
-H File-
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface ImageSequenceViewController : UIViewController
<UIGestureRecognizerDelegate>{
UISwipeGestureRecognizer *swipeLeftRecognizer;
NSMutableArray *myImages;
IBOutlet UIImageView *imageView;
IBOutlet UIImageView *bView;
IBOutlet UISegmentedControl *segmentedControl;
}
#property (nonatomic, retain) UISwipeGestureRecognizer *swipeLeftRecognizer;
#property (nonatomic, retain) UIImageView *imageView;
#property (nonatomic, retain) IBOutlet UISegmentedControl *segmentedControl;
-(IBAction)takeLeftSwipeRecognitionEnabledFrom:(UISegmentedControl *)aSegmentedControl;
-(IBAction)ButtonPressed1: (id)sender;
#end
-M File-
#import "ImageSequenceViewController.h"
#implementation ImageSequenceViewController
#synthesize swipeLeftRecognizer;
#synthesize imageView;
#synthesize segmentedControl;
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
//CUSTOM CODE
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
-(void)loadLeft {
//aView = [[UIImageView alloc] initWithFrame:self.view.frame];
CALayer *layer = [CALayer layer];
[layer setFrame:CGRectMake(0.0,
0.0,
[[self view] frame].size.height,
[[self view] frame].size.width)];
myImages = [[NSMutableArray alloc] init];
for(NSUInteger count=0; count<100; count++){
NSString *fileName;
if (count < 10)
{
fileName = [NSString stringWithFormat:#"trailerRotation_000%d", count];
}
else if (10 <= count < 100)
{
fileName = [NSString stringWithFormat:#"trailerRotation_00%d", count];
}
else
{
fileName = [NSString stringWithFormat:#"trailerRotation_0%d", count];
}
NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:#"jpg"];
//UIImage *image = [[UIImage alloc] initWithContentsOfFile:fileName];
//[myImages addObject:image];
[myImages addObject:[UIImage imageWithContentsOfFile:path]];
}
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:#"Contents"];
[anim setDuration:0.10];
[anim setCalculationMode:kCAAnimationDiscrete];
[anim setRepeatCount:1];
[anim setValues:myImages];
[self.view.layer addSublayer:layer];
[layer addAnimation:anim forKey:#"images"];
//aView.animationImages = myImages;
//aView.animationDuration = 10.00;
//aView.animationRepeatCount = 1;
}
-(void)loadRight {
bView = [[UIImageView alloc] initWithFrame:self.view.frame];
myImages = [[NSMutableArray alloc] init];
for(NSUInteger count=99; count>0; count--){
NSString *countString;
if (count < 10)
{
countString = #"000";
countString = [countString stringByAppendingFormat:#"%d", count];
}
else if (10 <= count < 100)
{
countString = #"00";
countString = [countString stringByAppendingFormat:#"%d", count];
}
else if (100 <= count < 1000)
{
countString = #"00";
countString = [countString stringByAppendingFormat:#"%d", count];
}
NSLog(#"%d", count);
NSString *fileName = #"trailerRotation_";
fileName = [fileName stringByAppendingFormat:countString];
fileName = [fileName stringByAppendingFormat:#".jpg"];
[myImages addObject:[UIImage imageNamed:fileName]];
}
bView.animationImages = myImages;
bView.animationDuration = 10.00;
bView.animationRepeatCount = 1;
}
- (void)viewDidLoad {
[super viewDidLoad];
imageView = [[UIImageView alloc] initWithFrame:self.view.frame];
[imageView setImage:[UIImage imageNamed:#"trailerRotation_0000.jpg"]];
//[self.view addSubview:imageView];
[self loadLeft];
[self loadRight];
UIGestureRecognizer *recognizer;
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
[self.view addGestureRecognizer:recognizer];
[recognizer release];
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
self.swipeLeftRecognizer = (UISwipeGestureRecognizer *) recognizer;
swipeLeftRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
if ([segmentedControl selectedSegmentIndex] == 0) {
[self.view addGestureRecognizer:swipeLeftRecognizer];
}
self.swipeLeftRecognizer = (UISwipeGestureRecognizer *) recognizer;
[recognizer release];
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.segmentedControl = nil;
self.swipeLeftRecognizer = nil;
self.imageView = nil;
}
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void)viewDidAppear:(BOOL)animated {
[self becomeFirstResponder];
}
-(void)startItLeft {
NSLog(#"Left");
//[aView startAnimating];
//[self.view addSubview:aView];
//[aView release];
[bView release];
}
-(void)startItRight {
NSLog(#"Right");
[bView startAnimating];
[self.view addSubview:bView];
//[aView release];
[bView release];
}
//- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {
//}
//- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
//}
//- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event {
//}
-(IBAction)ButtonPressed1:(id)sender
{
NSLog(#"Button");
//[aView stopAnimating];
[bView stopAnimating];
//[self loadLeft];
[self loadRight];
}
-(IBAction)takeLeftSwipeRecognitionEnabledFrom:(UISegmentedControl *) aSegmentControl {
if ([aSegmentControl selectedSegmentIndex] == 0) {
[self.view addGestureRecognizer:swipeLeftRecognizer];
}
else {
[self.view removeGestureRecognizer:swipeLeftRecognizer];
}
}
-(void)handleSwipeFrom:(UISwipeGestureRecognizer *) recognizer {
//CGPoint location = [recognizer locationInView:self.view];
//[self showImageWithText:#"swipe" atPoint:location];
if (recognizer.direction == UISwipeGestureRecognizerDirectionLeft) {
//[self startItLeft];
}
else {
[self startItRight];
}
}
//CUSTOM CODE
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)dealloc {
[super dealloc];
}
#end
I'm rather new to iOS development so any advice is helpful.
Thanks.
Try:
[myImages addObject:(id)[UIImage imageWithContentsOfFile:path].CGImage];
Since the CAKeyFrameAnimation expects CGImageRef objects.
It looks like you're trying to load up 100 images and cycle them all within the space of 0.1 second. Not only is that pretty ridiculous (that's 1000fps right there, and CoreAnimation is capped at 60fps), but it's likely to take longer than 0.1 seconds for CoreAnimation to copy all the images before it even starts, which means that it will have finished before it started (and therefore no animation will occur).
I'll admit it was a PEBKAC error.
Thanks all for your help.