Sebastian Suchanowski Programmer's notes

27Nov/130

Autolayout without coding – UIScrollView (ambiguous scrollable content height)

Recently while doing application upgrade to iOS7 I’ve encountered few issues with autolayout machanism and I want to share with you one in particular. I hope that will help you make your app ‘responsive’ :) and you could solve the ambiguous scrollable content height issue without writing any code.

Let’s go back in history, we had an app called iDoc24 and after iOS7 was greatly adopted I had to start putting all things aside and prepare update with new style. Here how the main menu looked back then and what was the result of upgrading.

On the left we have a first version. Let’s leave the discussion if the tab bar should be used there – assume that this is the result that we want to achieve. Now – as you could imagine we have two simple (there are more but those are obvious) ways to do it:

  • Three static buttons,
  • TableView with custom cells.

I went there with table view – why? I like it for first, secondly is was easy to ajust to 4 inch iphoned in the era before autolayout and the most important – it gives me bouncing out of the box, yeah! Later on I’ve added some hidden action after pulling the menu but let’s not go there now and focus on the job. Why I’ve stated that bouncing was most important here? It’s simple – I’ve seen have people were using the apps and most of them are not only do the thing that it was designed to do but they are playing with it. I don’t like those apps with static views because bouncing work on iOS better than on any other platform I wanted to take advanted from it. Seriosly, every person that I’ve seen playing with the app enjoyed dragging the menu up and down – which is why I’ve made all views behieve that way – it give an impression that app is kinda living its life.

Ok, now let’s go to the future – second screen shows my end result. After we removed one of menu and deployment target was set to iOS7 I started to wondering if I still want table view there. I’ve decided to do it without help of the tables for couple of reasons:

  • I wanted to play with autolayout and learn it very good so I’ve made all the views works great in landscape mode although I didn’t need it :p
  • a part of my plan for upgrading to iOS7 was getting rid of unnecessary code, adding cocoapods, really serious refactoring and even make the app ready to go if Apple have launch device with different dimentions to what we have right now,
  • if I ever heard that somebody is using the table view just to replace two buttons I’d think that he is crazy.

Start

Our goal here is to achieve to make new autolayout version work as well as iOS6 version and remove code from tableview delegate as well make it work for lanscape mode. Let’s make some assumptions:

  • we don’t know app (device) width or height,
  • bottom menu has static height

…that’s all!

During next steps I will guide you right to the solution that worked for me, making only some comments about what I did before going there and what didn’t work for me.

First of all we have to create proper hierarchy:

Look at the screencast below the get the idea (I did it using Reveal app – could be useful sometimes)

Now let’s go though it and explain:

  • Top most view: Container view – placed there by default
  • First view: this is my helper view for getting the right size – I will be refering to it later on
  • Second view: bottom menu
  • Scroll view: center menu (Send & See Your Case)
  • View: container for two menu views (you may think that this is a little redundant but the way that scroll view works now with autolayout made me do this
  • Two views with some labels and images

Now let’s focus on the constraints going from the inside. I will omit here the values for the labels and images and try to explain more important things.

Scroll view automatically sets content size for itself (while using autolayout) but we don’t know the actual dimentions here so what we do is we place the view insinde scroll view – this will keep all together, inside this view we have two menu views and the constraints here will be:

This will make sure there are glued to both edges

  • Leading space to container view equals 0
  • Trailing space to container view equals 0

We don’t know actual hight so we have to make sure that both view will be same hight and each will be on the right position

  • Equal hights (top to bottom view)
  • Top space to container view equals 0 (for top one)
  • Bottom space to container view equals 0 (for bottom one)

This looks quite done, now we go higher and deal with container view for menu items and make sure that it will fill precisely the parent scroll view. To do this I’ve normaly set

  • Leading space to container view equals 0
  • Trailing space to container view equals 0
  • Top space to container view equals 0
  • Bottom space to container view equals 0

WRONG!

Looks legit but what I did end up here (assuming done all other steps) with is properly working scroll view but messed up when going to landscape mode – scroll kept the width from the portait mode and moreover the scroll view doesn’t have idea what size it should be so if you set the width and height for start then it will run – but it won’t resize.

This is why I’ve added the as I called it helper view so I could get the right dimentions. This view is the most back view so I won’t mess anything and other view in front of it has an opaque set to YES. The sole purpose of helper view is get for me the height of current view from top down to bottom menu. So I’ve added:

  • Leading space to container view equals 0
  • Trailing space to container view equals 0
  • Top space to container view equals 0
  • Bottom space to bottom menu view equals 0

Important here is to select checkbox Bounce Vertically which will enforce scroll view to bounce wherever the content height will be.

Having the right hight for the menu items we are going back to menu items container view and fixe the badly shapped constraints:

  • Leading space to container view equals 0
  • Trailing space to container view equals 0
  • Top space to container view equals 0
  • Bottom space to container view equals 0
  • Equal hights (container view to helper view)
  • Equal widths (container view to helper view)

And because scroll view was still messed up – it didn’t change the width on landscape mde. I’ve added spaces to the helper view which was sure to resize on any state

  • Leading space to helper view equals 0
  • Trailing space to helper view equals 0
  • Top space to helper view equals 0
  • Bottom space to helper view equals 0

Thanks to all this I could rotate my menu and keep it looking slick. All this ended up behaving like table view – just what I wanted. The end result with

Share!
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

(required)

No trackbacks yet.