How to reposition UILabels and UIImageViews whose dimensions change dynamically? - iphone

I have a UITableView with many rows that push a DetailViewController depending on the selection. This detail view contains a UIImageView, and several UILabels (let's say book description, book comments etc). In viewWillAppear I assign the proper content to these outlets, in order to display content for the selected row. My problem is that the text might be one sentence, or a couple of paragraphs. So, if I have one outlet for book description and one other for book comments, how am I supposed to position these components properly, so that their horizontal distance is always the same? I thought of creating a UIWebView and load there dynamically generated HTML, but there has to be a cleaner way, right??
Here is a visual something if that helps :)
------------------------------
| Description |
| [multiple lines go here] |
| |
| [Image] |
| |
| Comments |
| [multiple lines go here] |
------------------------------

When you layout your UITableView, If you're using UILabels for the description and comments you can figure out the size with something like this:
CGSize labelSize = [nameLabel.text sizeWithFont: nameLabel.font
constrainedToSize: CGSizeMake( actualWidth, MAXFLOAT )
lineBreakMode: UILineBreakModeWordWrap];
Once you know the height for Description lets say, you can position the UIImageView appropriately using CGRect, etc, etc. Then calculate the height of the UITableView row with something like this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

Create a custom view class and perform layout in -layoutSubviews using -sizeThatFits: and -sizeToFit.
Layout code does not belong in the view controller.

Related

UIScrollview not working with Storyboard

Hello I'm trying to setup a scrollview in the storyboard and followed the following steps to do it:
add a scrollview to the root view.
pin zero spaces to all edges of super view.
add a UIView (contentView) to the above scrollview.
pin zero spaces to all edges of the scrollview add some widgets to
contentView and change the height of the contentView to 2000.
I saw this solution is working on many tutorials I saw but not its not working on me. What am I doing wrong? I use swift.
Can someone explain step by step how do to set up a scrollview in the storyboard?
My constrains:
OK, let's imagine a the following view hierarchy (note, looking at constraints in Interface Builder are easier if you give those views unique names in the "Document" section of the "Identity Inspector"):
To set that up, you'd add the following constraints in IB (I'm justing going to write it in VFL, because it's a very concise way of showing the constraints):
Obviously, define scroll view relative to its superview (the main view, in this example):
H:|[scrollView]|
V:|[scrollView]|
Define, contentView such that
It's width is the same as the main view (==view), and
The scroll view's contentSize will change to fit the size of the contentView. Per TN2154, the constraints between a scrollview and its subviews defines the contentSize of the scroll view, not the relative size of the subviews.
Thus:
H:|[contentView(==view)]|
V:|[contentView]|
Define the layout for three labels such that they're offset within the contentView:
H:|-[label1]-|
H:|-[label2]-|
H:|-[label3]-|
Rather than hardcoding the height of the contentView (and thus the contentSize of the scroll view, instead just define the label's relationship to the vertical height of the contentView, which (because of step 2, above), adjusts the vertical height of the contentSize of the scroll view:
V:|-[label1]-[label2]-[label3]-|
This is all you need to do. I didn't hardcode any widths (the main view has a width automatically, and both the scroll view and, more importantly, the contentView define their widths related to that. But the label widths are inset from the contentView, and the contentView height (and thus the scroll view's contentSize) is inferred from the intrinsic height of the three labels.
The end result is constraints in IB that look like:
FYI, if you want to do some diagnostics, you can click on the view debug button while the app is running on the simulator:
You can see the view (and optionally the constraints) and make sure everything looks ok:
You can also look at the _autolayoutTrace via the (lldb) prompt:
(lldb) po [[UIWindow keyWindow] _autolayoutTrace]
UIWindow:0x7fbbb3617910
| •UIView:0x7fbbb349a840
| | *UIScrollView:0x7fbbb3491c80
| | | *UIView:0x7fbbb348e180
| | | | *UILabel:0x7fbbb348e450'Label'
| | | | *UILabel:0x7fbbb3490670'Label'
| | | | *UILabel:0x7fbbb3490a70'Label'
| | | UIImageView:0x7fbbb34a3eb0
| | | UIImageView:0x7fbbb34a3800
| | *_UILayoutGuide:0x7fbbb349a970
| | *_UILayoutGuide:0x7fbbb349b460
This confirms that there are no conflicting layouts and that there are no ambiguous layouts.

How to achieve an advanced table view header

