Adding UITableView with autolayouts programmatically - ios

When I add UITableView programmatically and use Autolayouts, I usually write code like this:
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)
style:UITableViewStylePlain];
[self.view addSubview:self.tableView];
self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *views = #{#"tableView": self.tableView};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[tableView]|"
options:0
metrics:nil
views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[tableView|"
options:0
metrics:nil
views:views]];
The default initialiser for UITableView requires some CGRect to be positioned in, but when we use AutoLayout, there is no need to set frame programmatically.
Do I add the UITableView correctly?
Is there a way to avoid "dummy" CGRect?

try this
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero];

Related

Adding a subview to a view controller messes up with a table view

I have a UIViewController that has a UITableView as a subview. I want to add a background view under the table view but when I add it, the controller's edgesForExtendedLayout seem to be messed up
This is correct:
This is not correct:
My viewDidLoad method looks like this. If I do not add the subview, all looks ok.
- (void)viewDidLoad
{
[super viewDidLoad];
// UITableView
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:TAManeuvreCellId];
[self.view addSubview:self.tableView];
UIView *backgroundBlurView = [[UIView alloc] init];
// autolayout
backgroundBlurView.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *views = NSDictionaryOfVariableBindings(backgroundBlurView, _tableView);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_tableView]|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_tableView]|" options:0 metrics:nil views:views]];
// comment this and everything is ok
[self.view addSubview:backgroundBlurView];
[self.view sendSubviewToBack:backgroundBlurView];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[backgroundBlurView]|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[backgroundBlurView]|" options:0 metrics:nil views:views]];
}
I think the fix for this is setting:
self.navigationController.navigationBar.translucent = FALSE;
self.edgesForExtendedLayout = UIRectEdgeNone;
See:
How to prevent UINavigationBar from covering top of view in iOS 7?
iOS 7 UIImagePickerController navigationbar overlap

Set auto layout dynamically to scroll view in iOS

i am creating scroll view dynamically now i want to set auto layout for that
i implemented following code to set auto layout but its not working at all.
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title=#"Insta SMS Collection";
scrollView = [[UIScrollView alloc]initWithFrame:self.view.frame];
[self.view addSubview:scrollView];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *views = #{#"scrollView":scrollView};
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:
[scrollView]"
options:kNilOptions
metrics:nil
views:views;
[self.view addSubview:scrollView];
}
add horizontal and vertical autolayout.
[self.view addSubview:scrollView];
NSDictionary *dictScrollConst = NSDictionaryOfVariableBindings(scrlView);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[scrlView]|" options:0 metrics:nil views:dictScrollConst]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[scrlView]|" options:0 metrics:nil views:dictScrollConst]];
Maybe this will help you.

Adding a background imageview programmatically with autolayout

