Getting UIScrollView to work correctly on iPad - ios

2ND UPDATE
Courtesy of this thread
In iOS6, XCode 4.5, UIScrollView is not Scrolling, despite contentSize being set
the answer has been provided! Turning off Auto Layout on your Storyboard (the entire thing) will fix ScrollView and allow things to scroll properly. Spread the word people!
UPDATE
Added code. Seriously cannot figure out why this will not work on a iPad.
.h file
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#end
.m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.contentSize = CGSize(768, 1600);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Again just to clarify I'm using Storyboards, I'm first dragging in a ScrollView, setting the size to standard iPad screen (768x1004 because I have a Nav bar at the top) then adding my image on top of that and setting it's size (768x1600). Then I connect both of these to the header file (as shown above) and still I can't get the image to scroll. I have my view mode set to "Aspect Fit", could this be the issue? I've tried other settings and no luck but not all of them.
Any specific advice would be so appreciated!
ORIGINAL POST
I know there a number of topics out there regarding this one, but I'm having a dog of a time trying to get a ScrollView to work. I am attempting to load an image that is 768x1600 (on an iPad screen only) so that you have to vertically scroll to see more of the image's content. To create the ScrollView, I use a Storyboard and drag a ScrollView into the ViewController frame, align it and ensure interactions are enabled. Then, on top of the ScrollView (also in Storyboard) I add the UIImage I wish to use (ensuring it is a subview) and size it accordingly, then set interactions enabled as well.
No matter how hard I try, I cannot get this to work in Simulator or on my device. I have made sure that my ScrollView is set as a delegate in the IB, that is has an IBOutlet on the header file and is both synthesized and loaded into my implementation file. I have also ensured that I have set contentSize by;
self.scrollView.contentSize = CGSizeMake(768, 1600);
I have also tried to add the UIImage as a Subview via code (as opposed to on the Storyboard) and when I do this the image does not appear when I run Simulator. On top of this, when I click the page no scrolling option is available.
Any help anyone can give me on this one is much appreciated. If code is necessary I will post it.

I think I just figured it out. You say you drug the UIImageView on top of the scroll view.
UIImageView's aren't user-interactable!
Try selecting your image view in Interface Builder and setting 'User interaction enabled' to YES for the image view.
If that doesn't work, I would suggest adding the image view in code (remove it from IB first):
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"someImage.png"]];
self.imageView.frame = CGRectMake(0,0,768,1600);
self.imageView.userInteractionEnable = YES;
[self.scrollView addSubview:self.imageView];
self.scrollView.contentSize = CGSizeMake(768, 1600);
self.scrollView.frame = self.view.bounds;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

Related

Basic UIAnimation

