Before you bash me for duplicate, please know that I have looked nearly every other method but none of them have helped. I have a long view in which I have a scroll view.
The view is 320 by 671. The scroll view has been linked to the outlet "scrollView" correctly.
The property "scrollView" has been properly declared and synthesised.
My code:
[scrollView setScrollEnabled: YES];
scrollView.contentSize = CGSizeMake(320, 671);
scrollView.clipsToBounds = YES;
scrollView.delegate = self; // I have adopted the delegate protocol in .h
So, my problem is that the view doesn't scroll, and the scroll bar doesn't even show up.
EDIT:
I resized the uiview to normal 320 by 460. I deleted the scroll view in xib and decided to add like this:
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame: CGRectMake(self.view.center.x, self.view.center.y, 320, 460)];
[scrollView setScrollEnabled: YES];
scrollView.contentSize = CGSizeMake(320, 671);
scrollView.clipsToBounds = YES; scrollView.delegate = self;
[self.view addSubview: scrollView];
OK, now what happens is when I scroll the screen, the bar comes up and I can scroll around to change the bar's position, but the actual view doesn't scroll
You need set the ContentSize of UIScrollView to the size of your CONTENT.
Do not set "ContentSize" to the size of the view. The "Content Size" should tell the size of the content within the scroll view.
Your scrollview should be 320x460 and your scrollview.contentsize should be 320x671.
You must layout your subviews "outside" of the view in IB.
EDIT:
Your layout should look like this:
http://ge.tt/api/1/files/4qGbz2N/2/blob/x675
The textview is placed outside the views frame but inside the scrollview. The scrollviews content size should be set accordingly to fit all subviews. In this case yValue should be 550 + 128
Related
So after figuring out how scrollView works, I've implemented it with the following code:
self.scrollView.delegate = self;
self.scrollView.userInteractionEnabled = YES;
CGRect view = CGRectMake(0, 0, 320, 750);
self.scrollView.contentSize = view.size;
The above code works as intended on ALL simulators in Xcode 6. However, when I run it my phone (iphone4s on ios7), the scroll does not function at all. Are people experiencing the same problems since the new release? Or am I missing something I've learned from the documentation?
Had the same issue here. Just need to resize the scrollview's frame size in viewDidLayoutSubviews which overrides auto layout.
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[scrollView setContentSize:CGSizeMake(320, 2600)];
// Adjust frame for iPhone 4s
if (self.view.bounds.size.height == 480) {
scrollView.frame = CGRectMake(0, 0, 320, 436); // 436 allows 44 for navBar
}
}
In AutoLayout
In general, Auto Layout considers the top, left, bottom, and right edges of a view to be the visible edges. That is, if you pin a view to the left edge of its superview, you’re really pinning it to the minimum x-value of the superview’s bounds. Changing the bounds origin of the superview does not change the position of the view.
The UIScrollView class scrolls its content by changing the origin of its bounds. To make this work with Auto Layout, the top, left, bottom, and right edges within a scroll view now mean the edges of its content view.
The constraints on the subviews of the scroll view must result in a size to fill, which is then interpreted as the content size of the scroll view. (This should not be confused with the intrinsicContentSize method used for Auto Layout.) To size the scroll view’s frame with Auto Layout, constraints must either be explicit regarding the width and height of the scroll view, or the edges of the scroll view must be tied to views outside of its subtree.
Note that you can make a subview of the scroll view appear to float (not scroll) over the other scrolling content by creating constraints between the view and a view outside the scroll view’s subtree, such as the scroll view’s superview.
Here are two examples of how to configure the scroll view, first the mixed approach, and then the pure approach
Mixed Approach
Position and size your scroll view with constraints external to the scroll view—that is, the translatesAutoresizingMaskIntoConstraints property is set to NO.
Create a plain UIView content view for your scroll view that will be the size you want your content to have. Make it a subview of the scroll view but let it continue to translate the autoresizing mask into constraints:
- (void)viewDidLoad {
UIView *contentView;
contentView = [[UIView alloc] initWithFrame:CGRectMake(0,0,contentWidth,contentHeight)];
[scrollView addSubview:contentView];
// DON'T change contentView's translatesAutoresizingMaskIntoConstraints,
// which defaults to YES;
// Set the content size of the scroll view to match the size of the content view:
[scrollView setContentSize:CGSizeMake(contentWidth,contentHeight)];
/* the rest of your code here... */
}
Create the views you want to put inside the content view and configure their constraints so as to position them within the content view.
Alternatively, you can create a view subtree to go in the scroll view, set up your constraints, and call the systemLayoutSizeFittingSize: method (with the UILayoutFittingCompressedSize option) to find the size you want to use for your content view and the contentSize property of the scroll view
Pure Auto Layout Approach
To use the pure autolayout approach do the following:
Set translatesAutoresizingMaskIntoConstraints to NO on all views involved.
Position and size your scroll view with constraints external to the scroll view.
Use constraints to lay out the subviews within the scroll view, being sure that the constraints tie to all four edges of the scroll view and do not rely on the scroll view to get their size.
A simple example would be a large image view, which has an intrinsic content size derived from the size of the image. In the viewDidLoad method of your view controller, you would include code similar to the code shown in the listing below:
- (void)viewDidLoad {
UIScrollView *scrollView;
UIImageView *imageView;
NSDictionary *viewsDictionary;
// Create the scroll view and the image view.
scrollView = [[UIScrollView alloc] init];
imageView = [[UIImageView alloc] init];
// Add an image to the image view.
[imageView setImage:[UIImage imageNamed:"MyReallyBigImage"]];
// Add the scroll view to our view.
[self.view addSubview:scrollView];
// Add the image view to the scroll view.
[scrollView addSubview:imageView];
// Set the translatesAutoresizingMaskIntoConstraints to NO so that the views autoresizing mask is not translated into auto layout constraints.
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
imageView.translatesAutoresizingMaskIntoConstraints = NO;
// Set the constraints for the scroll view and the image view.
viewsDictionary = NSDictionaryOfVariableBindings(scrollView, imageView);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[imageView]|" options:0 metrics: 0 views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[imageView]|" options:0 metrics: 0 views:viewsDictionary]];
/* the rest of your code here... */
}
I did not try Vishu's answer, but what I did was update to iOS 8 so it's compatible with Xcode 6 and it worked!
I have a UIScrollView which is 208pt wide and 280pt tall that contains custom buttons that are 200pt wide and 280 pt tall with 8pt gaps between them. This scrollview has paging enabled but doesn't clip the subviews so that it always snaps to having one button centered but shows the other ones that go off screen. I am trying to make the field in which you can swipe through the buttons take up the full width of the screen, and I am trying to accomplish this with a secondary custom subclass of UIScrollView called PagingView which just has a UIScrollView property and passes all hits on it down to its scrollview. For whatever reason, though, when I try it without the paging view like this:
unsigned height = self.view.frame.size.height;
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(60, height - 308, 208, 280)];
scrollView.pagingEnabled = true;
scrollView.clipsToBounds = false;
scrollView.showsHorizontalScrollIndicator = false;
[self.view addSubview:scrollView];
It works, albeit with the field I can interact with the scrollview limited to its frame. However, when I try it with the scrollview:
unsigned height = self.view.frame.size.height;
pagingView = [[PagingView alloc] initWithFrame:CGRectMake(0, height - 308, 320, 280)];
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(60, height - 308, 208, 280)];
scrollView.pagingEnabled = true;
scrollView.clipsToBounds = false;
scrollView.showsHorizontalScrollIndicator = false;
pagingView.scrollView = scrollView;
[self.view addSubview:pagingView];
[self.view addSubview:scrollView];
It works, but I am able to swipe anywhere on the screen to move through the scrollview. How do I remedy this?
Not clear what you are doing here. You are adding two scroll views to self.view but actually you need only one.
The easiest way with least code is to use one plain UIScrollView, present your buttons as subviews of correctly sized UIViews (you need the gaps around the buttons), and enable paging for the scroll view. Done.
Please note that the measurements you describe do not work out. The scroll view width is 208, the button 200, so the wrapper view should have width 208 and the origin.x of the button should be 4. The scroll view height is 280, the button as well, so there is no vertical margin: wrapper height also 280, button origin.y is 0.
I've got a scroll view, in which I have an imageview displaying a 960x960 image, but it scrolls to something close to 4x that. I've tried to log the widths of all possible views and everything claims that it's 960x960 (or smaller, I think I logged the screen width once...?)
I need this image to stop scrolling at the bottom right corner of the image rather than entering deadspace. Any help would be greatly appreciated.
Heck, even telling me what the name of the object is that is larger than my scrollView.contentSize would put me on the right track...
//Test-Image is just a 960 by 960 image that's numbered around the edges 1-10 so you can tell if it's being moved
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Test-Image.png"]];
self.imageView = tempImageView;
[tempImageView release];
scrollView.contentSize = CGSizeMake(imageView.frame.size.width, imageView.frame.size.height);
//Tested with this, results the same.
//[scrollView setContentSize:CGSizeMake(960, 960)];
NSLog(#"What is my scrollView's height attribute?...%f", scrollView.contentSize.height);
// Returns 960
NSLog(#"What is in scrollView's width attribute?...%f", scrollView.contentSize.width);
// Returns 960
scrollView.contentOffset = CGPointMake(480, 480);
scrollView.maximumZoomScale = 8.0;
scrollView.minimumZoomScale = 0.25;
// Commenting clipsToBounds out doesn't seem to have any effect
scrollView.clipsToBounds = YES;
scrollView.delegate = self;
[scrollView addSubview:imageView];
Unfortunately, I do not have a specific answer.
Reference. Try [scrollView addSubview: self.imageView]; instead of [...addSubview: imageView];
Content Size. Try setting the content size after adding the ImageView.
[scrollView setContentSize: CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];
Delegate. Did you use and set the scrollview's delegate property (oIWScroll.delegate = self;)?
Clipping. It should not matter.
ScrollView Frame. Make sure the frame of the scrollview is equal to or smaller than [UIScreen mainScreen].applicationFrame.
Framing. When I had a situation similar to what you described, one of the the things I did was to create a container UIView, add it to the scroll view and stuff the objects into the container view. But you really should not have to do that for one image.
I also set the contentMode = UIViewContentModeTop.
I hope these suggestions help.
I am writing an iPhone app with a tab bar and navigation bar. At a certain point, I am pushing an instance of my DetailsViewController class onto the navigation controller stack to show it.
This controller creates its view hierarchy in code: the controller's view property is set to a UIScrollView, which contains a plain UIView (let's call it "contentView") sized to hold all the content to be shown. At the bottom of this contentView, I have four UIButtons.
Now when I run the app (in the simulator at present), and scroll to the bottom of the view, the top two buttons respond to touches; the third responds to touches only in the top portion of it, and the lower button doesn't respond to touches at all. By clicking in various parts of the third button, it appears that the lower 93 pixels of the scroll view is not passing touch events through to its subviews.
93 is suspicious: it's also the combined height of the tab bar (49 pixels) and navigation bar (44 pixels). Yet the navigation bar and tab bar are outside the scroll view. Any suggestions why this might be happening?
Here's the code in question:
- (void)loadView
{
CGRect frame = [[UIScreen mainScreen] applicationFrame];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:frame];
scrollView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
scrollView.delegate = self;
self.view = scrollView;
UIView *contentView = [[UIView alloc] initWithFrame:scrollView.bounds];
contentView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
[scrollView addSubview:contentView];
CGSize viewSize = contentView.bounds.size;
CGSize size;
CGFloat y = 0;
/* Snip creating various labels and image views */
/* Actions view creates and lays out the four buttons; its sizeThatFits:
** method returns the frame size to contain the buttons */
actionsView = [[PropertyDetailActionsView alloc] initWithFrame:CGRectZero];
actionsView.autoresizingMask = (UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth);
actionsView.delegate = self;
size = [actionsView sizeThatFits:viewSize];
actionsView.frame = CGRectMake(0, y, size.width, size.height);
[contentView addSubview:actionsView];
y += size.height;
[contentView setFrame:CGRectMake(0, 0, viewSize.width, y)];
scrollView.contentSize = contentView.frame.size;
[contentView release];
[scrollView release];
}
As I suggested on Twitter yesterday, it may have something to do with the flexible bottom margin set to the actionsView.
That suggestion did not resolve the problem, yet it lead to the right direction. By removing the flexible height of the contentView the problem has been fixed.
So if anyone out there is having similar problems, try to play with your autoresizingMasks.
also make sure all your content views are the height that covers the bottom button.
I make each view a different color to see them.
I added a UIScrollView in my appDelegate, and then did
scrollView.contentSize = CGSizeMake(720, 480);
scrollView.showsHorizontalScrollIndicator = YES;
scrollView.showsVerticalScrollIndicator = YES;
scrollView.delegate = self;
[scrollView addSubview:viewController.view];
[window makeKeyAndVisible];
Where view Controller loads up a UIView. In IB, I set the size of the UIView to be 720x480, but it's not showing up any larger when I run. I can scroll around my UIView to blank white space that is 720x480, but I want my UIView to be resized to this size too. I checked the arguments in the initial drawRect rect, and they are still only 320x480, so it seems that I have to do something else to set the size of my UIView, other than resize it in IB?
I got around this by changing the frame size of the view from the viewControllers ViewDidLoad method. Apparently the controller was constraining the UIView size, even though I set it as larger in IB.