Is there a way to expand/contract UITableViewCells on the fly? - iphone

I would like to have a custom UITableViewCell that displays limited data while unselected, but then expand to show more details when selected.
The issue I have is how do I adjust the size of the cell during a select/deselect event?

Make a sub-class of UITableViewCell, and override the drawRect() method.
In your view controller's didSelectRowAtIndexPath, you can switch between the contracted and expanded states. You can change frame sizes, add or remove sub-views, add more data, whatever you need to do.

I was doing it not so long ago. To adjust the size you need to make UITableView call heightForRowAtIndexPath again. It will cause redrawing of cell. Use
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
in order to do that. If you set animation to YES it will nicely animate expanding of your cell. Also to adjust cell, setSelected: in your UITableViewCell subclass may be helpfull.

Related

How can I replace `UITableViewCell` with a `UIScrollView` or `UITableView` after the main `UITableView` is already loaded?

So I am messing around with how this feels in my app. I have a UITableView and I have the swiping/panning in place, where I kind of flick the cell away and once the cell is away I have it call a method in the same class where I have my UITableView as a property. Once that cell is swiped away and that method gets called, I want to animate the size of the now empty cell to be about 3 times the size of the cell and have a UIScrollView or UITableView be added. It will be a place to store all comments about that cell.
Basically, I would just like some ideas on how I can replace a swiped cell with a UIScrollView or UITableView and animate it to three times the size of any cell.
In a nutshell, if the text below is tl;dr:
call reloadRowsAtIndexPaths, remember which cell you've changed, update cellForRowAtIndexPath and heightForRowAtIndexPath accordingly, and you are set to go.
Full version:
When you said swiped away, did you meant that you are reloading or deleting certain row of your UITableView?
If so, I think you might be able to do what you described by calling [tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationLeft]; (or whatever direction you'd like), then saving the indexPaths you've changed (in your case only one indexPath), and react appropriately in the cellForRowAtIndexPath dataSource method - changing the normal cell for another one, custom-made, with UITableView or UIScrollView inside, and also reacting in the heightForRowAtIndexPath delegate method, to change the height.
The animation itself will be handled by tableView, so that's an ease for you.
Also, if you will use this method to change the contents of the cell for UITableView, don't forget to assign delegate and dataSource of that cell's new tableView, since that causes lot of troubles when forgot.

UITextView in UITableViewCell subclass, how to keep the data separate from the view

So I don't know what the best way to follow MVC is. Similar to the address books app, I want to have a UITableVeiewcell that has the ability to edit notes. I figured I would do that with a UITextView in a UITableViewCell subclass. My subclass has just that as a property, and a label that says "notes". I can see a few use cases that I need to consider,
1) when they are done editing and click outside or hit return.
2) when the text goes beyond the size of the cell I need to resize the cell.
Because my UITextView is in IB, is there a good way to define the delegate methods for the UITextView since my UITableView is in another ViewController subclass? Like how do I pass that information back?
Or, is it better to create my UITableViewCell subclass in code since it's just a couple of items so all my delegate and resizing code is done in the view controller class?
Thanks!
After text field editing was finished, you can store it's value in some dictionary in your controller. You can use cell's indexPath as key in this dictionary. In such way you will not lose your data with dequeue cells.
To resize cell you must call reloadData method and change rowHeight property of entire tableView or implement tableView:heightForRowAtIndexPath: delegate method to set needed row height to current cell.
I haven't use UIKit since iOS 3.1, so the second part of my answer can be out of date, but I hope it will help you =)

Animated change of uitableviewcell height and toggle of contents