I need to add a background image view for my views for a project I've done using storyboards + autolayout. I want to add this image programmatically using code. so basically it should be from top layoutguide to bottom layoutguide, without going under them. I've tried few ways which failed horribly.
one way I first adjust the VC'c view before adding like this
id topGuide = self.topLayoutGuide;
UIView *superView = self.view;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings (superView, topGuide);
[self.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:[topGuide]-20-[superView]"
options:0
metrics:nil
views:viewsDictionary]
];
[self.view layoutSubviews];
but for some reason my imageview still goes under statusbar.
this is how I add the bg imageview
self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default"]];
self.backgroundView.contentMode = UIViewContentModeTop;
[self.view insertSubview:self.backgroundView atIndex:0];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[backgroundImageView]|" options:0 metrics:nil views:#{#"backgroundImageView":self.backgroundView}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[backgroundImageView]|" options:0 metrics:nil views:#{#"backgroundImageView":self.backgroundView}]];
Adding the constraint related to the topLayoutGuide to self.view is useless. The view controller layout its root view (self.view) independently from AutoLayout, and will override the constraints effects (don't quote me on this, this is an observation more than a real understanding of the layout system).
Instead, add the first constraint (#"V:[topGuide]-20-[superView]") to self.backgroundView:
self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default"]];
self.backgroundView.contentMode = UIViewContentModeTop;
[self.view insertSubview:self.backgroundView atIndex:0];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[topGuide]-(20)-[backgroundImageView]|" options:0 metrics:nil views:#{#"backgroundImageView":self.backgroundView, #"topGuide": self.topLayoutGuide}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[backgroundImageView]|" options:0 metrics:nil views:#{#"backgroundImageView":self.backgroundView}]];
[self.view layoutSubviews];

scrollView doesn't work even though contentSize is larger than frame and subview is added before setting content size

- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBar.translucent = YES;
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"sprites_0001_Rectangle-1.png"] forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.translucent = YES;
UIImageView *imageView = [[UIImageView alloc]init];
UIImage *image = [UIImage imageNamed:#"sprites_0000s_0008_1st-Page.png"];
imageView.image = image;
//imageView.translatesAutoresizingMaskIntoConstraints = NO;
imageView.backgroundColor = [UIColor clearColor];
self.view = imageView;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
//Write the code to set up view for iPad
}else{
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.backgroundColor = [UIColor clearColor];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:scrollView];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-40-[scrollView(==240)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(scrollView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-50-[scrollView(==468)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(scrollView)]];
UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"ParentsMock.png"]];
imageView.translatesAutoresizingMaskIntoConstraints = NO;
[scrollView addSubview:imageView];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[imageView(==1000)]|"
options:0
metrics:0
views:NSDictionaryOfVariableBindings(imageView)]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[imageView(==2000)]|"
options:0
metrics:0
views:NSDictionaryOfVariableBindings(imageView)]];
}
This is my attempt to create UIScrollView programmatically however I couldn't make the scrollView work even though I set the contentSize after adding the subview into the scrollView.
As you can see in this picture, I use UINavigationController to wrap a UIViewControllar and set UIImageView as its view. the I created a scrollView and add it on top of the view. then I create another imageView1 and insert it into the scrollView.
please note that the view of the entire view controller is an imageView which is different from the imageView i insert into the scrollView.
You should set your content size using constraints, ton by setting it directly. It does not scroll because you don't have constraints to the left, top, right or bottom of your scroll view content. See my answer here
Edit:
Try adding this:
imageView.translatesAutoresizingMaskIntoConstraints = NO;
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:
#"|[imageView(==1000)]|"
options:0
metrics:0
views:NSDictionaryOfVariableBindings(imageView)]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:
#"V:|[imageView(==2000)]|"
options:0
metrics:0
views:NSDictionaryOfVariableBindings(imageView)]];
and remove the code where you are setting the content size.
Edit:
Replace your entire code with this:
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.backgroundColor = [UIColor clearColor];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:scrollView];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-40-[scrollView(==240)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(scrollView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-50-[scrollView(==468)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(scrollView)]];
UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"ParentsMock.png"]];
imageView.translatesAutoresizingMaskIntoConstraints = NO;
[scrollView addSubview:imageView];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[imageView(==1000)]|"
options:0
metrics:0
views:NSDictionaryOfVariableBindings(imageView)]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[imageView(==2000)]|"
options:0
metrics:0
views:NSDictionaryOfVariableBindings(imageView)]];
The only way I have been successful in creating UIScrollViews is to use Autolayout. This is the simplest and most effective way I know. For this you will need to remove the
initWithFrame:CGRectMake(40, 100, 240, 168)];
Replace:
NSDictionary *layoutDic = ....
With:
NSDictionary *layoutDic = NSDictionaryOfVariableBindings(scrollView);
Edit: I use your code, and it works, I can scroll, I do in viewDidLoad
UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(40, 100, 240, 168)];
UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"purple_button.png"]];
[scrollView addSubview:imageView];
scrollView.contentSize = CGSizeMake(1000, 2000);
scrollView.backgroundColor = [UIColor clearColor];
scrollView.scrollEnabled = YES;
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *layoutDic = NSDictionaryOfVariableBindings(scrollView);
[self.view addSubview:scrollView];
NSArray *scrollViewConstraintWidth = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-40-[scrollView(==240)]" options:0 metrics:nil views:layoutDic];
NSArray *scrollViewConstraintHeight = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-50-[scrollView(==468)]" options:0 metrics:nil views:layoutDic];
[self.view addConstraints:scrollViewConstraintHeight];
[self.view addConstraints:scrollViewConstraintWidth];
in properties under Show the file inspector uncheck Use Auto Layout
Add the delegate to self like this:
UIScrollView *scrollView = [[UIScrollView alloc]init];
scrollView.delegate=self;
UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"ParentsMock.png"]];
[scrollView addSubview:imageView];
I found out the answer. It seems that I need to enable userInteraction on UIImageView. Remember when I use UIImageView as the view of the view controller. Therefore default value for userInteractionEnabled Property of UIImageView is NO. It ACCEPTS NO touches at all. We need we enable it like this
imageView.userInteractionEnabled = YES;
PROBLEM Solved.

