Confusion Regarding UIScrollView and AutoLayout - ios

I have looked around many different threads over the same issue and can't seem to grasp what is going on here. I created a very basic and simple project. What I want to happen is for a bunch of elements to be inside of a scroll view that scrolls properly. These elements may include a UITableView that scrolls independently (or not). Here is how I set up my basic project:
Running this in the simulator will result in a view that doesn't scroll. This is expected as there is more than enough room for all of the elements. I then changed the size of UIScrollView like so:
Running this in the simulator results in a smaller view that will not scroll. I assume I am not doing this the correct way. Here is the code I have most recently tried:
ViewController.h
#interface ViewController : UIViewController <UIScrollViewDelegate>
#property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
#property (strong, nonatomic) IBOutlet UIButton *buttonOne;
#property (strong, nonatomic) IBOutlet UIButton *buttonTwo;
#property (strong, nonatomic) IBOutlet UIButton *buttonThree;
#property (strong, nonatomic) IBOutlet UIButton *buttonFour;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.buttonOne setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.buttonTwo setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.buttonThree setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.buttonFour setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Any help would be greatly appreciated.

The problem is that when you change the size of the scroll view in interface builder, you are also setting the content's size to the same as the frame size.
You can manually increase the content size of the scroll view in code so that you can scroll it like this:
// scrollView is an outlet to your scroll view
// Add 200 points to the bottom of the scroll view
[self.scrollView setContentInset:UIEdgeInsetsMake(0, 0, 200, 0)];
Though, you probably don't need to do this as long as you draw the sub view at full size, and make it a sub view of some other view, and let it automatically re-size itself.

Related

Nested UIScrollViews. Trying to get one to zoom out with the same speed and factor as the other zooming in. View frozen

I am trying to set up nested UIScrollViews. What I have is two scroll views with the same content size 640*640 setup like this: canvasScrollView (a UIScrollView) > contentScrollView (a UIScrollView) > content (a UIView). These are all in a UIViewController. What I want to happen is, when the user pinches to zoom in on the content in contentScrollView the canvasScrollView view zooms out at with same factor and speed. I have tried setting up code like below:
#import "ViewController.h"
#import "ContentView.h"
#interface ViewController () <UIScrollViewDelegate>
#property (weak, nonatomic) IBOutlet UIScrollView *canvasScrollView;
#property (strong, nonatomic) UIView *viewForZoom;
#property (strong, nonatomic) ContentView *content;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIScrollView *contentScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 568)];
contentScrollView.contentSize=CGSizeMake(640 ,640);
contentScrollView.minimumZoomScale=0.25;
contentScrollView.maximumZoomScale=1;
self.content = [[[NSBundle mainBundle] loadNibNamed:#"floatingView" owner:self options:nil] objectAtIndex:0];
self.viewForZoom=self.content;
[contentScrollView addSubview:self.content];
contentScrollView.delegate=self;
//canvasScrollView was setup in the interface builder, same dimensions as above 320*568
self.canvasScrollView.contentSize=CGSizeMake(640 ,640);
self.canvasScrollView.minimumZoomScale=0.25;
self.canvasScrollView.maximumZoomScale=1;
self.canvasScrollView.userInteractionEnabled=NO;
[self.canvasScrollView addSubview:contentScrollView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.viewForZoom;
}
My first step is to make sure it is the contentScrollView that zooms and not the canvasScrollView. With my code above the views load up fine but I am unable to pan or zoom the content. I'm not sure why this doesn't work. I have disabled the canvasScrollView from user interaction as later on this will be modified programmatically, I have also set the contentScrollView delegate. Not working though. Would really appreciate some help on this one!!!
Thanks
You have added contentScrollView to a view that has userInteractionEnabled=NO. A view that doesn't allow user interaction does not allow user interaction any of its subviews. Try attaching it to the self.view instead.
[self.view addSubview:contentScrollView];

ios, scrolling screen with a few objects without zooming. Attempt 2

#everybody
Hi guys!
I've not found out the solution to my problem, so I decide to ask the question again.
First attempt is there LINK
I have screen w/ a few labels. Each of them might be from 1 to a dozen lines. So some times all content not to fit on screen so scrolling is necessary.
All seem to be easy and there are a lot of tutorials how to do it. Just set contentSize bigger than frame. But my problem that scrolling works only when I zoom in screen. Setting contentSize doesn't give any effect.
#interface OMSScroolViewController : UIViewController <UIScrollViewDelegate>
#property (strong, nonatomic) IBOutlet UIScrollView *scroll;
#property (strong, nonatomic) IBOutlet UILabel *label1;
#property (strong, nonatomic) IBOutlet UILabel *label2;
#end
and implementation
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
scroll.minimumZoomScale=1.0;
scroll.maximumZoomScale=1.0;
[scroll setContentSize:CGSizeMake(320, 1690)]; // constants for simplicity
scroll.delegate=self;
}
I've also tried to use a extra UIView inside UIScroolView but w/o any success.
Moreover I found a few threads there on stackoverflow w/ the same problem, unfortunately w/o solutions.
Thanks for cooperation.

ios, scrolling screen with a few objects without zooming

I have screen w/ a few labels. Each of them might be from 1 to a dozen lines.
So some times all content not to fit on screen so scrolling is necessary.
All seem to be easy and there are a lot of tutorials how to do it.
But my problem that scrolling works only when I zoom in screen. Setting "contentSize" doesn't give any effect.
#interface OMSScroolViewController : UIViewController <UIScrollViewDelegate>
#property (strong, nonatomic) IBOutlet UIScrollView *scroll;
#property (strong, nonatomic) IBOutlet UILabel *label1;
#property (strong, nonatomic) IBOutlet UILabel *label2;
#end
and implementation
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
scroll.minimumZoomScale=1.0;
scroll.maximumZoomScale=1.0;
[scroll setContentSize:CGSizeMake(320, 1690)]; // constants for simplicity
scroll.delegate=self;
}
any suggestions?
thanks in advance.
Although not technically required, I've never had UIScrollView to work properly without using a content view to wrap the scrollable content. Once you wrap all your labels in a single view, your code should work without issue.