I have a tableview with UiTableViewCells from a XIB and I want to animate a change of cell height when selected and showing/hiding some elements.
Now, for the animated change of height there's no problems, I've done it with the tutorial in this answer .
The problem is how to toggle some elements!
I can't figure out how to solve this problem! Putting on the xib the elements, they cover the cell above; by code I can't find a method to call when a cell is opened and the animation i finished!
Any ideas?
Thanks to all!
There may be an easier way than this, but one way would be instead of changing the cell height and adding the new components in the animation block, set a flag for that row that it should be expanded then in your animation block call
[tableview reloadData]
And in your
heightForRowAtIndexPath
method return the new cell height and in the
cellForRowAtIndexPath
method of your delegate return the new version of the cell with the additional elements.

Decrease UITableViewCell width and put custom button on the left

Is there any way to decrease the standard width of grouped UITableViewCell and put a custom button on the left side(outside of cell boundary)? I tried to change the cell size but it keeps same
You are going to have to fake the editing mode.
What I mean by that is that as AtomRiot said you have to subclass UITableViewCell so that when in editing mode you show the button you want on the left, outside the cell.
But first things first.
To change the indentation level for your cells all you need to do is implement this delegate method for the UITableView
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
So that takes care of it. Then in your UITableViewCell subclass all I would do is to implement the method
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
which I assume is called when the table the cell belongs to has changed to editing mode.
There I would fade in (or animate in any way you want) a button to appear on the left of your cell.
I have done it inside a grouped-style cell but never on the outside.
Give it a try!
You could subclass UITableCell and add your own custom views inside of it. I have not personally added a button inside one but it should work. It may get confused with the row selected call the tableview makes if you are implementing that.
The Cocoanetics blog seems to have a pretty good solution to this:
http://www.cocoanetics.com/2010/03/how-to-shrink-cells/

Can a UITableView (not UITableViewCell) have variable size?

I have a UIView (created in IB) with a grouped UITableView as a subview. Below this table view is a UIButton. The XIB containing the view will be loaded by a few different viewcontrollers, and so the contents of the table view can vary between one and four cells.
Here's what I want to achieve: when the view loads, the height of the tableview (tableView.frame.size.height) should be adjusted depending on the number of cells, and the button should be placed just beneath the table view.
Can this be done? Could it somehow be done if the view is created programmatically?
Thanks in advance
Edit: Pxl's suggestion was just what I was looking for. A while later, the need arose to have more than just a button below the table view - this was accomplished by creating a separate view containing everything I needed, and implementing the tableView:viewForFooterInSection: and tableView:heightForFooterInSection: functions.
A note for those of you trying to do the same thing: the tableview has to be programmatically created if you want different heights for the footers, or footers for only some of the sections. This is because the footer height set in IB will override the one returned from the tableView:heightForFooterInSection: function.
if there are only a handful of rows, may i suggest that you create a special UITableViewCell that contains just a button?
then make that button cell the bottom row of the last group all the time. make the group so that it will be unlabeled and appear as if the button is sitting at the bottom of your tableview. this way you won't have to muck around with recalculating the tableview's frame and redrawing it.
if the tableview will scroll due to there being many rows, then you'd be calculating the height of the tableview up to a set max (at which point the tableview will need to scroll to show more rows).
once you've determined the height of the tableview you'll need to display your rows, make a frame of the appropriate size, set the tableview's frame to it, position the button just under the tableview, and then redraw the view.
the layout and positioning in this case will need to be done programmatically.
UITableview is a subclass of UIView, so you can change its frame to suit your needs just like a UIView, and UITableView will manage drawing itself to whatever frame you give it.
Just use the methods UITableViewDataSource and UITableViewDelegate provides you.
height = [self tableView:numberOfRowsInSection]*[self tableView:heightForRowAtIndexPath:] + A_CONSTANT_FOR_HEADER_AND_FOOTER_HEIGHT
I agree with pxl that adding a cell with the button in it may be the easiest way to accomplish what you want.
Whether or not you do that, the table view's sizeToFit method should resize the view to (just) fit its contents. If that doesn't work, you can use numberOfSections and rectForSection: to build a loop that determines the height of the table's contents, and reset its frame manually. (And then position the button underneath.)