I need to create a UITableView with multiple columns. In that, there will be a constant block on the top row of the table. When the user scrolls through the table, the row which is there in that block, will be picked. Basically it is a table view with UIPickerView.
I wish I was able to upload an image to explain this.
I'm not sure how to go about this. This is a hybrid of UITableView and picker view. Can I implement this is as a picker view of course with multi column (the block acting as a custom picker)?
Please help.
Thanks,
~Vishal
YOu can get an index to the data represented in your top row using the UITableView method:
- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point
where point would be (CGPoint){0,0} (or some point which intersects with your block/row 1)
or
- (NSIndexPath *)indexPathForRowsInRect:(CGRect)rect
where rect would relate to you "block".
you will want to manage the scrolling so that the table comes to rest with the top of a row aligned with the block or top of the table. This UITableView method may prove helpful, you should trigger it when your tableview comes to rest after a scroll:
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath
atScrollPosition:(UITableViewScrollPosition)scrollPosition
animated:(BOOL)animated
with UITableViewScrollPositionTop as the scroll position
I expect you want each column to scroll independently. In that case you would need one tableView per column. Then you just need to make sure you know which tableView is doing the message sending in your respective delegate and datasource methods (easy to manage as a pointer to the tableView is the first parameter sent in those methods).
Related
I'm using UITableViewController in order to use static cells.
Is there any way to freeze first cell so it's not scrollable? I'd like to other cells to scroll but first one to stay intact.
I was thinking about regular UIViewController with some stuff on top and UITableView under, but this won't work because I need UITableViewController in order for static cells to work.
The only other way to make it work is with UIViews and Scroll view, but then I don't get benefit of UITableView.
Is that possible?
EDIT:
Just to make it clear. I like to use UITableView with static cells because I have outlets and actions. Buttons, fields inside cells. I'd like to limit "coding" only to show/hide cells. I don't want to create UI inside code. I want to do as much as I can using Storyboard.
Not sure how to put views on section header using Storyboard. Is it possible at all? I only can set text caption.
Also! Even though I do have header (with test) it still scrolls with rest of cells. I need to make sure it stays on a screen.
You can use this delegate method and pass your custom view along with your sub control it will get stick at top :
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
return <your custom view>;
}
I'm trying to implement accordion view using UITableView. I want nesting of the view up to 2 levels.
(Example : There are multiple Regions under Each Region there will be zero/multiple Locations and under Each Location there will zero/multiple Users).
For implementing this scenario I used nested UITableView. i.e Outer TableView (i.e Region TableView) will have its cell as another UITableView (i.e Location TableView) and Each cell of LocationTableView will have another UITableView(i.e TableView Showing users list under each location) as its cell.
I have attached the images for more clarification.
In below image Regions are sections of the tableview. (note : not a single row for now in tableview)
After Tapping 2nd section i.e section with name Region I dynamically reload that section and add the cell(i.e the cell that contains the UITableview showing the locations)
But, it shows the empty space below the location tableview.
Instead I want something like this as below :
Again after tapping the 0th section(Location 0) of the inner tableview (i.e tableview containing location list) I dynamically reload that section of tableview and add the cell(i.e the cell that contains the UITableview showing the list of users under that location)
Have a look at below image
It works perfectly.
Now my issue is that I have calculated the height of the outer UITableviewCell in *- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath )indexPath method depending on the number Location within That Region(i.e Cell) and number of Users under each Location under that Particular Region cell. Issue is that I need to hide/show the locations and users list(All the locations and users list is not shown at once)as according to accordionView. So the height of the inner tableView increase/decrease, hence leaving the blank space at the bottom. Also I have created custom UITableViewCell (i.e creating separate nib file for the cell) for each inner cell containing tableview as ContentView and implemented all the UITableView Data Source and Delegate methods in its corresponding .m file.
What I want is not to show that empty blank space.
When control goes in the inner tableview cells I can't set the height of the outer UITableView from there.
Hope you understood my problem. Please help me. Thank you!!!
I had some similar requirements like this, I didnt use the nested tableview as it brought some complexities to me, so I tried playing around with indentation and indexpaths of the tableview to achieve what I wanted. I just did a small sample app with that concept with some dummy data. I have never tried this approach with Custom cells. See if this helps.
I know I am not answering to the exact question that you asked but I am trying to give a different approach which for me looked simpler.
I just modified my base code to match your data
How to create an Accordion with UItableview under a UItableview?
The source can be found here
Accordion
Screenshot
-anoop
Is it possible to have a UISearchBar on Static Cells, I really need the static cells, and there are like 40 of them, so how can I use the UISearchBar in it?
My Cells are filled with a button (Every name has another button (Every Cell has another name)).
So basically I need to search for the button text onto of each cell, and for that show the cells that contain the search string.
Can someone provide help please?
Thanks for your time and effort.
When you use static cells, as you probably already know, you don't implement the delegate methods in your UITableViewController. However, if you want to only display some of your static cells (or change the ones displayed), you can implement the delegate methods and call super on them after making whatever changes you need.
So by this I mean... If I have a static table view with 1 section, 3 cells, and I only want to display the first cell and the last cell, I would implement - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section, and have it return 2. Then I would implement - (UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath, and when it gets called with the index path with section 0, row 0, I'll call the superclass method with section 0 row 0. And when it gets called with section 0 row 1, I'll call the superclass with section 0 row 2. Basically, I'm mapping from indices of rows that will be displayed to the indices in the complete static table as defined in the storyboard.
However, I would suggest that you don't need to use static cells at all, and it will be a lot simpler. You won't have to deal with this mapping to make this work. You would maybe want to use static cells if your cells have UITextFields in them, or some other type of view that could cause problems for reuse. But in your case, a dynamic table would be much better to use because you don't have any content in a cell that would need to possibly be saved if a cell were going to be reused at a different index.
If you go the dynamic table route, you just need to implement the delegate for the search bar, and as you type you will store the list of filtered results in an array stored in an instance variable or property, and reload your table, using that array as the data source.
I have a UI table view loading data from network. If the user move the finger on one cell, one button will be displayed, just like iPhone style delete button. If the user click this button, the value of one label in the cell will be changed accordingly. However, I didn't find any way to make table view to re-draw this cell, except for reload the whole table. I don't want to use reload data method, because I just need change the value in one cell instead of the whole table. Any suggestion on this?
Take a look at the method
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
Calling this method will result in your table view's data source asking its delegate for information about that cell.
For future reference, I found this very easily by checking the documentation on UITableView. I suggest you do that in the future before posting here.
I am using a UITableView to display the results of a series of calculations. When the user hits 'calculate', I add the latest result to the screen. When I add a new cell, the UITableViewCell object is added to an array (which is indexed by tableView:cellForRowAtIndexPath:), and then I use the following code to add this new row to what is displayed on the screen:
[thisView beginUpdates];
[thisView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation: UITableViewRowAnimationFade];
[thisView endUpdates];
This results in the new cell being displayed. However, I then want to immediately scroll the screen down so that the new cell is the lowermost cell on-screen. I use the following code:
[thisView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
This almost works great. However, the first time a cell is added and scrolled to, it appears onscreen only briefly before vanishing. The view scrolls down to the correct place, but the cell is not there. Scrolling the view by hand until this invisible new cell's position is offscreen, then back again, causes the cell to appear - after which it behaves normally. This only happens the first time a cell is added; subsequent cells don't have this problem. It also happens regardless of the combination of scrollToRowAtIndexPath and insertRowsAtIndexPath animation settings.
EDIT:
I've now started inserting cells at the second-to-last position of the table, rather than the end, and the problem still occurs - when first inserted, a cell is 'invisible' until it goes offscreen and comes back on again. What could be causing this, and how can I force the cell to be drawn as soon as it is added to the table?
You're having problems because your updating the table without updating the data model backing it. Tables don't actually know how many rows they have nor what cells to display. They depend on the datasource and the delegate to tell them these things. Your design expects the table itself to track them.
insertRowsAtIndexPaths: is intended to be used for moving existing rows around a table, not for adding entirely new logical rows. When you insert an entirely new cell, the tableview looses track of how many rows it actually has.
Before you display a new row, the first thing you should do is update the values returned by:
– numberOfSectionsInTableView:
– tableView:numberOfRowsInSection:
... to reflect the addition of the new rows. This will allow the table to understand how big it is.
Then you need to update cellForRowAtIndexPath: to return the correct cell for the added row. Then you need to reload the table.
After you've done that, you should be able to scroll the tableview to the end and have the cell display properly.
The important thing to remember about tables is that they are dumb. The table itself holds no data, doesn't know how many sections and rows it has or what order the rows and sections come in. All the logic about data, sections, rows, cells and cell contents comes from the datasource and/or the delegate. When you want to change a table, you actually change the datasource and/or the delegate and then the table will reflect those changes automatically.
Edit:
Upon rereading the parent, I see that your putting the actual UITableViewCell objects in your data array and that you have one cell for each row.
This is not how tableviews are supposed to work and this will not scale beyond a few dozen rows at most.
Tableviews are intended to be an illusion that allows you display a lOGICAL table which has an arbitrary high number or rows. To that end, it only keeps enough UITableViewCell objects alive to cover the visually displayed area in the UI. With a default cell height of 44 pixels this means a tableview will never have more than 9 cell objects at a time.
Instead of eating memory holding cells that are not displayed, the tableview lets the delegate dequeue a cell that has scrolled off screen, repopulate it with the data of another LOGICAL row and then display it in a new position. This is done in cellForRowAtIndexPath:
You really need to start over here with your design. Your data needs to be kept separate from the user interface objects. You don't want to have more cells alive at anyone time than absolutely necessary because your memory use will balloon and your response time will degrade. Your current problem is the result of this unusual design.
When you've done that, you can add the result row as outlined above.
Try to scroll with some time shift after cell update via NSTimer or performSelector:withDelay:. It can help but to fix all problems I think there need to do more work.
The glitches may be caused because a UITableView considers itself the owner of any UITableViewCell instances it is displaying, and reuses them as needed. Part of that process is calling prepareForReuse on the cell. Since you are keeping the cells in an array, you do not want them reused. Try implementing an empty prepareForReuse in your UITableViewCell class. Or just create cells dynamically in tableView:cellForRowAtIndexPath: as apple recommends.
I used what Skie suggested to avoid the problem in the following way:
Immediately after adding the row:
[self performSelector:#selector(scrollToDesiredArea:) withObject:newIndexPath afterDelay:0.4f];
This called the following:
-(void)scrollToDesiredArea:(NSIndexPath *)indexPath{
UITableView *thisView = (UITableView*)self.view;
[thisView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
The delay of 0.4s seems to be sufficient to avoid the glitching; any less and it still happens. It may have to be different on varying models of iPhone hardware, though - I only tested on emulator.