I'm animating a UITableView into view when a UIView is tapped, like a drop down menu. It's fully visible, all cells are there, and the tableview's delegate and datasource are set. For some reason it doesn't respond to taps on any cells. Any ideas?
_tableView = [UITableView new];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
_tableView.backgroundColor = [UIColor yellowColor];
_tableView.rowHeight = kMenuCellHeight;
_tableView.allowsSelection = YES;
_tableView.dataSource = self;
_tableView.delegate = self;
_tableView.bounces = YES;
_tableView.tableHeaderView = nil;
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"MenuCell"];
[self insertSubview:_tableView belowSubview:_blankView];
_menuHeight = 4 * kMenuCellHeight;
_tableTopConstraint = [NSLayoutConstraint constraintWithItem:_tableView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_blankView attribute:NSLayoutAttributeBottom multiplier:1 constant:-_menuHeight];
NSLayoutConstraint *tableLeading = [NSLayoutConstraint constraintWithItem:_tableView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:levelView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *tableTrailing = [NSLayoutConstraint constraintWithItem:_tableView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:levelView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
NSLayoutConstraint *tableHeight = [NSLayoutConstraint constraintWithItem:_tableView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:_menuHeight];
[_tableView addConstraint:tableHeight];
[self addConstraints:#[ _tableTopConstraint, tableTrailing, tableLeading ]];
Related
I have Created Two UIView one headerview and second is UICollectionView both subview of UIScrollView and I have hidden my NavigationBar entire app.
Now I have added below code for set "SafeAreaLayoutGuides" in iOS11 but here application crass due to superview nil found.
I have added below code.
UIView *parentView = self.view.superview;
UIView *childView = scrollViewMain.superview;
childView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *topConstraint;
NSLayoutConstraint *bottomConstraint;
if (#available(iOS 11, *)) {
topConstraint = [NSLayoutConstraint constraintWithItem:childView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:parentView.safeAreaLayoutGuide attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
bottomConstraint = [NSLayoutConstraint constraintWithItem:childView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:parentView.safeAreaLayoutGuide attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
} else {
topConstraint = [NSLayoutConstraint constraintWithItem:childView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
bottomConstraint = [NSLayoutConstraint constraintWithItem:childView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
}
[parentView addConstraint:topConstraint];
[parentView addConstraint:bottomConstraint];
If parentView is nil (because self.view.superview is nil), then that means that self.view hasn't been added to the view hierarchy yet.
Make sure that whatever view contains this one has called self.addSubview(childView); that'll fix the "nil superview" issue.
Its been 2 days working on this problem and i just can't figure it out.
I have a UIScrollView stretched in all my view and i am adding to it as subViews a random number of UIImageViews, and i am enabling paging so it will look like a gallery app.
My problem is when i rotate the screen, the images frames stays the same (this is probably because of the constraints) so i tried to give the images constraints and it worked they would rotate perfectly but then a problem appeared where the scroll view wont scroll anymore and the images are on top of each other ..
This is my code :
-(void)setupScrollView
{
for(int i = 0 ; i < [_arrayOfImages count] ; i++)
{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.frame.size.width*i, 0, self.view.frame.size.width, self.view.frame.size.height)];
[imageView setImage:[[_arrayOfImages objectAtIndex:i] getImageForImageView:imageView]];
[imageView setUserInteractionEnabled:YES];
[imageView setContentMode:UIViewContentModeScaleAspectFit];
[imageView setTranslatesAutoresizingMaskIntoConstraints:NO];
[_scrollView addSubview:imageView];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.f constant:0.f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1.f constant:0.f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]];
}
[_scrollView setContentSize:CGSizeMake(self.view.frame.size.width*[_arrayOfImages count], self.view.frame.size.height)];
}
Can anyone help me please ? thanks
You need to change the frame of UIScrollView and the UIImageViews in Autorotate delegate methods. After that you have to change the ContentSize of UIScrollView.
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{}
//ios 7
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{}
duration:(NSTimeInterval)duration -
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{}
//ios 8
-(void)viewWillTransitionToSize:(CGSize)size
withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator{
if (size.width > size.height) {
// Positions for Landscape
} else {
// Positions for Portrait
}
}
I'am not really sure, because I need to see all application, but you can try following code
-(void)setupScrollView
{
for(int i = 0 ; i < [_arrayOfImages count] ; i++)
{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.frame.size.width*i, 0, self.view.frame.size.width, self.view.frame.size.height)];
[imageView setImage:[[_arrayOfImages objectAtIndex:i] getImageForImageView:imageView]];
[imageView setUserInteractionEnabled:YES];
[imageView setContentMode:UIViewContentModeScaleAspectFit];
[imageView setTranslatesAutoresizingMaskIntoConstraints:NO];
[_scrollView addSubview:imageView];
[imageViewArray addObject:imageView]
if (i == 0) {
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.f constant:0.f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1.f constant:0.f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]];
} else {
UIImageView * previousView = [imageViewArray objectAtIndex:i-1];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:previousView attribute:NSLayoutAttributeLeading multiplier:1.f constant:0.f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:previousView attribute:NSLayoutAttributeTrailing multiplier:1.f constant:0.f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:previousView attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:previousView attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]];
}
}
[_scrollView setContentSize:CGSizeMake(self.view.frame.size.width*[_arrayOfImages count], self.view.frame.size.height)];
}
Also, you need to declare imageViewArray as NSMutableArray:
add to #interface:
NSMutableArray * imageViewArray;
and in viewDidLoad:
imageViewArray = [[NSMutableArray alloc] init];
I am trying to add a gray uiview overlay using autolayouts so that when you rotate the device it automatically still covers the entire screen. How would this be done programatically?
It is easy, you need 4 constraints to do that - top, bottom, left and right:
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f];
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f];
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f];
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeRight multiplier:1.0f constant:0.0f];
Try this:
UIView *greyView = [UIView new];
[self.view addSubview:greyView];
greyView.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *viewDictionary = #{#“greyView”:greyView};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[myView]-0-|“ options:0 metrics:nil views:viewDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#“H:|-0-[myView0]-0-|” options:0 metrics:nil views:viewDictionary]];
I'm creating a scrollView and adding a contentView to it using autolayout. The contentView's height I thought would be determined by the height and constraints of its contents. Since it has a label, shouldn't the contentView's height equal the label height? Only way height exists (in blue in the snapshot) is if adding a height constraint to the contentView. I thought this would be unnecessary since autolayout should know the heights of labels from their intrinsic content size?
.
// Scrollview
_scrollView = [UIScrollView new];
_scrollView.translatesAutoresizingMaskIntoConstraints = NO;
_scrollView.backgroundColor = [UIColor yellowColor];
_scrollView.bounces = YES;
[self.view addSubview:_scrollView];
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_scrollView]|" options:0 metrics:0 views:#{ #"_scrollView" : _scrollView }];
NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_scrollView]|" options:0 metrics:0 views:#{ #"_scrollView" : _scrollView }];
[self.view addConstraints:horizontalConstraints];
[self.view addConstraints:verticalConstraints];
// Content view
_contentView = [UIView new];
_contentView.translatesAutoresizingMaskIntoConstraints = NO;
_contentView.backgroundColor = [UIColor blueColor];
[_scrollView addSubview:_contentView];
NSArray *horizontalContentConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_contentView]|" options:0 metrics:0 views:#{ #"_contentView" : _contentView }];
NSArray *verticalContentConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_contentView]|" options:0 metrics:0 views:#{ #"_contentView" : _contentView }];
[_scrollView addConstraints:horizontalContentConstraints];
[_scrollView addConstraints:verticalContentConstraints];
// Why does height of content view need to be added to get the blue area to show?
NSLayoutConstraint *contentViewHeight = [NSLayoutConstraint constraintWithItem:_contentView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:NSLayoutAttributeNotAnAttribute attribute:NSLayoutAttributeHeight multiplier:1 constant:5];
[_contentView addConstraint:contentViewHeight];
NSLayoutConstraint *contentViewOuterLeading = [NSLayoutConstraint constraintWithItem:_contentView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *contentViewOuterTrailing = [NSLayoutConstraint constraintWithItem:_contentView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
[self.view addConstraints:#[ contentViewOuterLeading, contentViewOuterTrailing ]];
// Day label
_dayLabel = [UILabel new];
_dayLabel.translatesAutoresizingMaskIntoConstraints = NO;
_dayLabel.text = #"Monday";
_dayLabel.backgroundColor = [UIColor greenColor];
[_contentView addSubview:_dayLabel];
NSLayoutConstraint *dayLabelTop = [NSLayoutConstraint constraintWithItem:_dayLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
NSLayoutConstraint *dayLabelCenterX = [NSLayoutConstraint constraintWithItem:_dayLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_contentView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
[_contentView addConstraints: #[ dayLabelTop, dayLabelCenterX ]];
It's because a UIScrollView has a content size of (0,0).
You can say it's bounds should be flush with the superview, but that's not actually changing its contentSize. Additionally, you add the contentView, but again you're saying it should be flush with its superview (the scrollview) though since the scroll view's size is still (0,0), you're implicitly saying that the content's view size will be 0,0. It's only after you add a constraint that specifically says 5px do you actually see a bit of the view.
A scroll view will get it's appropriate size from it's contents, so if you instantiated the content view as:
UIView * contentView = [[UIView alloc] initWithFrame:[UIScreen mainscreen].bounds];
The scroll view's content size would be equal to [UIScreen mainscreen].bounds and you would still be satisfying the layout constraints you write.
As you add UI elements to uiscrollview, and arrange them via layout constraints, the scrollview will automatically expand as needed.
I wrote a blog post exactly on this subject, Programmatic ScrollViews w/ NSLayout ... you may have too look at an older commit to it, but I ran into this exact same issue.
Ok figured it out. Adding a constraint from contentView to the bottom of its label made it work. No height constraint is needed for the contentView. Here's the updated code:
// Scrollview
_scrollView = [UIScrollView new];
_scrollView.translatesAutoresizingMaskIntoConstraints = NO;
_scrollView.backgroundColor = [UIColor yellowColor];
_scrollView.alwaysBounceVertical = YES;
[self.view addSubview:_scrollView];
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_scrollView]|" options:0 metrics:0 views:#{ #"_scrollView" : _scrollView }];
NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_scrollView]|" options:0 metrics:0 views:#{ #"_scrollView" : _scrollView }];
[self.view addConstraints:horizontalConstraints];
[self.view addConstraints:verticalConstraints];
// Content view
_contentView = [UIView new];
_contentView.translatesAutoresizingMaskIntoConstraints = NO;
_contentView.backgroundColor = [UIColor blueColor];
[_scrollView addSubview:_contentView];
NSArray *horizontalContentConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_contentView]|" options:0 metrics:0 views:#{ #"_contentView" : _contentView }];
NSArray *verticalContentConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_contentView]|" options:0 metrics:0 views:#{ #"_contentView" : _contentView }];
[_scrollView addConstraints:horizontalContentConstraints];
[_scrollView addConstraints:verticalContentConstraints];
NSLayoutConstraint *contentViewOuterLeading = [NSLayoutConstraint constraintWithItem:_contentView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *contentViewOuterTrailing = [NSLayoutConstraint constraintWithItem:_contentView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
[self.view addConstraints:#[ contentViewOuterLeading, contentViewOuterTrailing ]];
// Day label
_dayLabel = [UILabel new];
_dayLabel.translatesAutoresizingMaskIntoConstraints = NO;
_dayLabel.text = #"Monday";
_dayLabel.backgroundColor = [UIColor greenColor];
[_contentView addSubview:_dayLabel];
NSLayoutConstraint *dayLabelTop = [NSLayoutConstraint constraintWithItem:_dayLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
NSLayoutConstraint *dayLabelCenterX = [NSLayoutConstraint constraintWithItem:_dayLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_contentView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
NSLayoutConstraint *dayLabelBottom = [NSLayoutConstraint constraintWithItem:_dayLabel attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_contentView attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
[_contentView addConstraints: #[ dayLabelTop, dayLabelCenterX, dayLabelBottom ]];
I'm trying to manually animate in a UIView, contained in a UIViewController, from the top of the screen. This view will have a height of 150px.
I setup layout constraints for when it's "collapsed" and when it's "expanded" (shown). I animate between the two constraints when I want to hide/show, respectively.
I setup the view contained in this UIViewController in IB with a simple UILabel in the upper-left of the view.
CGFloat closeUpViewHeight = 150.f;
self.closeUpViewController = [[[CloseUpViewController_Phone alloc] initWithNibName:#"CloseUpViewController_Phone"
bundle:nil]
autorelease];
[self addChildViewController:self.closeUpViewController];
[self.view addSubview:self.closeUpViewController.view];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.closeUpViewController.view
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeHeight
multiplier:0.f
constant:closeUpViewHeight]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.closeUpViewController.view
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:1.f
constant:0.f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.closeUpViewController.view
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.f
constant:0.f]];
self.expandedCloseUpViewConstraint = [NSLayoutConstraint constraintWithItem:self.closeUpViewController.view
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:0.f
constant:0.f];
self.collapsedCloseUpViewConstraint = [NSLayoutConstraint constraintWithItem:self.closeUpViewController.view
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.f
constant:-1.f];
Anyone know why the resulting UILabel has aliasing problems?
Fixed my problem, pretty dumb mistake.
Inside the setup for my view controller, I added a drop shadow to the UIView and accidentally had carried over this:
self.view.layer.masksToBounds = NO;
self.view.layer.shadowOffset = CGSizeMake(0, 2);
self.view.layer.shadowRadius = 3;
self.view.layer.shadowOpacity = 0.8;
self.view.layer.shouldRasterize = YES; //<--- Don't rasterize.
Removing the shouldRasterize line fixes the issue here.