ScrollView Swipe Right not working XCode - iphone

I've a scrollView in which subviews are added and these subviews can be swiped top, right and left. But for some reason the swipe right does not seem to be working at all. I'm completely new to Objective-C, due to which i've been struggling real hard to make it work. I've a main view controller implementation with following code:
my MainViewController.m is
- (void)viewDidLoad {
[super viewDidLoad];
_headerViewController = [self.storyboard instantiateViewControllerWithIdentifier:kHeaderId];
_headerViewController.delegate = self;
[scrollView addSubview:_headerViewController.view];
_actionsListViewController = [self.storyboard instantiateViewControllerWithIdentifier:kActionsListId];
_actionsListViewController.delegate = self;
[scrollView insertSubview:_actionsListViewController.view
belowSubview:_headerViewController.view];
_agendasListViewController = [self.storyboard instantiateViewControllerWithIdentifier:KAgendasListId];
_agendasListViewController.delegate = self;
[scrollView insertSubview:_agendasListViewController.view
belowSubview:_headerViewController.view];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self positionSearchField:YES];
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * 2,
scrollView.frame.size.height * 2);
_headerViewController.view.frame = CGRectMake(0, 0,
scrollView.frame.size.width,
scrollView.frame.size.height);
//action view will be displayed when swiped left
_actionsListViewController.view.frame = CGRectMake(scrollView.frame.size.width, 0,
scrollView.frame.size.width,
scrollView.frame.size.height);
//agenda view should have been displayed when swiped right
_agendasListViewController.view.frame = CGRectMake(-scrollView.frame.size.width, 0,
scrollView.frame.size.width,
scrollView.frame.size.height);
_scrollViewBounds = scrollView.bounds;
}
and the viewShouldScroll function
- (void)viewShouldScroll:(UISwipeGestureRecognizerDirection)direction {
CGRect frame = CGRectMake(scrollView.contentOffset.x,
scrollView.contentOffset.y,
scrollView.frame.size.width,
scrollView.frame.size.height);
UIViewController *currentController = [self visibleViewController];
switch (direction) {
case UISwipeGestureRecognizerDirectionUp:
frame.origin.y += scrollView.frame.size.height;
break;
case UISwipeGestureRecognizerDirectionLeft:
//works fine and displays action view
frame.origin.x += scrollView.frame.size.width;
break;
case UISwipeGestureRecognizerDirectionDown:
frame.origin.y -= scrollView.frame.size.height;
break;
case UISwipeGestureRecognizerDirectionRight:
if( currentController == _headerViewController ) {
//does not work for agenda when swiped right
NSLog(#"x position is %f#", frame.origin.x);
frame.origin.x = -320; //hardcoded to check if this works, but doesnot
NSLog(#"width is %f#", scrollView.frame.size.width); //gives -320
}
else {
//works fine when swiped from left to right to show main view
frame.origin.x -= scrollView.frame.size.width; //0
}
break;
default:
break;
}
[scrollView scrollRectToVisible:frame animated:YES];
}
Gesture recognizers have been added from storyboard for LEFT, RIGHT and TOP. As per the code, i've added agenda view with position of x as -320 in CGRectMake and on swipe right, i'm trying to make it visible by changing the x point of frame.origin but it does not seem to work. Any help would be appreciated.

I managed to do it this way::
...
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * 3,
scrollView.frame.size.height * 2);
...
I was using the width of scrollView as scrollView.frame.size.width * 2, which made the total width of scroll view double of scrollView.frame.size.width, but since i had 3 subviews in the main scrollView, i needed to do create scrollView with width 3 times the width of scrollView frame as scrollView.frame.size.width * 3

Related

Infinite scrolling image; scrolls left to right in portrait mode

I am trying to make an image scroll horizontally to the right while the device is in portrait mode. The image needs to scroll automatically until a timer ends, and needs to scroll seamlessly. How can I achieve this?
Try this,hope this will help.
// Create Image's array
NSMutableArray * imagesArray = [[NSMutableArray alloc]init];
for (int imageCount = 0; imageCount < YOURCOUNT;imageCount++)
{
[imagesArray addObject:[UIImage imageNamed:#"localImagePath%d.png",imageCount]];
}
// Create ScrollView
UIScrollView * scrollview = [[UIScrollView alloc]initWithFrame:CGRectMake(0.0,0.0,320.0,480.0)];
scrollview.contentSize = CGSizeMake(scrollview.frame.size.width * YOURCOUNT,scrollview.frame.size.height);
// Add those image's to the scrollview
CGFloat xPos = 0.0;
for (UIImage * image in imagesArray) {
#autoreleasepool {
UIImageView * imageview = [[UIImageView alloc]initWithImage:image];
imageview.frame = CGRectMake(xPos, 0.0,scrollview.frame.size.width,scrollview.frame.size.height);
[scrollview addSubview:imageview];
xPos += scrollview.frame.size.width;
}
}
[self.view addSubview:scrollview];
// Animate to the Right
[UIView animateWithDuration:10.0 delay:0 options:UIViewAnimationTransitionNone
animations:^{
[scrollview setContentOffset:CGPointMake(scrollview.contentSize.width - scrollview.frame.size.width,0.0) animated:NO];
}
completion:^(BOOL finished) {
NSLog(#"Finished");
}];

dynamic UIScrollView with paging and data from NSMutableArray

I saw alot of people asking about it, I read everything but still could not figure how to do it. I have a UIScrollView with paging enabled, also I have a NSMutableArray with strings.
what I want to do is that the UIScrollView will show to UITextView with the string and when I change to the next page, it will show the next item on the NSMutableArray.
for some reason I can't get it to work.
- (void)setupPage
{
pagingView.delegate = self;
[self.pagingView setBackgroundColor:[UIColor blackColor]];
[pagingView setCanCancelContentTouches:NO];
pagingView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
pagingView.clipsToBounds = YES;
pagingView.scrollEnabled = YES;
pagingView.pagingEnabled = YES;
pagingView.backgroundColor = [UIColor clearColor];
[pagingView setShowsHorizontalScrollIndicator:NO];
[pagingView setShowsVerticalScrollIndicator:NO];
for (int i=0;i<[arrCat count];i++)
{
UITextView * txtJoke = [[UITextView alloc]initWithFrame:CGRectMake(10, 10, 100, 100)];
[pagingView addSubview:txtJoke];
txtJoke.text = [arrCat objectAtIndex:i];
txtJoke.textAlignment = UITextAlignmentRight;
}
[pagingView setContentSize:CGSizeMake(960, [pagingView bounds].size.height)];
}
- (void)scrollViewDidScroll:(UIScrollView *)_scrollView
{
if (pageControlIsChangingPage) {
return;
}
/*
* We switch page at 50% across
*/
CGFloat pageWidth = _scrollView.frame.size.width;
int page = floor((_scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
//pageControl.currentPage = page;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)_scrollView
{
pageControlIsChangingPage = NO;
}
- (IBAction)changePage:(id)sender :(int)current
{
/*
* Change the scroll view
*/
CGRect frame = pagingView.frame;
frame.origin.x = frame.size.width * 1;
frame.origin.y = 0;
[pagingView scrollRectToVisible:frame animated:YES];
/*
* When the animated scrolling finishings, scrollViewDidEndDecelerating will turn this off
*/
pageControlIsChangingPage = YES;
}
This code is a combination of something from another app that i'm trying to fit into this, but without any success.
Please help. Thanks alot.
For one thing, all of your UITextView's have the same frame coordinates, so they will be on top of each other. Assuming you're scrolling horizontally, you need to offset the UITextView's x origin by the page width.
Are you using a UIPageControl? If not, you can just deleted the methods other than setupPage. Those other methods are just used for changing the UIPageControl, and changing the page using the UIPageControl.
Here is a basic scroll view implementation similar to yours:
static NSUInteger kNumberOfPages = 3;
static NSUInteger kPageWidth = 320;
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.pagingEnabled = YES;
self.scrollView.contentSize = CGSizeMake(kPageWidth * kNumberOfPages, self.scrollView.frame.size.height);
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
self.scrollView.delegate = self;
self.pageOne.frame = CGRectMake(0, 0, kPageWidth, self.pageOne.frame.size.height);
[self.scrollView addSubview:self.pageOne];
self.pageTwo.frame = CGRectMake(kPageWidth, 0, kPageWidth, self.pageTwo.frame.size.height);
[self.scrollView addSubview:self.pageTwo];
self.pageThree.frame = CGRectMake(2*kPageWidth, 0, kPageWidth, self.pageThree.frame.size.height);
[self.scrollView addSubview:self.pageThree];
self.pageControl.numberOfPages = kNumberOfPages;
self.pageControl.currentPage = 0;
}
# pragma mark - Scroll View Related Methods
- (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.
if (pageControlUsed_)
{
// do nothing - the scroll was initiated from the page control, not the user dragging
return;
}
// Switch the indicator when more than 50% of the previous/next page is visible
int page = floor((self.scrollView.contentOffset.x - kPageWidth / 2) / kPageWidth) + 1;
self.pageControl.currentPage = page;
}
// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
pageControlUsed_ = NO;
}
// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
pageControlUsed_ = NO;
}
- (IBAction)changePage:(id)sender
{
int page = self.pageControl.currentPage;
// update the scroll view to the appropriate page
CGRect frame = self.scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
[self.scrollView scrollRectToVisible:frame animated:YES];
// Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above.
pageControlUsed_ = YES;
}

Gap between subviews of UIScrollView

I have two subviews of UIScrollView. One is textView and other is tableView. I made textview's height flexible based on its content, but I have one problem. If the text in the textview (which is parsed data) is small, there is a big gap between textview and tableview. Or if the text is too large then it covers the tableview. How can I keep the same gap between textview and tableview irrespective of the amount of content of text view? This is all done in IB.
Thanks.
you must handle both textview and tableview position dynamically like ur text view height and y-axis is
y-axis 10; height 40;
now in tableview setframe:cgrectmake(your X coordinate, textview.frame.size.height+20)
so its always show same difference between textview and tableview if your textview height is 60 than tableview y point is 60+20
- (void)loadView
{
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
pagingScrollView.pagingEnabled = YES;
pagingScrollView.backgroundColor = [UIColor blackColor];
pagingScrollView.showsVerticalScrollIndicator = NO;
pagingScrollView.showsHorizontalScrollIndicator = NO;
pagingScrollView.contentSize = CGSizeMake(pagingScrollViewFrame.size.width * [self imageCount],
pagingScrollViewFrame.size.height);
pagingScrollView.delegate = self;
self.view = pagingScrollView;
}
- (CGRect)frameForPagingScrollView {
CGRect frame = [[UIScreen mainScreen] bounds];
frame.origin.x -= PADDING;
frame.size.width += (2 * PADDING);
return frame;
}
- (CGRect)frameForPageAtIndex:(NSUInteger)index {
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
CGRect pageFrame = pagingScrollViewFrame;
pageFrame.size.width -= (2 * PADDING);
pageFrame.origin.x = (pagingScrollViewFrame.size.width * index) + PADDING;
return pageFrame;
}

iPhone:UIScrollView with Paging in Landscape Mode Issue

I am build an app in Landscape mode only and I have an issue is that not fill up color with width in a Landscape mode in iPhone but I can't understand how can i do that so please give me some idea to develop this functionality.
Refer https://github.com/cwalcott/UIScrollView-Paging
Thanks in advance.
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
pageControlBeingUsed = NO;
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], nil];
for (int i = 0; i < colors.count; i++)
{
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[self.scrollView addSubview:subview];
[subview release];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * colors.count, self.scrollView.frame.size.height);
self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = colors.count;
[super viewDidLoad];
}
- (void)scrollViewDidScroll:(UIScrollView *)sender
{
if (!pageControlBeingUsed)
{
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
}
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
pageControlBeingUsed = NO;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
pageControlBeingUsed = NO;
}
- (IBAction)changePage
{
// Update the scroll view to the appropriate page
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * self.pageControl.currentPage;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
[self.scrollView scrollRectToVisible:frame animated:YES];
// Keep track of when scrolls happen in response to the page control
// value changing. If we don't do this, a noticeable "flashing" occurs
// as the the scroll delegate will temporarily switch back the page
// number.
pageControlBeingUsed = YES;
}
Solve my issue by just remove inner subView in Autosizing property of UIScrollView in interface Builder.
I think the reason will be
self.scrollView.frame.size returns (768,1024) in viewDidLoad: method but actually you need (1024,768). To solve this,
1) In IB, Attribute Inspecter change orientation to landscape mode.
or
2) Change
frame.size = self.scrollView.frame.size;
to
frame.size = CGSizeMake(1024,768);

