Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a tableview with cells containing text views as well as imageviews. My project is currently using AutoLayout. My goal is to get the imageview to display in fullscreen when it is tapped. One option is to use a modal view controller, but I want to have this work sort of like the way tapping on images in the facebook app works, the app centers the image and fades the background.

Since I'm using autolayout, I cannot simply set the frame of the imageview to fill the screen. Instead, I need to use autolayout constraints. My image view has 5 constraints, a constraint setting a distance from the bottom of the cell, as well as the left an right sides, and one controlling the image height. The last is a vertical space constraint between the textview above the image view and the top of the image. While this would appear to conflict with the height and bottom constraints, for some reason interface builder forces me to have this. To avoid problems, I set this constraint's priority to be less than 1000 (the image should never overlap the textview anyways, since the tableview cell height is set so everything will fit perfectly).

To center the image, I set the distance from the left and right to be zero and remove the vertical space constraint. In order to center the image, I replace the bottom space constraint with a center y alignment constraint to the UIWindow as opposed to the tableviewcell. I want to have it be in the center of the screen, not the cell.

To get the main window I use this:

AppDelegate* myDelegate = (((AppDelegate*) [UIApplication sharedApplication].delegate));
//access main window using myDelegate.window

Then, to set the constraint:

//currently sets the distance from the bottom of the cell to 14
//changing it...
[cellselected removeConstraint:cellselected.imagebottomspace];
cellselected.imagebottomspace = [NSLayoutConstraint constraintWithItem:cellselected.viewimage attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:myDelegate.window attribute:NSLayoutAttributeCenterY multiplier:0 constant:0];
[cellselected addConstraint:cellselected.imagebottomspace];

However, this doesn't work. The changes in the width and height of the image view apply just fine. However, when readding the imagebottomspace constraint, I get an unsatisfiable layout--apparently the constraint conflicts with another constraint which sets the distance between the bottom and the image view to 14, the very constraint I just removed. So it seems that it isn't actually removing the constraint.

When I proceed and let the app break a constraint, the imageview moves, but to the wrong place. It isn't centering in the screen. It moves way up and off the screen.

Obviously what I'm doing isn't right. What am I doing wrong?

share|improve this question
 
Is imageBottomspace an IBOutlet to a constraint you made in IB? Also, what behavior do you see -- is the bottom of the image staying where it was? –  rdelmar Jul 3 '13 at 5:03
 
@rdelmar see the changes I made in the code above. –  applepie Jul 3 '13 at 5:30
 
@rdelmar imageBottomspace is indeed an IBOutlet –  applepie Jul 3 '13 at 5:30
 
The multiplier on your centerY constraint should be 1, not 0. Also, I got weird effects (with the image view sometimes in front, and sometimes in back of the cells) unless I removed the image view from the cell, added the image view as a subview of the window, and added the centerY constraint to the window. –  rdelmar Jul 3 '13 at 5:37
 
@rdelmar hmm now I'm getting this "Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal." Guess I can't do it this way....tried removing the image view and adding it as a subview of the window, same error. I'm using a UITableViewController, so I guess the only other place I can put the image view is either the cell or the table view itself (and I don't think that would work either). Hmm.. –  applepie Jul 3 '13 at 6:09
show 1 more comment

1 Answer

up vote 4 down vote accepted

So I guess you want something like this:

zooming image view demo

First, you need to know that as of Xcode 4.6.3, the nib editor (“Interface Builder”) has a bug when setting up constraints in a table view cell. It should create the constraints between the subviews and the cell's content view, but instead it creates the constraints between the subviews and the cell itself. This tends to screw up layout at runtime.

The consequence of this is that you should either remove all of the constraints that were in the nib and recreate them in code, or just get rid of the nib and create the cell's entire view hierarchy in code.

Second, there's an easier way to do the image zooming. Here's the basic procedure when a cell is selected:

  1. Convert the selected cell's image view bounds to a CGRect in the top-level view's coordinate system.
  2. Create a new image view just for zooming and set its frame to that CGRect. Set its userInteractionEnabled to YES. Set its autoresizingMask to flexible width and height. Add a tap gesture recognizer.
  3. Add the new image view as a subview of the top-level view.
  4. Set the cell's image view's hidden property to YES.
  5. In an animation block, set the new image view's frame to the top-level view's bounds.
  6. Disable the table view's panGestureRecognizer.

When the new image view is tapped, reverse the procedure:

  1. Convert the selected cell's image view bounds to a CGRect in the top-level view's coordinate system.
  2. In an animation block, set the zoomed image view's frame to that CGRect.
  3. In the animation completion block:
    1. Remove the zoomed image view from its superview.
    2. Set the cell's image view's hidden property to NO.
    3. Enable the table view's panGestureRecognizer.

Since you're not moving the original image view, you don't have to mess with its constraints. Hidden views still participate in layout.

Since you're creating the new image view in code, it will have translatesAutoresizingMaskIntoConstraints set to YES by default. This means that you can just set its frame. Auto layout will automatically turn the frame into constraints.

You can find the full source code in this github repository.

share|improve this answer
 
thanks! this method is a much simpler and much more elegant than dealing with the constraints. –  applepie Jul 3 '13 at 22:52
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.