This is a very basic question but its my first time doing any animation in an app.
I have the following scenario. View 1 with some text is displayed and at a certain time the other views 2 and 3 should be animated in from the top pushing down on the first view.
At the moment I'm using auto layout in storyboard. Should I stop doing that when I want to animate or continue using it?
Do I have to programmatically add/update constraints or show/hidden views?
I have tried show/hidden but it doesn't seem to work for me. When trying this I added all the views (right picture) and then set view 2 and 3 to be hidden hoping the bottom view to automatically go up, but that didn't work...
I haven't tried to manually set constraints because i have never done it before. I have a basic understanding of how it should be done but would like to know first if its the way to go?
I've set up a very basic project to illustrate my answer. You can find it here. Almost everything is done in IB. The left red view is pinned to the top of the screen and this constraint is connected to an IBOutlet in ViewController.m. Position of other views depend on position of the left red view. We change this constraint's constant value two times - first time after VC has loaded but not yet appeared on the screen, to move red views out of the screen. Second time, when button is pressed, we change constraint to what it was and force layout with animation. That's pretty much it.
#import "ViewController.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *redViewTopConstraint;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.redViewTopConstraint.constant = - ([UIScreen mainScreen].bounds.size.width * 0.3 + 20);
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)action:(id)sender {
self.redViewTopConstraint.constant = 20;
[UIView animateWithDuration:0.5f delay:0 usingSpringWithDamping:0.65f initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
#end

UIScrollView not working with Autolayout called from a Tab Bar Controller

I have created a very simple test environment one Tab Bar Controller and one View Controller with the following structure:
UI TAB BAR Controller ---------> UIScrollView
UIScrollView
View
Scroll View
Label
Label
Label
.h file
#interface rpViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
#end
.m file
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.scrollView.contentSize = CGSizeMake(320, 1000);
}
If the start entry point for the app is the view with the scroller everything works fine!
If the start entry point is theTab Bar Controller the scroller is not working?
If your going to work purely with Autolayout you should not be doing any direct manipulations of frames, bounds or contentSize. Apple has written a technical note about working with UIScrollView and Autolayout Technical Note TN2154 that you should read.
So to answer the question, if you are going to be using auto layout you cannot manipulate contentSize and expect consistent results.

UIButton not clickable outside initial frame of an UIScrollView

I got stuck with the strange behavior of UIScrollView that I cannot click on the UIButton after I enlarge the contentSize of the UIScrollView.
What I wanted to do:
Show a form with using UIScrollView
After clicking on the submit button, the scroll view will enlarge some amount of height to show further information.
In the further information, I will place and show another UIButton(hidden at the beginning) in order to process to the next step.
The problem is that I placed the new UIButton to the enlarged area and the button is not clickable whereas I placed the UIButton to existing area(the initial frame of scroll view) then the button works normally. For both cases, the scroll bar of the scroll view performs normal behavior.(ie, the scroll end is the new content height)
Here is what I have so far:
A UIView xib (placed all elements inside it including the hidden button)
A UIScrollView (loaded the UIView xib into it)
UIView* view = [[[NSBundle mainBundle] loadNibNamed:#"view" owner:self options:nil] objectAtIndex:0];
[view loaded];
[scrollView addSubview:view];
After the submit button is clicked:
// offset = some amount;
[scrollview setContentSize:CGSizeMake(scrollview.contentSize.width, scrollview.contentSize.height+offset)];
// h = some amount before the end of the scroll view
CGRect r = nextBtn.frame;
r.origin.y = h;
nextBtn.frame = r;
[nextBtn setHidden:NO];
I have tried to change the clipSubviews attribute of scroll view but seems it is not working for my case at all.
Anyone knows how it happens? And is there any better methods to get this job done? (resize the scroll view and then place another button in it)
Any help would be great! Thanks a lot!
I assume that the button is direct or indirect child of the contents view you load from the xib file.
The problem is because you changed the scroll view's contentSize but did not change the frame of the contents view. Superviews participate in touch hit testing. You can place a subview outside of its superview bounds and by default the subview will not be clipped but touch events will not be delivered to it because the superview checks during hit testing that the touch is outside of its bounds and rejects the touch. See UIView hitTest:withEvent: for details.
You can add a button say submit and another button as subview of the scrollview.Keep your another button hidden in start and call setContentsize. now when user clicks on submit button then set another button to visible and again call set content size.In this way you would be able to achieve what you want to.
i have tried to generate scenario for you.I have tried this on view based application with storyboard without auto layout.
so in story board do some thing like this:
#import <UIKit/UIKit.h>
#interface ALViewController : UIViewController
#property (nonatomic, weak) IBOutlet UIScrollView *scroll;
#property (nonatomic, weak) IBOutlet UIButton *btn1;
#property (nonatomic, weak) IBOutlet UIButton *btn2;
===========
implementation:
#import "ALViewController.h"
#interface ALViewController ()
#end
#implementation ALViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.btn2 setHidden:YES];
[self adjustContentSize];
}
-(void)adjustContentSize
{
CGRect contentRect = CGRectZero;
for (UIView *view in self.scroll.subviews)
{
if (![view isHidden]) {
contentRect = CGRectUnion(contentRect, view.frame);
}
}
self.scroll.contentSize = contentRect.size;
}
(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)btnClicked:(id)sender
{
UIButton *btn = (UIButton *)sender;
if (btn.tag ==1)
{
[self.btn2 setHidden:FALSE];
[self adjustContentSize];
}
}
#end
and in storyboard some thing like this:
#end
for your information:view frame 0,0,768,1024
scroll frame: 0,0,768,1024
btn1 frame: 361, 753, 46, 30
btn2 frame: 351, 1032, 46, 30
run your code :
at first your scroll view would be unscrollable because we have set btw 2 to be hidden and set content size.As soon as you will be clicking on btn 1, see code we are making btn 2 visible again and calling set content size.
Conclusion:
the scrollview content size looks for its visible contain of which we can take benefit of.
thanks and regards.

How to insert a UITextView to a UIImageView

I'm programming an application, in wich you create UIImageView-objects.
The color of these objects can be set.
But the next step I am trying to do is: set a TextView in the imageView, but this text should entered by the user (certainly realized with the class UIKeyboard.)
Im sum: I have a imageView, which needs an editable UITextView in it.
Do you have any idea how it could be realized?
Your approach is wrong.
You want an image view because the app lets you "create an image"
In reality and technically this isn't correct, what you will want to be doing is using a simple UIView to set he colour of an area, and you an place a UITextField or UITextView over that.
A UIImageView is a very specific UIView subclass for displaying images. You can't add your other UI inside of it, the best you could do is over it.
I you do use a UIView, when you're done you need to "convert" your UIView to an image which you can then use to save, send etc
For more about that check out Save UIView's representation to file
You simply want to subclass UIImageView and add a UITextView during init. Like this
#interface MyImageView : UIImageView {
}
#property (nonatomic, strong) UITextView *textView;
#end
And the implementation
#implementation MyImageView
- (id)init {
if ((self = [super init])) {
self.textView = [[UITextView alloc] initWithFrame:CGRectMake(...)];
[self addSubview:self.textView];
}
return self;
}
#end

why my actual UI layout is not same with my designed layout in xib

this is what I designed in xib, and it's my expectation also.
My ViewControlle.h file:
#interface DetailHeadViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIScrollView *slideScrollView;
#property (weak, nonatomic) IBOutlet UIImageView *smallImageView;
#property (weak, nonatomic) IBOutlet UIImageView *barBGVImageView;
#end
My ViewController.m file (part of the source code)
- (void)viewDidLoad
{
[super viewDidLoad];
slideScrollView.pagingEnabled = YES;
slideScrollView.showsHorizontalScrollIndicator = NO;
slideScrollView.showsVerticalScrollIndicator = NO;
UIImageView * page1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"headSection_hot1"]];
[slideScrollView addSubview:page1]; //Update 3
}
the result is this,
But actually the correct result is this,
Anyone can help to point out what the problem is?
Thanks in advance
update (remove bar image)
for easier, I remove bar image in xib and also comment out the relatived code.
Please see the following picture.
update 2
IB
To me it looks like your scroll view frame is not set correctly. It should probably be set to 0,0,480,320.
It also looks like the transparency isn't set on the BarImageView. Select the BarImageView in the xib, open up the inspector window, click on the 4th tab, set the background color to Clear Color and reduce the alpha.
You may also want to post how your adding the image to the scroll view as that could create issues as well.
Update 1:
In the viewDidLoad of your DetailHeadViewController try this:
self.scrollView.frame = self.view.bounds;
UIImageView * page1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"headSection_hot1"]];
page1.frame = self.view.bounds;
[self.slideScrollView addSubview:page1];
self.scrollView.contentSize = self.view.bounds.size; // Note that the contentSize must be changed
// from this if you want to scroll.

Resources