I have a grouped UITableView. Now unlike the default table view header my header should be next to the individual cells:
Standard:
[Header Cell]
[Item 1]
[Item 2]
What I need
+-------+----------------+
| | Item 1a |
| h1 +----------------+
| | Item 1b |
+ - - - +----------------+
| Item 1c |
+------------------------+
| | Item 2a |
| h2 +----------------+
| | Item 2b |
+------------------------+
| | Item 3a |
| h3 +----------------+
| | -placeholder- |
+-------+----------------+
Some remarks:
Group H1 has three items
Group H2 has two items
Group H3 has just one item (I have to insert a placeholder cell so that the header cell can have the full height of two item-cells
When the user scrolls the list then the header should be pushed upwards that the two header-cells don't overlap.
The challenge here is the height of the header cell:
If I set the height to 0 and uncheck clip subviews then that header cell is shown but does not get pushed away at the correct position.
If I set the height of the header cell to the visual height then there is an empty space of that height across the whole width of the table which I don't want...
Update 1: I just realized that apple uses such a list for the search (grouped by messages, mails, contacts, calenders etc.). So my question basically is how can I tweak UITableView in order to behave like the grouped search results... :-)
(source: mshcdn.com)
Update: I created a project on github, which does exactly this. I have extracted all the relevant code for the behaviour into two classes (BBFloatingHeaderViewController & BBFloatingHeaderCell). There is also an example project. I hope this is useful for others :-)
Here's the project: besi/FloatingTableViewHeader
This is an excerpt from the readme:
Floating UITableView headers
These classes aim to copy the behaviour found in iOS built-in Spotlight search, where the search results are grouped by category and the icon of the respective category floats on the left side of the search results.
Setup
Check out the example project so see how to setup the classes.
Add the .m + .h files of BBFloatingHeaderViewController and BBFloatingHeaderCell to your project.
Create a TableView and set the Class of the ViewController to your subclass of BBFloatingHeaderViewController
Create the header cell in IB and set its class to your subclass of BBFloatingHeaderCell
Make sure that your floating header view is the topmost view in the BBFloatingHeaderCell's view hierarchy.
The result
Floating Headers http://i.minus.com/jyea3I5qbUdoQ.png

IB Custom UITableViewCell - Dynamic Height for cell and detailText

Im trying to create a table very similar to the Messages table,
It requires 3 labels,
- Title
- detailText
- Time (on the far right side)
The detail text needs to be dynamic height and so does the actual tableViewCell
is it possible to make a dynamic height tableViewCell in IB?
Yes you can,
Just use this method to of the UITableViewDelegate
tableView:heightForRowAtIndexPath:
First, you need some NSString method to calculate the height of cell it needs. And in my experience, you need the tableView:heightForRowAtIndexPath as Cyprian said, and under different cell height, the cell returned from tableView:cellForRowAtIndexPath: should have different layout too, to present the multi-line strings.

UITableView change first upper/lower unused cell

Is it possible to modify the first "cell" under/over the "real" content?
Imagine this as the content or structure:
#0:[]
#1:[]
#2:[]
#3:[]
#4:[]
In this case, I would want to modify the cells with the number -1 and 5. But this should not affect the behaviour of the scrollbar. (e.g. not extending the scrollable content)
Thanks in advance
EDIT: Take a look at the facebook-refresh-cell. (Pull down the UITableView)
If I understand it correctly, you want to change the content of cells off-screen.
You actually don't want to change the cells themselves, but rather, you want to change the underlying data model that provides the cells with their data. You can, of course, do this at any time.
You shouldn't be trying to get at the UITableCell objects themselves.
Hi
Instead of trying to modify the cells, just create your own Footer and Header cells and put everything you need there, it will always stay there without modifying the actual data cells
Look into
(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *view = [[[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 30)] autorelease];
view.backgroundColor = [UIColor redColor];
return view;
}
you can do the same for Footer view just change the viewForHeaderInSection to viewForFooterInSection

How can i have more than one cell in a table view row?

I have seen apps that have table views that have rows that contain 2 or 3 cells. Something like the following:
| 3 cells in one row |
/-------\ /-------\ /-------\
|do this| | do | |do smth| <--- table view row that contains 3 cells
| | | that | | else |
\-------/ \-------/ \-------/
When you click on a cell they behave exactly like a cell and have different events. Is there a simple way to do this or do I have to use some trick.
Those aren't actually separate cells. A UITableView can only contain rows, not columns. But each cell can be laid out with its content in three equal-sized areas, thereby mimicking a real grid of content.
If they don't have to look like cells, I would use 3 Buttons in a custom UITableViewCell. They also get blue if you tap on them.
Adding buttons and then using the code from here seems to be the easiest way. Although the initWithFrame:CGRectZero looks hacky, it works.