Fitting an Image to Screen on Rotation iPhone / iPad?

I have been playing around with one of the iPhone examples from Apple' web site (ScrollViewSuite) . I am trying to tweak it a bit so that when I rotate the the iPad the image will fit into the screen in landscape mode vertical. I have been successful in getting the image to rotate, but the image is larger than the height of the landscape screen, so the bottom is below the screen. I would like to image to scale to the height of the landscape screen.
I have been playing around with various autoSizingMask attributes without success.
The imageView is called "zoomView" this is the actual image which loads into a scrollView called imageScrollView.
I am trying to achieve the screen to rotate and look like this.... sorry only 1 link allowed new user :(
olsonvox.com/photos/correct.png
However, this is what My screen is looking like.
http://www.olsonvox.com/photos/incorrect.png
I would really appreciate some advice or guidance. Below is the RootViewController.m for the project.
Blade
#
import "RootViewController.h"
#define ZOOM_VIEW_TAG 100
#define ZOOM_STEP 1.5
#define THUMB_HEIGHT 150
#define THUMB_V_PADDING 25
#define THUMB_H_PADDING 25
#define CREDIT_LABEL_HEIGHT 25
#define AUTOSCROLL_THRESHOLD 30
#interface RootViewController (ViewHandlingMethods)
- (void)toggleThumbView;
- (void)pickImageNamed:(NSString *)name;
- (NSArray *)imageNames;
- (void)createThumbScrollViewIfNecessary;
- (void)createSlideUpViewIfNecessary;
#end
#interface RootViewController (AutoscrollingMethods)
- (void)maybeAutoscrollForThumb:(ThumbImageView *)thumb;
- (void)autoscrollTimerFired:(NSTimer *)timer;
- (void)legalizeAutoscrollDistance;
- (float)autoscrollDistanceForProximityToEdge:(float)proximity;
#end
#interface RootViewController (UtilityMethods)
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center;
#end
#implementation RootViewController
- (void)loadView {
[super loadView];
imageScrollView = [[UIScrollView alloc] initWithFrame:[[self view]bounds]];
// this code makes the image resize to the width and height properly.
imageScrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin| UIViewAutoresizingFlexibleBottomMargin| UIViewAutoresizingFlexibleBottomMargin;
// TRY SETTNG CENTER HERE SOMEHOW>....
[imageScrollView setBackgroundColor:[UIColor blackColor]];
[imageScrollView setDelegate:self];
[imageScrollView setBouncesZoom:YES];
[[self view] addSubview:imageScrollView];
[self toggleThumbView];
// intitializes with the first image.
[self pickImageNamed:#"lookbook1"];
}
- (void)dealloc {
[imageScrollView release];
[slideUpView release];
[thumbScrollView release];
[super dealloc];
}
#pragma mark UIScrollViewDelegate methods
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
UIView *view = nil;
if (scrollView == imageScrollView) {
view = [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}
return view;
}
/************************************** NOTE **************************************/
/* The following delegate method works around a known bug in zoomToRect:animated: */
/* In the next release after 3.0 this workaround will no longer be necessary */
/**********************************************************************************/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
[scrollView setZoomScale:scale+0.01 animated:NO];
[scrollView setZoomScale:scale animated:NO];
}
#pragma mark TapDetectingImageViewDelegate methods
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotSingleTapAtPoint:(CGPoint)tapPoint {
// Single tap shows or hides drawer of thumbnails.
[self toggleThumbView];
}
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotDoubleTapAtPoint:(CGPoint)tapPoint {
// double tap zooms in
float newScale = [imageScrollView zoomScale] * ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
[imageScrollView zoomToRect:zoomRect animated:YES];
}
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotTwoFingerTapAtPoint:(CGPoint)tapPoint {
// two-finger tap zooms out
float newScale = [imageScrollView zoomScale] / ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
[imageScrollView zoomToRect:zoomRect animated:YES];
}
#pragma mark ThumbImageViewDelegate methods
- (void)thumbImageViewWasTapped:(ThumbImageView *)tiv {
[self pickImageNamed:[tiv imageName]];
[self toggleThumbView];
}
- (void)thumbImageViewStartedTracking:(ThumbImageView *)tiv {
[thumbScrollView bringSubviewToFront:tiv];
}
// CONTROLS DRAGGING AND DROPPING THUMBNAILS...
- (void)thumbImageViewMoved:(ThumbImageView *)draggingThumb {
// check if we've moved close enough to an edge to autoscroll, or far enough away to stop autoscrolling
[self maybeAutoscrollForThumb:draggingThumb];
/* The rest of this method handles the reordering of thumbnails in the thumbScrollView. See */
/* ThumbImageView.h and ThumbImageView.m for more information about how this works. */
// we'll reorder only if the thumb is overlapping the scroll view
if (CGRectIntersectsRect([draggingThumb frame], [thumbScrollView bounds])) {
BOOL draggingRight = [draggingThumb frame].origin.x > [draggingThumb home].origin.x ? YES : NO;
/* we're going to shift over all the thumbs who live between the home of the moving thumb */
/* and the current touch location. A thumb counts as living in this area if the midpoint */
/* of its home is contained in the area. */
NSMutableArray *thumbsToShift = [[NSMutableArray alloc] init];
// get the touch location in the coordinate system of the scroll view
CGPoint touchLocation = [draggingThumb convertPoint:[draggingThumb touchLocation] toView:thumbScrollView];
// calculate minimum and maximum boundaries of the affected area
float minX = draggingRight ? CGRectGetMaxX([draggingThumb home]) : touchLocation.x;
float maxX = draggingRight ? touchLocation.x : CGRectGetMinX([draggingThumb home]);
// iterate through thumbnails and see which ones need to move over
for (ThumbImageView *thumb in [thumbScrollView subviews]) {
// skip the thumb being dragged
if (thumb == draggingThumb) continue;
// skip non-thumb subviews of the scroll view (such as the scroll indicators)
if (! [thumb isMemberOfClass:[ThumbImageView class]]) continue;
float thumbMidpoint = CGRectGetMidX([thumb home]);
if (thumbMidpoint >= minX && thumbMidpoint <= maxX) {
[thumbsToShift addObject:thumb];
}
}
// shift over the other thumbs to make room for the dragging thumb. (if we're dragging right, they shift to the left)
float otherThumbShift = ([draggingThumb home].size.width + THUMB_H_PADDING) * (draggingRight ? -1 : 1);
// as we shift over the other thumbs, we'll calculate how much the dragging thumb's home is going to move
float draggingThumbShift = 0.0;
// send each of the shifting thumbs to its new home
for (ThumbImageView *otherThumb in thumbsToShift) {
CGRect home = [otherThumb home];
home.origin.x += otherThumbShift;
[otherThumb setHome:home];
[otherThumb goHome];
draggingThumbShift += ([otherThumb frame].size.width + THUMB_H_PADDING) * (draggingRight ? 1 : -1);
}
// change the home of the dragging thumb, but don't send it there because it's still being dragged
CGRect home = [draggingThumb home];
home.origin.x += draggingThumbShift;
[draggingThumb setHome:home];
}
}
- (void)thumbImageViewStoppedTracking:(ThumbImageView *)tiv {
// if the user lets go of the thumb image view, stop autoscrolling
[autoscrollTimer invalidate];
autoscrollTimer = nil;
}
#pragma mark Autoscrolling methods
- (void)maybeAutoscrollForThumb:(ThumbImageView *)thumb {
autoscrollDistance = 0;
// only autoscroll if the thumb is overlapping the thumbScrollView
if (CGRectIntersectsRect([thumb frame], [thumbScrollView bounds])) {
CGPoint touchLocation = [thumb convertPoint:[thumb touchLocation] toView:thumbScrollView];
float distanceFromLeftEdge = touchLocation.x - CGRectGetMinX([thumbScrollView bounds]);
float distanceFromRightEdge = CGRectGetMaxX([thumbScrollView bounds]) - touchLocation.x;
if (distanceFromLeftEdge < AUTOSCROLL_THRESHOLD) {
autoscrollDistance = [self autoscrollDistanceForProximityToEdge:distanceFromLeftEdge] * -1; // if scrolling left, distance is negative
} else if (distanceFromRightEdge < AUTOSCROLL_THRESHOLD) {
autoscrollDistance = [self autoscrollDistanceForProximityToEdge:distanceFromRightEdge];
}
}
// if no autoscrolling, stop and clear timer
if (autoscrollDistance == 0) {
[autoscrollTimer invalidate];
autoscrollTimer = nil;
}
// otherwise create and start timer (if we don't already have a timer going)
else if (autoscrollTimer == nil) {
autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:thumb
repeats:YES];
}
}
- (float)autoscrollDistanceForProximityToEdge:(float)proximity {
// the scroll distance grows as the proximity to the edge decreases, so that moving the thumb
// further over results in faster scrolling.
return ceilf((AUTOSCROLL_THRESHOLD - proximity) / 5.0);
}
- (void)legalizeAutoscrollDistance {
// makes sure the autoscroll distance won't result in scrolling past the content of the scroll view
float minimumLegalDistance = [thumbScrollView contentOffset].x * -1;
float maximumLegalDistance = [thumbScrollView contentSize].width - ([thumbScrollView frame].size.width + [thumbScrollView contentOffset].x);
autoscrollDistance = MAX(autoscrollDistance, minimumLegalDistance);
autoscrollDistance = MIN(autoscrollDistance, maximumLegalDistance);
}
- (void)autoscrollTimerFired:(NSTimer*)timer {
[self legalizeAutoscrollDistance];
// autoscroll by changing content offset
CGPoint contentOffset = [thumbScrollView contentOffset];
contentOffset.x += autoscrollDistance;
[thumbScrollView setContentOffset:contentOffset];
// adjust thumb position so it appears to stay still
ThumbImageView *thumb = (ThumbImageView *)[timer userInfo];
[thumb moveByOffset:CGPointMake(autoscrollDistance, 0)];
}
#pragma mark View handling methods
- (void)toggleThumbView {
[self createSlideUpViewIfNecessary]; // no-op if slideUpView has already been created
CGRect frame = [slideUpView frame];
if (thumbViewShowing) {
frame.origin.y = 0;
} else {
frame.origin.y = -225;
}
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[slideUpView setFrame:frame];
[UIView commitAnimations];
thumbViewShowing = !thumbViewShowing;
}
- (void)pickImageNamed:(NSString *)name {
// first remove previous image view, if any
[[imageScrollView viewWithTag:ZOOM_VIEW_TAG] removeFromSuperview];
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.jpg", name]];
TapDetectingImageView *zoomView = [[TapDetectingImageView alloc] initWithImage:image];
zoomView.autoresizingMask = UIViewAutoresizingFlexibleWidth ;
[zoomView setDelegate:self];
[zoomView setTag:ZOOM_VIEW_TAG];
[imageScrollView addSubview:zoomView];
[imageScrollView setContentSize:[zoomView frame].size];
[zoomView release];
// choose minimum scale so image width fits screen
float minScale = [imageScrollView frame].size.width / [zoomView frame].size.width;
[imageScrollView setMinimumZoomScale:minScale];
[imageScrollView setZoomScale:minScale];
[imageScrollView setContentOffset:CGPointZero];
}
- (NSArray *)imageNames {
// the filenames are stored in a plist in the app bundle, so create array by reading this plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"Images" ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:path];
NSString *error; NSPropertyListFormat format;
NSArray *imageNames = [NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
if (!imageNames) {
NSLog(#"Failed to read image names. Error: %#", error);
[error release];
}
return imageNames;
}
- (void)createSlideUpViewIfNecessary {
if (!slideUpView) {
[self createThumbScrollViewIfNecessary];
CGRect bounds = [[self view] bounds];
float thumbHeight = [thumbScrollView frame].size.height;
float labelHeight = CREDIT_LABEL_HEIGHT;
// create label giving credit for images
UILabel *creditLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, thumbHeight, bounds.size.width, labelHeight)];
[creditLabel setBackgroundColor:[UIColor clearColor]];
[creditLabel setTextColor:[UIColor whiteColor]];
// [creditLabel setFont:[UIFont fontWithName:#"Helvetica" size:16]];
// [creditLabel setText:#"SAMPLE TEXT"];
[creditLabel setTextAlignment:UITextAlignmentCenter];
// create container view that will hold scroll view and label
CGRect frame = CGRectMake(0.0, -225.00, bounds.size.width+256, thumbHeight + labelHeight);
slideUpView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
slideUpView = [[UIView alloc] initWithFrame:frame];
[slideUpView setBackgroundColor:[UIColor blackColor]];
[slideUpView setOpaque:NO];
[slideUpView setAlpha:.75];
[[self view] addSubview:slideUpView];
// add subviews to container view
[slideUpView addSubview:thumbScrollView];
[slideUpView addSubview:creditLabel];
[creditLabel release];
}
}
- (void)createThumbScrollViewIfNecessary {
if (!thumbScrollView) {
float scrollViewHeight = THUMB_HEIGHT + THUMB_V_PADDING;
float scrollViewWidth = [[self view] bounds].size.width;
thumbScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, scrollViewWidth, scrollViewHeight)];
[thumbScrollView setCanCancelContentTouches:NO];
[thumbScrollView setClipsToBounds:NO];
// now place all the thumb views as subviews of the scroll view
// and in the course of doing so calculate the content width
float xPosition = THUMB_H_PADDING;
for (NSString *name in [self imageNames]) {
UIImage *thumbImage = [UIImage imageNamed:[NSString stringWithFormat:#"%#_thumb.jpg", name]];
if (thumbImage) {
ThumbImageView *thumbView = [[ThumbImageView alloc] initWithImage:thumbImage];
[thumbView setDelegate:self];
[thumbView setImageName:name];
CGRect frame = [thumbView frame];
frame.origin.y = THUMB_V_PADDING;
frame.origin.x = xPosition;
[thumbView setFrame:frame];
[thumbView setHome:frame];
[thumbScrollView addSubview:thumbView];
[thumbView release];
xPosition += (frame.size.width + THUMB_H_PADDING);
}
}
[thumbScrollView setContentSize:CGSizeMake(xPosition, scrollViewHeight)];
}
}
#pragma mark Utility methods
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {
CGRect zoomRect;
// the zoom rect is in the content view's coordinates.
// At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
// As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [imageScrollView frame].size.height / scale;
zoomRect.size.width = [imageScrollView frame].size.width / scale;
// choose an origin so as to get the right center.
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
return zoomRect;
}
#pragma mark -
#pragma mark Rotation support
// Ensure that the view controller supports rotation and that the split view can therefore show in both portrait and landscape.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
#end
If you've set up your UIScrollView in a Nib file, make sure it is resizing properly when rotated (Use the Autosizing controls in the Size Inspector in Interface Builder: Both sets of arrows inside the box should be red)
Then use this to rescale when the iPad changes orientation:
- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration{
//if your UIImageView is called zoomView use this
CGRect zoomRect=CGRectMake(0,0,zoomView.frame.size.width, zoomView.frame.size.height);
[scrollView zoomToRect:zoomRect animated:YES];}
(Sorry about the bad placement of the {} but it wasn't pasting properly as code for some reason)
Hope this helps!