Tuesday, September 25, 2012

iOS - Hide settings below tableView

Recently I posted a question on StackOverflow, on how you could possibly hide the settings menu below a tableview and let it be uncover from the top as it is done in the actual AppShopper App for iPhone.

I got some hints on how this could be done, but at the end I had to program the overall solution by myself. I answered my question already there, so you could probably just take the code from there, but as I find it quite interesting, and it could be used also in other projects I prefer to have it here in my blog.

I just put both views on the controller in the storyboard (the views get created in order, so the last in the list will be on top when the controller is shown) one over the other. Then you need to define a trigger for the uncover/cover function, which could be either a button, or a slide gesture or whatever. This trigger then needs to perform the following code

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve: UIViewAnimationCurveEaseOut];
CGRect newFrame = self.newsTableView.frame;
newFrame.origin.y = newFrame.origin.y + self.subview.frame.size.height;
[self.subView1 setFrame:newFrame];
[UIView commitAnimations];

Maybe you need to adjust something else in your case, but more or less you should be done!

Monday, September 17, 2012

UILabel - Change Vertical Alignment

Lately I promised you more posts about my experience in iOS programming. Unexpectedly my company needs lots of iOS-apps so I had no time to share my new knowledge with you which I want to catch up right now starting with a problem I faced today.

The Xcode is a great environment to visually develop iOS apps, but like any other IDE it has some limitations. Today I tried to create a custom UITableViewCell containing some UILabels and UIImages. One of this labels should show two lines of text with truncated tail (with "..." as suffix).

Up to here no problem at all, as long as you are happy with the apple defined standard behaviour of multiline labels. In a usual label if the text does not cover both lines (perhaps it covers in portrait, but not in landscape) then the label shows just one line with centred vertical alignment. In most of the cases this could be an option, however it does not fit into the design for our app. U, like me probably think, that it should not be a problem to change the vertical alignment, however this behaviour is not easy to change.

I found some posts in which other developers suggest to use the sizeToFit method of the UILabel. Despite that, generally this would be a solution, in my case the label is contained into a UITableCellView which adds one more level of difficulty to the problem. In a UITable the Cells are not created for each data item, but reused several times and so it would reuse the resized label over and over again, and as I saw from several tests, even though I called sizeToFit after each assignment, the Label is not reset.

In other posts I found the hint, that I have to reset the frame to its initial size before calling sizeToFit, in order to have it working correctly. That's already the right way, but what's the size to set it to? The one defined in the storyboard? Close, but what if you have more than one storyboard?

The solution is to define the hight and width according to the autosized properties in the storyboard reduced by the number of remaining lines times the hight of a line. The latter needs to be calculated using the font and the font size.

    [cell.myLabel setText:[dataDictionary valueForKey:kMyLabel]];
    CGSize titleSize = [cell.
myLabel.text sizeWithFont:cell.myLabel.font constrainedToSize:CGSizeMake(cell.frame.size.width,40.0f) lineBreakMode:cell.myLabel.lineBreakMode];  
    //Adjust the label the the new height
    CGRect newFrame = cell.eventTitleLabel.frame;
    newFrame.size.height = titleSize.height;
    cell.myLabel.frame = newFrame;

The code is quite self explaining, except maybe the "40.0f". This value is just saying tht in my case the height of the Label should be limited to 2 lines in my case. This could be improved by dynamically calculate the size of one row times the lines you want to display.

That's more or less the same solution I came up with implemented in a Category, which makes it simple and reusable.