UIScrollView not working with Autolayout called from a Tab Bar Controller - ios

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.

Related

Buttons/Links under view object in .xib file are not responding

Can somebody tell me why none of the buttons under the "License Agreement View" UIView object in my .xib file are triggering an action? It seems that the Scrollview object is messing up the behavior. When the buttons are directly under the "Scroll View" object (as opposed to the "License Agreement View" UIView object), then they function properly. But, I need to group my buttons under the UIViews as shown in the view hierarchy below.
Here's the view layout:
Here's my view hierarchy:
Here's the corresponding .m file:
#interface MYViewController ()
- (IBAction)licenseAgreementPressed:(id)sender;
- (IBAction)legalDisclaimerPressed:(id)sender;
- (IBAction)privacyStatementPressed:(id)sender;
#property (strong, nonatomic) IBOutlet UIView *licenseAgreementView;
#property (weak, nonatomic) IBOutlet UIButton *legalDisclaimerButton;
#property (strong, nonatomic) IBOutlet UIButton *privacyStatementButton;
#end
#implementation MYViewController
- (IBAction)licenseAgreementPressed:(id)sender
{
NSLog(#"Pressed A");
}
- (IBAction)legalDisclaimerPressed:(id)sender
{
NSLog(#"Pressed B");
}
- (IBAction)privacyStatementPressed:(id)sender
{
NSLog(#"Pressed C");
}
#end
Make sure you have made connection between IBAction(code) and UIButton(in xib) , please check this post How do I name and link an IBAction button created in a storyboard
Did you connect your actions to the elements in interface builder by control-dragging it?
If your actions are connected you will see a little filled out circle on the left of the line in your editor.
Check this tutorial for further information on how to connect your storyboard elements to your code.
It is because none of the buttons are inside the bounds of the license agreement view. A button outside its superview's bounds is untappable.
So the problem was the links, buttons, and text fields were not actually located within the bounds specified the parent views because the original .xib file didn't have the required constraints pinned to those elements. I discovered this by checking the "clip to bounds" checkbox in the Attributes Inspector pane. Whenever "clip to bounds" was checked, the app was NOT displaying any of the above view objects; I could only see links, buttons, and text fields when "clip to bounds" was unchecked but unfortunately, those elements were not clickable at that point. After setting the necessary constraints, however, the view elements were correctly placed within the bounds of their parent views and the text fields, labels, and buttons became clickable. I'm attaching the constraints that I used to fix the problem. Note: the constraints that are not expanded only include a height constraint.

iOS - Programatically add a new view to work with my storyboard autolayout viewcontroller

I am using Storyboards with autolayout where I have a viewcontroller full of views, buttons, labels, a table...
I want to create a new View at the top of this view, below the navigationbar, when a button is clicked, and hide it after clicking again over it.
I want to do this programatically. This means that this view will appear at the top and the rest of the views will have to move down the height of that new view. When this view disappears the views will move up again.
What'd be the best approach to do this? I've tried to create a view in the storyboard with height = 0 and change the height in code. Is there a better way for this?
Hi as you are using auto layout I would suggest taking an IBOutlet for the height constraint of the view that you want to put below the navigation bar and change it in code
Here is a sample
//IBOutlet for height constraint of view
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *conHeightTopView;
- (void)changeHeight:(BOOL)change{
if (change) {
_conHeightTopView.constant = 50;//Height of view when shown
}else{
_conHeightTopView.constant = 0;
}
}
All the views that need to be moved down should be put in one UIView. And your code should have an IBOutlet for this view.
When you create your new view programmatically, you will know it's height.
Now you can call setFrame of your first view and move it down.

Getting UIScrollView to work correctly on iPad

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

When will a control on a storyboard page be available to get frame info?

I'm using iOS 6 with storyboard and ARC.
I've got on my storyboard a UIView that I want to use for positioning and sizing - I've created an IBOutlet for the control in my controller via the Ctrl drag/drop so I know it's connected.
Now I want to try to reference this UIView from within the controller so I can dynamically create subviews within that UIView, positioned appropriately.
I'm trying to access the UIView from within viewDidLoad as follows
CGRect rect = self.myView.frame;
...but the rect is always coming up as 0, 0, 0, 0. myView is defined in the header file as:
#property (weak, nonatomic) IBOutlet UIView *myView;
I thought that all the controls from the storyboard would already be initialized when you got to viewDidLoad. If this is not the case, where should I put the code to use the frame of the UIView to create my subViews?
Thanks in advance.

How to assign my CustomNavigationBar to a UINavigationController?

In order to customize the aspect of the navigationBar of my UINavigationController, I've been told to subclass the UINavigationBar class.
I need to change the height of the bar, placing an image instead of the title.. etc. I can't do it just using UINavigationBar properties.
Now, my issue is, how to assign to the UINavigationController, my CustomNavigationBar instance ? I can't use UINavigationController.navigationBar because it is read-only.
The only way seems to load a xib, but subclassing UINavigationController is not reccomended by Apple, so I'm a bit confused.
Depending exactly on how custom you want the nav bar, the following may help you:
1) An image in the bar, replacing the title text. (self is a UIViewController)
UIImageView *titleImg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.png"]];
self.navigationItem.titleView = titleImg;
[titleImg release];
2) A totally custom nav bar
Subview UIView (CORRECTION: UINavigationController) with a nib, using (for example, of iPhone portrait orientation) a imageview as the background (could have a gradient) and then custom buttons on the left and right side, all hooked up to your relevant responder functions. As long as you add this nav bar view as a subview to each view controller etc each time a new one is pushed to the stack, you would have overriden Apple's standard nav bar. (remember to set theirs to hidden in the app delegate)
Edit:
NavigationBar.h
#interface NavigationBar: UIViewController
{
IBOutlet UIImageView* navigationBarImgView; // remember to set these 4 IBOutlets as properties with (nonatomic, retain) and synthesize them.
IBOutlet UILabel* controllerHeader;
IBOutlet UIButton* rightButton;
IBOutlet UIButton* leftButton;
eController controller;
int screenWidth;
}
NavigationBar.m
-(id)initNavigationBar: (NSString*)name bundle:(NSBundle*)bundle: (eController)controllerName: (int)inScreenWidth
{
[super initWithNibName:name bundle:bundle];
controller = controllerName;
screenWidth = isScreenWidth;
return self;
}
You can see my init here only passes in a few things - an enum which was defined in my app delegate which contains the names of all possible view controllers. We interpret this enum in my custom Navigation Bar class and switch between all the possible controllers, and then setup their buttons and titles and the actions that get fired off using that information. The screen width is important - although you may not need this if you create the bar in IB, set the size of it to fill up the allocated space for both orientations.
Keep me posted :)

Resources