Having delegate problems for my Navigation controller

so i have a navigation controller, and in it i have a view and a scrollview embedded in that view. My goal is to make my program scroll to a location when it is close to it.
to do this i added to outlets to my vc. one is the scroll view and the other is the view. The view is just a big rectangle about twice as wide as the iphones screen and slightly higher. My scroll view scrolls only horizantally, and whenever i lift my finger from scrolling, my goal is if the iphones bounds are within the views bounds. I want the scroll view to manually scroll to the middle of that view. (if you can think of a game menu in angry birds or cut the rope, when the user is scrolling between level packs horizantally, when the user lets go from scrolling it sort of zaps into place to the level the user let go by, this is what i want to mimick).
so, heres my code for both my view and my vc. The only thing i did with storyboards is that i hooked up the two outlets, and set the size of my view.
(the level packs is the vc and the other one is the view).
#import <UIKit/UIKit.h>
#import "HorizantalLockingView.h"
#interface LevelPacks : UIViewController <ViewDelegate>
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property (weak, nonatomic) IBOutlet HorizantalLockingView *lockingView;
#end
#import "LevelPacks.h"
#implementation LevelPacks
#synthesize scrollView=_scrollView;
#synthesize lockingView = _lockingView;
-(void)viewDidAppear:(BOOL)animated
{
CGSize size;
size.width=825;
size.height=460;
self.scrollView.contentSize=size;
self.scrollView.contentOffset=CGPointMake(0, 0);
}
-(void)viewDidLoad
{
[super viewDidLoad];
self.lockingView.delegate=self;
}
- (void)viewDidUnload
{
[self setLockingView:nil];
[super viewDidUnload];
self.scrollView=nil;
// Release any retained subviews of the main view.
}
#end
#import <UIKit/UIKit.h>
#protocol ViewDelegate
#property (nonatomic, weak) UIScrollView *scrollView;
#end
#interface HorizantalLockingView : UIView
#property (nonatomic, weak) IBOutlet id <ViewDelegate> delegate;
#end
#import "HorizantalLockingView.h"
#implementation HorizantalLockingView
#synthesize delegate=_delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
CGRect location=self.superview.bounds;
NSLog(#"dkfjdkjf");
if (CGRectContainsRect(self.frame, location))
{
[self.delegate.scrollView scrollRectToVisible:CGRectMake(284, 190, 157, 119) animated:YES];
}
}
#end
o, and i did the nslog earlier to see if the method would even do anything, and the nslog never even ran, so obviously somethings wrong.
Im kind of new to this, any help would really be great!
Enabling paging will automatically do this for you.
scrollView.pagingEnabled=YES;
Also adding a UIPageControl and using the UIScrollView delegate methods to update the page control will add a good usability

iOS setting a UIScrollView variable from IB shows as nil

At the moment I have a UIViewController subclass with a UIScrollView and a UIView inside of it. Below is a snippet of code from the class:
.h
#import <UIKit/UIKit.h>
#interface Scroller : UIViewController <UIScrollViewDelegate>
{
UIScrollView *scrollView;
UIView *testView;
}
#property (retain, nonatomic) IBOutlet UIScrollView *scrollView;
#property (retain, nonatomic) IBOutlet UIView *testView;
#end
Inside the IB I link the UIScrollview to my variable, but when I get to the .m and try setting my scrollview contentSize it shows the scrollView as being nil.
.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// Initialize of scrollView
scrollView.contentSize = CGSizeMake(500, 500);
scrollView.delegate = self;
}
Am I missing an import or anything to get this to be properly allocated?
Edit
It may help to know, but if I try to debug the issue and in the lldb check the value of scrollView I get a EXC_BAD_ACCESS error if I try to continue in the code.
try
//.h
#interface Scroller : UIViewController <UIScrollViewDelegate>
{
}
#property (retain, nonatomic) IBOutlet UIScrollView *scrollView;
#property (retain, nonatomic) IBOutlet UIView *testView;
//.m
[self.scrollView setContentSize:CGSizeMake(500, 500)];
just to clarify
scrollview without the self. was looking at the iVar - which I assume you had not alloc-ed/init-ed.
The #property IBOutlet connected to your nib is NOT the same as that iVar. In effect you have two variables of the same name - if you get rid of those iVars the property will still get allocated and initialised for you when the XIB is loaded.
The issue wasn't related to the code, but the debugger itself. I tried doing this in xCode 4.3.1 and was debugging through the application and saw that the proper fields weren't being set both in the xib and in the code. I deleted everything and opened up xCode 4.2 and tried in there and everything worked nicely. After testing in 4.2 I moved to 4.3.1 where it asked me to switch from the GDB to the LLDB. I guess it was just paranoia on my end for not seeing proper results showing up.

Resources