UIImageView inside a scrollView with screen rotation - objective-c

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)interfaceOrientat‌​ion{}
//ios 7
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrient‌​ation{}
duration:(NSTimeInterval)duration -
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOri‌​entation{}
//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];

Related

Animated UITableView doesn't respond to taps

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 ]];

Why doesn't contentView containing a label have any height in its scrollView in autolayout?

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 ]];

How to align UIImageView to the centre of the view controller?

I want an imageview to appear centre at the bottom,i added the imageview to another imageview in the view controller.the result is imageview is appearing at the bottom but not exactly at centre, can any one suggest what is wrong in my code?
-(void)viewWillAppear:(BOOL)animated
{
UIImageView *imgView=[[UIImageView alloc]init];
[imgView setTranslatesAutoresizingMaskIntoConstraints:NO];
UIImageView *mspimgvw=[[UIImageView alloc]init];
[mspimgvw setTranslatesAutoresizingMaskIntoConstraints:NO];
mspimgvw.image=[UIImage imageNamed:#"msplogo.jpg"];
[self.imgView addSubview:mspimgvw];
[self.view addSubview:imgView];
CGFloat bottom=0;
[imgView addConstraint:[NSLayoutConstraint constraintWithItem:mspimgvw attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:imgView attribute:NSLayoutAttributeBottom multiplier:1 constant:bottom-40]];
[imgView addConstraint:[NSLayoutConstraint constraintWithItem:mspimgvw attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:imgView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:bottom-40]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[imgView]|" options:0 metrics: 0 views:dicViews]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[imgView]|" options:0 metrics: 0 views:dicViews]];
}
I want image to appear to the centre of the view controller.What to change in my code?
Here you go:
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
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]];

Adding subview to tableview using autolayout

I was trying to add a subview to tableview using autolayout, but I get this Assertion failure when I do so.
" * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super.'"
My code
UIView *view = [[UIView alloc] init];
[view setBackgroundColor:[UIColor redColor]];
[parentView addSubview:view];
[view setTranslatesAutoresizingMaskIntoConstraints:NO];
NSLayoutConstraint *c1 = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0];
NSLayoutConstraint *c2 = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeLeft multiplier:0.0 constant:10.0];
NSLayoutConstraint *c3 = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0];
NSLayoutConstraint *c4 = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:50.0];
[parentView addConstraint:c1];
[parentView addConstraint:c3];
[parentView addConstraint:c2];
[parentView addConstraint:c1];
but if I set frame to the view without any autolayout constraint, it works fine.
I couldn't figure out what I am missing.

Positioning UIView in UIViewController using NSLayoutConstraints causes aliased UILabel?

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.