Stan
Stan

Reputation: 6561

How to implement image view gallery using UIScrollView & UIPageControl with preview of next and previous images?

So I want to make a sliding image view gallery with preview of next and previous images. I want it to show partly the next image (if available) and the previous image (if there was one). What do I mean exactly? Assuming there are 3 images at all.

  1. the very 1st image. So I want the 1st image to display at center (horizontally) and a part of next image as well, so user could see there is at least 1 image remaining. Schematically: [&&&] [

  2. the 2nd image. I want to show a part of 1st image (at left side) and a 2nd image (at center) and a part of 3rd image (at right). So any user could easily determine there is at least 1 image behind and at least 1 image remains. Schematically: ] [###] [

  3. the 3rd and last image. There are a part of 2nd image (at left) and 3rd image at center. So there is no doubt that there is no image remains and at least 1 image behind. Schematically: ] [@@@].

So how to implement this idea in the right way?

I did it so:

//  ItemGalleryVC.h


#import <UIKit/UIKit.h>


@interface ItemGalleryVC : UIViewController <UIScrollViewDelegate>{

    IBOutlet UIScrollView  *scrollView;
    IBOutlet UIPageControl *pageControl;

    BOOL pageControlIsChangingPage;
}

@property (nonatomic, retain) IBOutlet UIScrollView  *scrollView;
@property (nonatomic, retain) IBOutlet UIPageControl *pageControl;

- (IBAction)changePage:(id)sender;
- (void)setupPage;

@end

and

    //  ItemGalleryVC.m

    #import "ItemGalleryVC.h"

    @implementation ItemGalleryVC
    @synthesize scrollView;
    @synthesize pageControl;

    - (void)viewDidLoad 
    {
        [self setupPage];
        [super viewDidLoad];
    }


    - (void)didReceiveMemoryWarning 
    {
        [super didReceiveMemoryWarning];
    }

    - (void)viewDidUnload 
    {
        [scrollView release];
        [pageControl release];
    }


    - (void)dealloc 
    {
        [super dealloc];
    }

    - (void)setupPage
    {
        NSLog(@"setupPage");
        scrollView.delegate = self;

        [scrollView setCanCancelContentTouches:NO];

        scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
        scrollView.clipsToBounds = YES;
        scrollView.scrollEnabled = YES;
        scrollView.pagingEnabled = YES;

        NSUInteger nimages = 0;
        CGFloat cx = 0; //the total scroll width
        CGRect rect = scrollView.frame; //image frame
        rect.size.height = scrollView.frame.size.height; 
        rect.size.width = scrollView.frame.size.width - 100; //50px at left and right sides
        rect.origin.y = scrollView.frame.origin.y+5; //down by 5 px
        for (; ; nimages++) {
            NSString *imageName = [NSString stringWithFormat:@"item_image0%d.jpg", (nimages + 1)];
            UIImage *image = [UIImage imageNamed:imageName];
            if (image == nil) {
                NSLog(@"no more imagez");
                break;
            }
            NSLog(@"setting up img: %@",imageName);
            UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

            rect.origin.x = cx+50; //move right by 50px

            imageView.frame = rect;
            imageView.contentMode = UIViewContentModeScaleAspectFit;
            imageView.backgroundColor = [UIColor blackColor];

            [scrollView addSubview:imageView];
            [imageView release];

            cx += rect.size.width+30;
        }

        self.pageControl.numberOfPages = nimages;
            // for the last image to be centered frame need to be wider by 100px
        [scrollView setContentSize:CGSizeMake(cx+100, [scrollView bounds].size.height)];
    }


    - (void)scrollViewDidScroll:(UIScrollView *)_scrollView
    {
        if (pageControlIsChangingPage) {
            return;
        }

        // calc page number according to its frame size 
        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;

// this code added to correct image position (frame width) when using touch sliding
        CGRect frame = scrollView.frame;
        frame.origin.x = (frame.size.width-70) * pageControl.currentPage;
        frame.origin.y = 0;

        [scrollView scrollRectToVisible:frame animated:YES];
    }

    - (IBAction)changePage:(id)sender 
    {
        /*
         *  Change the scroll view
         */
        CGRect frame = scrollView.frame;
        frame.origin.x = (frame.size.width-70) * pageControl.currentPage;
        frame.origin.y = 0;

        [scrollView scrollRectToVisible:frame animated:YES];

        pageControlIsChangingPage = NO;
    }

    @end 

The problem is the frame size (it's width). Its ScrollView.frame size but i need it smaller (less wide). With this code If I use page control only to switch images everything works fine and animation looks right. But if I use sliding its totally bad. The code above contains a fix (in scrollViewDidEndDecelerating) but it still works not native while sliding and it works good for 3 images. It slides to incorrect position and than it move a bit back. If there are more than 3 images slider wont slide to the last image.
I'm curious if there is some other and proper way to do it.

Upvotes: 0

Views: 2811

Answers (2)

Stan
Stan

Reputation: 6561

Actually I found another soultion - http://www.cocoacontrols.com/platforms/ios/controls/hgpagescrollview this control is what I want.

Upvotes: 1

Gabriel.Massana
Gabriel.Massana

Reputation: 8225

Try, and the scrollView will draw outside its bounds.

[scrollView setClipsToBounds:NO];

Upvotes: 0

Related Questions