I have a problem with a custom class of UIScrollView that I use to hold an UIImageView inside of it.
I have another ViewController with a Main UIScrollView that I add some objects of the CustomScrollViewClass Class. I am trying to enable zooming inside this custom UIScrollvView but with no sucess!!!
Everything seems to work fine BUT I cannot zoom the UIImageView inside my object from CustomScrollViewClass! I have tried a lot of things but nothing worked by now.
//CustomScrollViewClass .h file
#import <UIKit/UIKit.h>
#interface CustomScrollViewClass : UIScrollView <UIScrollViewDelegate>
{
BOOL iPad;
BOOL iPhone5;
NSString *imageName;
UIImageView *imageView;
}
#property (nonatomic,strong) NSString *imageName;
#property (nonatomic,strong) UIImageView *imageView;
- (id)initWithImageAndFrame:(CGRect)frame imageName:(NSString*)image;
#end
This is the .m file
//CustomScrollViewClass .m file
#import "CustomScrollViewClass.h"
#implementation CustomScrollViewClass
#synthesize imageName,imageView;
- (id)initWithImageAndFrame:(CGRect)frame imageName:(NSString*)image
{
self = [super initWithFrame:frame];
if (self) {
CGRect imagef;
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
if (screenSize.height > 480.0f) {
iPhone5 = YES;
imagef = CGRectMake(0, 0, 320, 388);
} else {
iPhone5 = NO;
imagef = CGRectMake(0, 0, 320, 420);
}
iPad = NO;
} else {
iPad = YES;
iPhone5 = NO;
imagef = CGRectMake(0, 0, 768, 824);
}
self.contentSize = imagef.size;
self.maximumZoomScale = 2.0;
self.minimumZoomScale = 1.0;
self.zoomScale = 1.0;
self.userInteractionEnabled = YES;
self.multipleTouchEnabled = YES;
imageName = image;
UIImageView *imageAux = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
imageAux.frame = imagef;
imageAux.contentMode = UIViewContentModeScaleAspectFit;
imageView = imageAux;
[self addSubview:imageView];
NSLog(#"%#",imageName);
}
return self;
}
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
NSLog(#"%#",#"viewForZoomingInScrollView");
return self.imageView;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
NSLog(#"%#",#"scrollViewDidZoom");
}
#end
As you can see it should work with zoom but it does not! The image appears noarmally. The part of the code I use to add custom views of it is this one (in this example I add 5 custom views in the Main UIScrollView):
//Method in MainView that I add objects from CustomScrollViewClass
-(void)PrepareScrollView
{
CGSize scrollviewc;
//Add Main ScrollView
UIScrollView *scroll = [[UIScrollView alloc] init];
if (iPad) {
scrollviewf = CGRectMake(0, 200, 768, 824);
scrollviewc = CGSizeMake((768 * 5), 824);
}
else {
if (iPhone5){
scrollviewf = CGRectMake(0, 180, 320, 388);
scrollviewc = CGSizeMake((320 * 5), 388);
} else {
scrollviewf = CGRectMake(0, 60, 320, 420);
scrollviewc = CGSizeMake((320 * 5), 420);
}
}
scroll.frame = scrollviewf;
scroll.contentSize = scrollviewc;
scroll.pagingEnabled = YES;
for (int i = 0; i < 5; i++) {
CGRect imagef;
if (iPad) {
imagef = CGRectMake((i * 768), 0, 768, 824);
} else {
if (iPhone5){
imagef = CGRectMake((i * 320), 0, 320, 388);
} else {
imagef = CGRectMake((i * 320), 0, 320, 420);
}
}
//Add Custom ScrollView with UIImageView
CustomScrollViewClass *AUX = [[ImageView alloc] initWithImageAndFrame:imagef imageName:[NSString stringWithFormat:#"%i%#",i+1,#"_pt.jpg"]];
[scroll addSubview:AUX];
}
self.scrollView = scroll;
[self.view addSubview:self.scrollView];
}
Related
My application starts by showing some Intro slides. 4 in total and in the last one, a button is used to close the slides and to go to the main page.
What I wish to make is to remove the button, and to make the last slide slidable. The user continues to slide to the right, and at the end it lands to the main page.
But don't know how to acheave that.
Here is the definition of
#interface IntroSlideViewController ()<ABCIntroViewDelegate>
#property ABCIntroView *introView;
#end
#implementation IntroSlideViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
}
-(void)viewDidAppear:(BOOL)animated{
/***************Page Control**************/
self.introView = [[ABCIntroView alloc] initWithFrame:self.view.frame];
self.introView.delegate = self;
self.introView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:1.000];
[self.view addSubview:self.introView];
/***************************************/
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)onDoneButtonPressed {
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:FIRSTTIME_LOGIN];
InitScreenViewController* initVc = [self.storyboard instantiateViewControllerWithIdentifier:#"initScreenViewController"];
UINavigationController *navVC = [[UINavigationController alloc] initWithRootViewController:initVc];
[navVC setNavigationBarHidden:true];
[UIView transitionWithView:[AppDelegate getShareInstance].window duration:0.1f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
[AppDelegate getShareInstance].window.rootViewController = navVC;
}completion:nil];
}
#end
And the parent class ABCIntroViewDelegate:
#interface ABCIntroView () <UIScrollViewDelegate>
#property (strong, nonatomic) UIScrollView *scrollView;
#property (strong, nonatomic) UIPageControl *pageControl;
#property (strong, nonatomic) UIButton *doneButton;
#property (strong, nonatomic) UIView *viewOne;
#property (strong, nonatomic) UIView *viewTwo;
#property (strong, nonatomic) UIView *viewThree;
#property (strong, nonatomic) UIView *viewFour;
#property (strong, nonatomic) UIView *viewFive;
#end
#implementation ABCIntroView
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
[self addSubview:self.scrollView];
[self addSubview:self.pageControl];
[self.scrollView addSubview:self.viewOne];
[self.scrollView addSubview:self.viewTwo];
[self.scrollView addSubview:self.viewThree];
[self.scrollView addSubview:self.viewFour];
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
//Done Button
//[self addSubview:self.doneButton];
}
return self;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat pageWidth = CGRectGetWidth(self.bounds);
CGFloat pageFraction = self.scrollView.contentOffset.x / pageWidth;
self.pageControl.currentPage = roundf(pageFraction);
}
-(UIView *)viewOne {
if (!_viewOne) {
_viewOne = [[UIView alloc] initWithFrame:self.frame];
UIImageView *imageview;
imageview = [[UIImageView alloc] initWithFrame:self.frame];
imageview.image = [UIImage imageNamed:#"intro_slide_0"];
[_viewOne addSubview:imageview];
}
return _viewOne;
}
-(UIView *)viewTwo {
if (!_viewTwo) {
CGFloat originWidth = self.frame.size.width;
CGFloat originHeight = self.frame.size.height;
_viewTwo = [[UIView alloc] initWithFrame:CGRectMake(originWidth, 0, originWidth, originHeight)];
UIImageView *imageviewTwo;
imageviewTwo = [[UIImageView alloc] initWithFrame:self.frame];
imageviewTwo.image = [UIImage imageNamed:#"intro_slide_1"];
[_viewTwo addSubview:imageviewTwo];
}
return _viewTwo;
}
-(UIView *)viewThree{
if (!_viewThree) {
CGFloat originWidth = self.frame.size.width;
CGFloat originHeight = self.frame.size.height;
_viewThree = [[UIView alloc] initWithFrame:CGRectMake(originWidth*2, 0, originWidth, originHeight)];
UIImageView *imageviewThree;
imageviewThree = [[UIImageView alloc] initWithFrame:self.frame];
imageviewThree.image = [UIImage imageNamed:#"intro_slide_2"];
[_viewThree addSubview:imageviewThree];
}
return _viewThree;
}
-(UIView *)viewFour {
if (!_viewFour) {
CGFloat originWidth = self.frame.size.width;
CGFloat originHeight = self.frame.size.height;
_viewFour = [[UIView alloc] initWithFrame:CGRectMake(originWidth*3, 0, originWidth, originHeight)];
UIImageView *imageviewFour;
imageviewFour = [[UIImageView alloc] initWithFrame:self.frame];
imageviewFour.image = [UIImage imageNamed:#"intro_slide_3"];
[_viewFour addSubview:imageviewFour];
UIButton *btnDone = [[UIButton alloc] initWithFrame:CGRectMake(30, self.frame.size.height - 130, self.frame.size.width-60, 50)];
[btnDone setImage:[UIImage imageNamed:#"slide_3_button_unpressed"] forState:UIControlStateNormal];
[btnDone setImage:[UIImage imageNamed:#"slide_3_button_pressed"] forState:UIControlStateHighlighted];
[btnDone addTarget:self.delegate action:#selector(onDoneButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_viewFour addSubview:btnDone];
}
return _viewFour;
}
-(UIView *)viewFive {
if (!_viewFive) {
}
return _viewFive;
}
-(UIScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
[_scrollView setDelegate:self];
[_scrollView setPagingEnabled:YES];
[_scrollView setContentSize:CGSizeMake(self.frame.size.width*numberofPage, self.scrollView.frame.size.height)];
[self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
}
return _scrollView;
}
-(UIPageControl *)pageControl {
if (!_pageControl) {
_pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, self.frame.size.height-20, self.frame.size.width, 10)];
//[_pageControl setCurrentPageIndicatorTintColor:UIColorFromRGBAlpha(252, 61, 136, 1)];
//[_pageControl setPageIndicatorTintColor:UIColorFromRGBAlpha(223, 227, 232, 1)];
[_pageControl setNumberOfPages:numberofPage];
}
return _pageControl;
}
-(UIButton *)doneButton {
if (!_doneButton) {
_doneButton = [[UIButton alloc] initWithFrame:CGRectMake(0, self.frame.size.height-60, self.frame.size.width, 100)];
[_doneButton setTintColor:[UIColor whiteColor]];
// [_doneButton.titleLabel setFont:FONT_Regular(17)];
[_doneButton setBackgroundColor:[UIColor colorWithRed:96/255.0 green:167/255.0 blue:23/255.0 alpha:1]];
[_doneButton addTarget:self.delegate action:#selector(onDoneButtonPressed) forControlEvents:UIControlEventTouchUpInside];
}
return _doneButton;
}
#end
Maybe what I am asking is not possible to be implemented.
Any clues and ideas are welcome
You can easily achieve your requirement by modifying ABCIntroView class. From ABCIntroView you are getting the callback as - (void)onDoneButtonPressed to IntroSlideViewController so there you are navigating to MainViewController.
So follow up these steps to achieve your requirement
Remove done button code from ABCIntroView.
Modify the below function.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat pageWidth = CGRectGetWidth(self.bounds);
CGFloat pageFraction = self.scrollView.contentOffset.x/pageWidth;
self.pageControl.currentPage = roundf(pageFraction);
if (self.delegate != nil && self.pageControl.currentPage == 4){
[self.delegate onDoneButtonPressed];
}}
I've edited this question a few times, but can still not get my images to center inside a uiview. I want them to be able to rotate like the photos app and display the correct size when a user brings them up. Here is what I'm working with:
In my PhotoViewController.h
#import <UIKit/UIKit.h>
#protocol PhotoViewControllerDelegate <NSObject>
- (void)toggleChromeDisplay;
#end
#interface PhotoViewController : UIViewController <UIScrollViewDelegate, UIGestureRecognizerDelegate>
#property (nonatomic, strong) UIImage *photo;
#property (nonatomic) NSUInteger num;
//Delegate
#property (nonatomic, strong) id<PhotoViewControllerDelegate> photoViewControllerDelegate;
#property (nonatomic, strong) UIImageView *photoImgView;
#property (nonatomic, strong) UIScrollView *scrollView;
#end
In my PhotoViewController.m:
#import "PhotoViewController.h"
#interface PhotoViewController ()
#end
#implementation PhotoViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
//todo
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect screenBounds = self.view.bounds;
//scroll view
_scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, screenBounds.size.width, screenBounds.size.height)];
_scrollView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
_scrollView.pagingEnabled = NO;
_scrollView.scrollEnabled = YES;
[_scrollView setBackgroundColor:[UIColor blueColor]];
//Zoom Properties
_scrollView.maximumZoomScale = 6.0;
_scrollView.minimumZoomScale = 1.0;
_scrollView.bouncesZoom = YES;
_scrollView.delegate = self;
_scrollView.zoomScale = 1.0;
_scrollView.contentSize = _photoImgView.bounds.size;
[_scrollView setShowsHorizontalScrollIndicator:NO];
[_scrollView setShowsVerticalScrollIndicator:NO];
[self photoBounds];
[self.view addSubview: _scrollView];
//Add the UIImageView
_photoImgView = [[UIImageView alloc] initWithImage:_photo];
_photoImgView.image = _photo;
_photoImgView.clipsToBounds = YES;
_photoImgView.contentMode = UIViewContentModeScaleAspectFit;
_photoImgView.autoresizingMask = (UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin);
[_photoImgView setUserInteractionEnabled:YES];
[_scrollView addSubview: _photoImgView];
//Set up Gesture Recognizer
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapGestureCaptured:)];
UITapGestureRecognizer *dTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dTapGestureCaptured:)];
dTap.numberOfTapsRequired = 2;
[singleTap requireGestureRecognizerToFail:dTap];
//Gesture Methods
[self.scrollView addGestureRecognizer:singleTap];
[self.scrollView addGestureRecognizer : dTap];
}
- (void)photoBounds
{
UIInterfaceOrientation statusbar = [[UIApplication sharedApplication] statusBarOrientation];
CGSize photoBounds = _photo.size;
CGSize scrollBounds = self.view.bounds.size;
CGRect frameToCenter = [_photoImgView frame];
float newHeight = (scrollBounds.width / photoBounds.width) * photoBounds.height;
float newWidth = (scrollBounds.height / photoBounds.height) * photoBounds.width;
float yDist = fabsf(scrollBounds.height - newHeight) / 2;
float xDist = fabsf(scrollBounds.width - newWidth) / 2;
//Width Larger
if (photoBounds.width >=photoBounds.height) {
NSLog(#"portrait width");
_photoImgView.frame = CGRectMake(0, 0, scrollBounds.width, newHeight);
frameToCenter.origin.y = yDist;
}
//Height Larger
else if (photoBounds.height > photoBounds.width) {
NSLog(#"portrait height");
_photoImgView.frame = CGRectMake(0, 0, newWidth, scrollBounds.height);
frameToCenter.origin.x = xDist;
}
//Square
else {
NSLog(#"portrait square");
if ((statusbar == 1) || (statusbar == 2)) {
_photoImgView.frame = CGRectMake(0, 0, scrollBounds.width, newHeight);
frameToCenter.origin.y = yDist;
} else {
_photoImgView.frame = CGRectMake(0, 0, newWidth, scrollBounds.height);
frameToCenter.origin.x = xDist;
}
}
}
//Rotation Magic
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
//later
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self photoBounds];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
//
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
//Zoom Ability
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.photoImgView;
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
{
NSLog(#"scale %f", scale);
NSLog(#"done zooming");
}
//Touches Control
- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
//CGPoint touchPoint=[gesture locationInView:_scrollView];
NSLog(#"touched");
NSLog(#"single touch");
[self performSelector:#selector(callingHome) withObject:nil afterDelay:0];
}
- (void)dTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
NSLog(#"double touched");
}
- (void)panGestureCaptured:(UIPanGestureRecognizer *)gesture
{
NSLog(#"pan gesture");
}
- (void)callingHome {}
#end
The overall issue is that I can not get my picture to display correctly and be able to zoom on just it, no space around it and It needs to be the correct dimensions on load. I've been struggling with it for a few days.
Any help?
I have resolved a similar problem using a really simple subclass of UIScrollView of my own. You can take a look at it here - https://gist.github.com/ShadeApps/5a29e1cea3e1dc3df8c8. Works like charm for me.
That's how you init it:
scrollViewMain.delegate = self;
scrollViewMain.minimumZoomScale = 1.0;
scrollViewMain.maximumZoomScale = 3.0;
scrollViewMain.contentSize = imageViewMain.frame.size;
scrollViewMain.backgroundColor = [UIColor blackColor];
scrollViewMain.tileContainerView = imageViewMain;
There is awesome blog post about this problem from Peter Steinberger: http://petersteinberger.com/blog/2013/how-to-center-uiscrollview/
I have two Scroll View's in a xib, and they both contain a very large image that should start with it completely scaled down to fit. The first ScrollView works perfectly, objects are all moving around correctly when you zoom or scroll, but the second ScrollView starts completely zoomed in, unable to zoom out.
The ScrollView is now showing 25% of the image(completely zoomed in at 0,0) and also cannot be dragged to see the rest. If I pinch to zoom, the image moves diagonally up and left without zooming at all, I can now drag the image back to 0,0 and back down the the max point it scrolled diagonally.
.h file
UIScrollView *_scrollView;
UIScrollView *_miamiScrollView;
UIView *_mapImageView;
UIView *_mapMiamiView;
UIView *_mapContentView;
NSArray *_autoLayoutViews;
NSArray *_staticViews;
#property (strong, nonatomic) IBOutlet UIScrollView *scrollView;//(linked to working scrollview)
#property (strong, nonatomic) IBOutlet UIScrollView *miamiScrollView;//(Linked to 'broken' scrollview)
.m file
- (void)viewDidLoad
{
[self _customizeViews];
}
- (void) _customizeViews
{
UIImageView *mapImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"MainGameDisplay.jpg"]];
mapImageView.userInteractionEnabled = YES;
UIImageView *mapMiamiView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"miami.jpg"]];
mapMiamiView.userInteractionEnabled = YES;
_mapContentView = [[UIView alloc] initWithFrame:CGRectMake(0, 50, 568, 270)];
_mapContentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
_mapContentView.clipsToBounds = YES;
_mapContentView.userInteractionEnabled = YES;
[_mapContentView addSubview:_scrollView];
[_mapContentView addSubview:_miamiScrollView];
[self.view addSubview:_mapContentView];
[self.view sendSubviewToBack:_mapContentView];
UIScrollView *scrollView = _scrollView;
CGRect scrollFrame = scrollView.frame;
scrollFrame.origin = CGPointZero;
scrollView.frame = scrollFrame;
scrollView.delegate = self;
scrollView.minimumZoomScale = 1;
scrollView.maximumZoomScale = 1.0;
[scrollView addSubview:mapImageView];
scrollView.contentSize = mapImageView.frame.size;
_scrollView = scrollView;
_mapImageView = mapImageView;
UIScrollView *miamiScrollView = _miamiScrollView;
CGRect miamiScrollFrame = CGRectMake(0 , 270, 568, 270);
scrollFrame.origin = CGPointZero;
miamiScrollView.frame = miamiScrollFrame;
miamiScrollView.delegate = self;
miamiScrollView.minimumZoomScale = 0.125;
miamiScrollView.maximumZoomScale = 1;
[miamiScrollView addSubview:mapMiamiView];
miamiScrollView.contentSize = mapMiamiView.frame.size;
_miamiScrollView = miamiScrollView;
_mapMiamiView = mapMiamiView;
[self _setupAutolayoutViews];
[self _setupStaticViews];
[self _zoomToFit: _scrollView];
[self _zoomToFit: _miamiScrollView];
[self _updatePositionForViews:_autoLayoutViews];
}
- (void) _zoomToFit: (UIScrollView*)view
{
CGFloat contentWidth = view.contentSize.width;
CGFloat contentHeigth = view.contentSize.height;
CGFloat viewWidth = view.frame.size.width;
CGFloat viewHeight = view.frame.size.height;
CGFloat width = viewWidth / contentWidth;
CGFloat heigth = viewHeight / contentHeigth;
CGFloat scale = MAX(width, heigth);
if ( scale < view.minimumZoomScale ) {
view.minimumZoomScale = scale;
} else if ( scale > view.maximumZoomScale ) {
view.maximumZoomScale = scale;
}
view.zoomScale = scale;
}
#pragma mark - Positions
- (void) _updatePositionForViews:(NSArray *)views
{
CGFloat scale = _scrollView.zoomScale;
CGPoint contentOffset = _scrollView.contentOffset;
contentOffset.x -= _scrollView.frame.origin.x;
contentOffset.y -= _scrollView.frame.origin.y;
for ( UIView *view in views ) {
CGPoint basePosition = [self _basePositionForView:view];
[self _updatePositionForView:view scale:scale basePosition:basePosition offset:contentOffset];
}
}
- (CGPoint) _basePositionForView:(UIView *)view
{
NSString *key = [NSString stringWithFormat:#"%d", view.tag];
NSString *stringValue = [_coordinates objectForKey:key];
NSArray *values = [stringValue componentsSeparatedByString:#":"];
if ( [values count] < 2 ) return CGPointZero;
CGPoint result = CGPointMake([[values objectAtIndex:0] floatValue], [[values objectAtIndex:1] floatValue]);
return result;
}
- (void) _updatePositionForView:(UIView *)view scale:(CGFloat)scale basePosition:(CGPoint)basePosition offset:(CGPoint)offset;
{
CGPoint position;
position.x = (basePosition.x * scale) - offset.x;
position.y = (basePosition.y * scale) - offset.y;
CGRect frame = view.frame;
frame.origin = position;
view.frame = frame;
}
//////////////////////////////////////////////////////////////////////////////////////
#pragma mark - UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
{
[self _lockInteraction];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
{
[self _unlockInteraction];
}
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
{
[self _lockInteraction];
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
{
[self _unlockInteraction];
}
- (void) _lockInteraction
{
[self _setControls:_staticViews interacted:NO];
[self _setControls:_autoLayoutViews interacted:NO];
}
- (void) _unlockInteraction
{
[self _setControls:_staticViews interacted:YES];
[self _setControls:_autoLayoutViews interacted:YES];
}
- (void) _setControls:(NSArray *)controls interacted:(BOOL)interacted
{
for ( UIControl *control in controls ) {
if ( [control isKindOfClass:[UIControl class]]) {
control.userInteractionEnabled = interacted;
}
}
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
[self _updatePositionForViews:_autoLayoutViews];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self _updatePositionForViews:_autoLayoutViews];
}
- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView;
{
return _mapImageView;
}
//DEFAULT BUTTONS.
- (void) _setupAutolayoutViews
{
UIButton *btn1 = [UIButton buttonWithType: UIButtonTypeDetailDisclosure];
[btn1 addTarget:self action:#selector(quickTest:) forControlEvents:UIControlEventTouchUpInside];
btn1.tag = kAddContactButton;
btn1.center = CGPointZero;
[_mapContentView addSubview:btn1];
_autoLayoutViews = [[NSArray alloc] initWithObjects:btn1, nil];
}
//CUSTOM BUTTONS.
- (void) _setupStaticViews
{
UIButton *openMiamiButton = [UIButton buttonWithType:UIButtonTypeCustom];
[openMiamiButton setBackgroundImage:[UIImage imageNamed:#"logo.png"] forState:UIControlStateNormal];
[openMiamiButton addTarget:self action:#selector(quickTest:) forControlEvents:UIControlEventTouchUpInside];
openMiamiButton.frame = CGRectMake(0.0 ,0.0, 50.0, 50.0);
openMiamiButton.tag = OpenMiamiButton;
openMiamiButton.enabled = YES;
openMiamiButton.alpha = 0.5;
[_mapImageView addSubview:openMiamiButton];
_staticViews = #[openMiamiButton,];
for ( UIView *view in _staticViews ) {
CGPoint point = [self _basePositionForView:view];
CGRect frame = view.frame;
frame.origin = point;
view.frame = frame;
}
}
//And for the transition between views:
-(void) quickTest: (UIButton *)button
{
/*
if (!openMiami)
openMiami = [[MiamiGameDisplay alloc] initWithNibName:nil bundle:nil];
openMiami.mainPage = self;
[self.navigationController pushViewController:openMiami animated:YES];
*/
if (!testBool){
[UIView animateWithDuration:0.5f
animations:^{
_scrollView.frame = CGRectMake(0 , -270, 568, 270);
}
completion:Nil];
[UIView animateWithDuration:0.5f
animations:^{
_miamiScrollView.frame = CGRectMake(0 , 0, 568, 270);
}
completion:Nil];
testBool=YES;
}
else {
[UIView animateWithDuration:0.5f
animations:^{
_miamiScrollView.frame = CGRectMake(0 , 270, 568, 270);
}
completion:Nil];
[UIView animateWithDuration:0.5f
animations:^{
_scrollView.frame = CGRectMake(0 , 0, 568, 270);
}
completion:Nil];
testBool=NO;
}
}
I've run into a similar issue with scrollViews. Basically, as far as I can tell, only the last scrollView added to the window will respond as a scrollView.
You can produce the same effect with any other type of object being added to the window before the scrollView.
Example :
[[self window] addSubview:logo];
[[self window] addSubview:scrollView];
Will work, but:
[[self window] addSubview:scrollView];
[[self window] addSubview:logo];
will not. (Currently running against iOS 6.1.2 and xCode 4.6.1)
I am making a simple slideshow view within my app. I'd like to link my UIPageControl to my UIScrollView. This shouldn't be too difficult, but I haven't been able to find a simple solution anywhere. Below is my code.
HelpViewController.h
#import <UIKit/UIKit.h>
#interface HelpViewController : UIViewController{
}
#end
HelpViewController.m
#import "HelpViewController.h"
#interface HelpViewController ()
#end
#implementation HelpViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect scrollViewFrame = CGRectMake(0, 62, 320, 404);
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:scrollViewFrame];
[self.view addSubview:scrollView];
CGSize scrollViewContentSize = CGSizeMake(640, 404);
[scrollView setContentSize:scrollViewContentSize];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 50, 21)];
[label setText:#"Hello"];
[scrollView addSubview:label];
[scrollView setPagingEnabled:YES];
scrollView.showsHorizontalScrollIndicator = NO;
UIPageControl *pageControl = [[UIPageControl alloc] init];
pageControl.frame = CGRectMake(110,5,100,100);
pageControl.numberOfPages = 2;
pageControl.currentPage = 0;
[self.view addSubview:pageControl];
pageControl.backgroundColor = [UIColor redColor];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
Maybe this works for you
Don't forget to set the UIScrollView's delegate = self (or wherever you have the selector below).
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat pageWidth = self.scrollView.frame.size.width; // you need to have a **iVar** with getter for scrollView
float fractionalPage = self.scrollView.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
self.pageControl.currentPage = page; // you need to have a **iVar** with getter for pageControl
}
For your code it then would be:
.h file
#import <UIKit/UIKit.h>
#interface HelpViewController : UIViewController{
}
#property (nonatomic, retain) UIScrollView *scrollView;
#property (nonatomic, retain) UIPageControl * pageControl;
#end
.m file
#import "HelpViewController.h"
#interface HelpViewController ()
#end
#implementation HelpViewController
#synthesize scrollView=scrollView_;
#synthesize pageControl=pageControl_;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect scrollViewFrame = CGRectMake(0, 62, 320, 404);
self.scrollView = [[[UIScrollView alloc] initWithFrame:scrollViewFrame] autorelease];
self.scrollView.delegate = self;
[self.view addSubview:self.scrollView];
CGSize scrollViewContentSize = CGSizeMake(640, 404);
[self.scrollView setContentSize:scrollViewContentSize];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 50, 21)];
[label setText:#"Hello"];
[self.scrollView addSubview:label];
[self.scrollView setPagingEnabled:YES];
self.scrollView.showsHorizontalScrollIndicator = NO;
self.pageControl = [[[UIPageControl alloc] init] autorelease];
self.pageControl.frame = CGRectMake(110,5,100,100);
self.pageControl.numberOfPages = 2;
self.pageControl.currentPage = 0;
[self.view addSubview:self.pageControl];
pageControl.backgroundColor = [UIColor redColor];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat pageWidth = self.scrollView.frame.size.width;
float fractionalPage = self.scrollView.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
self.pageControl.currentPage = page;
}
#end
This is actually quite simple to setup. Firstly you need to create the scroll view and page control. Make sure you implement UIScrollViewDelegate in the interface of the class.
UIScrollView * scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * 3, scrollView.frame.size.height);
scrollView.delegate = self;
UIPageControl * pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 90, scrollView.frame.size.width, 20)];
pageControl.numberOfPages = scrollView.contentSize.width/scrollView.frame.size.width;
[pageControl addTarget:self action:#selector(changePage:) forControlEvents:UIControlEventValueChanged];
Then you need to add the following two methods:
- (IBAction)changePage:(id)sender {
CGFloat x = pageControl.currentPage * scrollView.frame.size.width;
[scrollView setContentOffset:CGPointMake(x, 0) animated:YES];
}
-(void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSInteger pageNumber = roundf(scrollView.contentOffset.x / (scrollView.frame.size.width));
pageControl.currentPage = pageNumber;
}
These methods add the required communication between the page control and the scroll view.
Following code will work for Swift:
func addScrollView() {
let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
let numberOfPages: CGFloat = 4
scrollView.contentSize = CGSize(width: scrollView.frame.width * numberOfPages, height: scrollView.frame.height * numberOfPages)
scrollView.delegate = self
scrollView.isPagingEnabled = true
let pageControl = UIPageControl(frame: CGRect(x: 0, y: scrollView.frame.height - 37, width: scrollView.frame.width, height: 37))
pageControl.numberOfPages = Int(numberOfPages)
pageControl.currentPage = 0
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let value = scrollView.contentOffset.x / scrollView.frame.size.width
pageControl.currentPage = Int(round(value))
}
to get exact page index without rounding off the value simply put the pagecontrol.currentpage in the scrollViewDidEndDecelerating delegate method of scroll view.This works for me!
All these answers are great but I'd like to offer an alternative solution, using ReactiveCocoa!
The following code makes an assumption that you have a property called scrollView and one called pageControl.
[RACObserve(self.scrollView, contentOffset)
subscribeNext:^(NSValue* value){
CGPoint offset = [value CGPointValue];
CGFloat fractional = offset.x/self.scrollView.width;
[self.pageControl setCurrentPage:lroundf(fractional)];
}];
All that's going on here is you're observing change on the contentOffset property of the scrollView and calculating the page index on every next event (i.e. every time the property value changes).
The only downside of this is that you have to unbox the CGPoint but on the upside there's no UIScrollViewDelegate code needed at all!
I want to publish tutorial about how to easily create an UIScrollView on http://www.xprogress.com/ and I just want to check with you guys if the code is alright before I publish anything. Any help will be appreciated and I'll put your name / website on the bottom of the article :)
Thanks a lot :)
Ondrej
header file:
///
/// IGUIScrollViewImage.h
///
/// IGUILibrary
///
/// Created by Ondrej Rafaj on 7.4.10.
///
/// Copyright 2010 Home. All rights reserved.
///
/// #todo enable margin and center the image to the middle of the view
/**
<b>Examples:</b>
<i>This is just a short example how to use this class</i>
<pre>
- (NSArray *)getImages {
NSMutableArray *arr = [[[NSMutableArray alloc] init] autorelease];
[arr addObject:[UIImage imageNamed:#"image-1.jpg"]];
[arr addObject:[UIImage imageNamed:#"image-2.png"]];
[arr addObject:[UIImage imageNamed:#"image-3.png"]];
[arr addObject:[UIImage imageNamed:#"image-4.jpg"]];
return (NSArray *)arr;
}
- (void)viewDidLoad {
IGUIScrollViewImage *svimage = [[IGUIScrollViewImage alloc] init];
[svimage setSizeFromScrollView:self.scrView]; // takes size of the scroll view you've already placed on stage via Interface Builder
// or
//[svimage setWidth:320 andHeight:240]; // half screen
[svimage enablePositionMemory]; // enables position (pagination) memory for this scroll view
// or
//[svimage enablePositionMemoryWithIdentifier:#"myIdentifier"]; if you have more instances of this scroll view in your application
[svimage enablePageControlOnBottom];
// or
//[svimage enablePageControlOnTop];
[self.myUIView addSubview:[svimage get]]; // and place it on the stage :)
[super viewDidLoad];
}
</pre>
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface IGUIScrollViewImage : NSObject <UIScrollViewDelegate> {
UIScrollView *scrollView;
UIPageControl *pageControl;
CGRect rectScrollView;
CGRect rectPageControl;
int scrollWidth;
int scrollHeight;
NSArray *contentArray;
UIColor *bcgColor;
BOOL pageControlEnabledTop;
BOOL pageControlEnabledBottom;
BOOL rememberPosition;
NSString *positionIdentifier;
}
#property (nonatomic, retain) UIScrollView *scrollView;
- (int)getScrollViewWidth;
- (void)setWidth:(int)width andHeight:(int)height;
- (void)setSizeFromScrollView:(UIScrollView *)scView;
- (void)setBackGroudColor:(UIColor *)color;
- (void)setContentArray:(NSArray *)images;
- (void)enablePageControlOnTop;
- (void)enablePageControlOnBottom;
- (void)enablePositionMemory;
- (void)enablePositionMemoryWithIdentifier:(NSString *)identifier;
- (UIScrollView *)getWithPosition:(int)page;
- (UIScrollView *)getWithPositionMemoryIdentifier:(NSString *)identifier;
- (UIScrollView *)get;
#end
And the implementation file:
//
// IGUIScrollViewImage.m
// IGUILibrary
//
// Created by Ondrej Rafaj on 7.4.10.
// Copyright 2010 Home. All rights reserved.
//
#import "IGUIScrollViewImage.h"
#define kIGUIScrollViewImagePageIdentifier #"kIGUIScrollViewImagePageIdentifier"
#define kIGUIScrollViewImageDefaultPageIdentifier #"Default"
#implementation IGUIScrollViewImage
#synthesize scrollView;
- (int)getScrollViewWidth {
return ([contentArray count] * scrollWidth);
}
- (void)setWidth:(int)width andHeight:(int)height {
scrollWidth = width;
scrollHeight = height;
if (!width || !height) rectScrollView = [[UIScreen mainScreen] applicationFrame];
else rectScrollView = CGRectMake(0, 0, width, height);
}
- (void)setSizeFromScrollView:(UIScrollView *)scView {
scrollWidth = scView.frame.size.width;
scrollHeight = scView.frame.size.height;
rectScrollView = CGRectMake(0, 0, scrollWidth, scrollHeight);
}
- (void)setContentArray:(NSArray *)images {
contentArray = images;
}
- (void)setBackGroudColor:(UIColor *)color {
bcgColor = color;
}
- (void)enablePageControlOnTop {
pageControlEnabledTop = YES;
}
- (void)enablePageControlOnBottom {
pageControlEnabledBottom = YES;
}
- (void)enablePositionMemoryWithIdentifier:(NSString *)identifier {
rememberPosition = YES;
if (!identifier) identifier = kIGUIScrollViewImageDefaultPageIdentifier;
positionIdentifier = identifier;
}
- (void)enablePositionMemory {
[self enablePositionMemoryWithIdentifier:nil];
}
- (UIScrollView *)getWithPosition:(int)page {
if (!contentArray) {
contentArray = [[[NSArray alloc] init] autorelease];
}
if (page > [contentArray count]) page = 0;
if (!scrollWidth || !scrollHeight) {
rectScrollView = [[UIScreen mainScreen] applicationFrame];
scrollWidth = rectScrollView.size.width;
scrollHeight = rectScrollView.size.height;
}
rectScrollView = CGRectMake(0, 0, scrollWidth, scrollHeight);
self.scrollView = [[UIScrollView alloc] initWithFrame:rectScrollView];
self.scrollView.contentSize = CGSizeMake([self getScrollViewWidth], scrollHeight);
if (!bcgColor) bcgColor = [UIColor blackColor];
self.scrollView.backgroundColor = bcgColor;
self.scrollView.alwaysBounceHorizontal = YES;
self.scrollView.contentOffset = CGPointMake(page * scrollWidth, 0);
self.scrollView.pagingEnabled = YES;
UIImageView *imageView;
UIView *main = [[[UIView alloc] initWithFrame:rectScrollView] autorelease];
int i = 0;
for (UIImage *img in contentArray) {
imageView = [[UIImageView alloc] initWithImage:img];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
imageView.backgroundColor = [UIColor blackColor];
float ratio = img.size.width/rectScrollView.size.width;
CGRect imageFrame = CGRectMake(i, 0, rectScrollView.size.width, (img.size.height / ratio));
imageView.frame = imageFrame;
[self.scrollView addSubview:imageView];
i += scrollWidth;
}
[imageView release];
[main addSubview:scrollView];
if (pageControlEnabledTop) {
rectPageControl = CGRectMake(0, 5, scrollWidth, 15);
}
else if (pageControlEnabledBottom) {
rectPageControl = CGRectMake(0, (scrollHeight - 25), scrollWidth, 15);
}
if (pageControlEnabledTop || pageControlEnabledBottom) {
pageControl = [[[UIPageControl alloc] initWithFrame:rectPageControl] autorelease];
pageControl.numberOfPages = [contentArray count];
pageControl.currentPage = page;
[main addSubview:pageControl];
}
if (pageControlEnabledTop || pageControlEnabledBottom || rememberPosition) self.scrollView.delegate = self;
//if (margin) [margin release];
return (UIScrollView *)main;
}
- (UIScrollView *)get {
return [self getWithPosition:0];
}
- (UIScrollView *)getWithPositionMemoryIdentifier:(NSString *)identifier {
[self enablePositionMemoryWithIdentifier:identifier];
return [self getWithPosition:[[[NSUserDefaults alloc] objectForKey:[NSString stringWithFormat:#"%#%#", kIGUIScrollViewImagePageIdentifier, positionIdentifier]] intValue]];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sv {
int page = sv.contentOffset.x / sv.frame.size.width;
pageControl.currentPage = page;
if (rememberPosition) {
[[NSUserDefaults alloc] setObject:[NSString stringWithFormat:#"%d", page] forKey:[NSString stringWithFormat:#"%#%#", kIGUIScrollViewImagePageIdentifier, positionIdentifier]];
}
}
- (void)dealloc {
[scrollView release];
[super dealloc];
}
#end
Just a quick glance. You alloc UIImageView multiple times in
-(UIScrollView*)getWithPosition:(int)page and release it only once:
for (UIImage *img in contentArray) {
imageView = [[UIImageView alloc] initWithImage:img];
// ...
}
[imageView release];