Align two uiviews below each other using autoloayout

I am trying desperately to align two views below each other with autolayout hoping to animate them in the future and with a relative position this makes it more rigid than just setting frames and updating etc...
So the code:
// create two views
UIView *one = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
UIView *two = [[UIView alloc] initWithFrame:CGRectMake(0, 150, 50, 50)];
// add some color
[one setBackgroundColor:[UIColor whiteColor]];
[two setBackgroundColor:[UIColor redColor]];
// add them to self ( self = uiview )
[self addSubview:one];
[self addSubview:two];
// make dict
NSDictionary *views = NSDictionaryOfVariableBindings(one, two);
// add constraints to make the views as wide as the container ( self )
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[one]|"
options:0
metrics:nil
views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[two]|"
options:0
metrics:nil
views:views]];
// add constraint to make the second ( two ) item 10px below the first ( one )
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[one]-10-[two]"
options:0
metrics:nil
views:views]];
```
<-- the result
<-- the goal
What am i doing wrong?
Thanks in advance!
These two lines explain it all:
UIView *one = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
UIView *two = [[UIView alloc] initWithFrame:CGRectMake(0, 150, 50, 50)];
This is exactly what you are seeing as a result: both views are 50x50 in size, and view two is placed at x=0 and y=150.
When working with autolayout, you need to forget everything about frames and rects. State what constraints you want, for each view and between views, and let autolayout create the frames behind the scenes.
Declare views for autolayout like this:
UIView *one = [[UIView alloc] init];
one.translatesAutoresizingMaskIntoConstraints = NO;
UIView *two = [[UIView alloc] init];
two.translatesAutoresizingMaskIntoConstraints = NO;
You should not set frames while using constraints. That's what constraints are for. Constraints are the cause, frame is the effect
// create two views
UIView *one = [[UIView alloc] init];
UIView *two = [[UIView alloc] init];
one.translatesAutoresizingMaskIntoConstraints = NO;
two.translatesAutoresizingMaskIntoConstraints = NO;
// add some color
[one setBackgroundColor:[UIColor whiteColor]];
[two setBackgroundColor:[UIColor redColor]];
// add them to self ( self = uiview )
[self addSubview:one];
[self addSubview:two];
// make dict
NSDictionary *views = NSDictionaryOfVariableBindings(one, two);
// add constraints to make the views as wide as the container ( self )
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[one]|"
options:0
metrics:nil
views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[two]|"
options:0
metrics:nil
views:views]];
// add constraint to make the second ( two ) item 10px below the first ( one )
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[one]-10-[two]|"
options:0
metrics:nil
views:views]];
Note: I have changed a constraint in the last line. Your constraints did not specify the height of view two. It would have given you an "AMBIGUOUS" layout.

Resources