I have a table view controller in which I need to display a date&time picker when a cell is tapped and hide it when the cell is tapped again. Basically the same effect that the iphone has when you choose your start and end date and time to create a new event in the calendar.
I'm guessing the display and hiding goes in the following method but I'm unsure of what goes inside:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {}
Some example code or link would be great. Thank you!!
Create your cell with whatever you want to show and the picker:
-----------------------------------
cell visible part
-----------------------------------
cell invisible part (with picker)
-----------------------------------
Define a property that let you know if you have to show the entire cell:
#property (nonatomic) BOOL shouldShowPicker;
Initialise this property (on viewDidLoad for example);
self.shouldShowPicker = NO;
A couple of methods to touch:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 4) { //where your picker row is
self.shouldShowPicker = YES;
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 4 && self.shouldShowPicker) { //where your picker row is
return CELL_VISIBLE_PLUS_INVISIBLE_PART;
} else if(indexPath.row == 4 && !self.shouldShowPicker) {
return return CELL_VISIBLE_PART;
} else {
return OTHER_CELLS_HEIGHT;
}
}
You might find my answer here useful which describes what you need to do.
Inline UIPicker Implementation
Essentially you create a custom cell containing a date picker, with optional buttons. You then add this cell below the cell when you edit it and remove it when finished. All explained in the link.
Related
What I'm trying to do is to insert some new data into the data source array, and then do [tableView reloadData]. The new array can be inserted, but there are two problems.
1) I want to have two radio buttons in the new cell for users to choose. Should I define a new cell object or something?
2) When reloading the data, the selected cell's color cannot be set to green as before.
Or any other suggestions on how to best implement this, thanks!!:
For the first problem, what I would do is pre-layout that cell containing the two radio buttons either in the storyboard (You can also do it in a .xib file). Then I will set an identifier for it like "LanguageSkillSelectionTableViewCell" or something. After that, when I am about to load the new set of data into the table view I can manage the presentation of cells in the table view through the callback cellForRowAtIndexPath:
An example would be if I want to load that LanguageSkillSelectionTableViewCell always at the beginning, then I would just set it at indexPath.row == 0. else set the contents of the data list to other rows.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *tableCell;
if(_loadedNewData)
{
if(indexPath.row < dataList.count && indexPath.row > 0)
{
tableCell = (DataTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"DataTableViewCell"];
//set attributes of the tableCell
}
else
{
tableCell = (LanguageSkillSelectionTablViewCell *)[tableView dequeueReusableCellWithIdentifier:#"LanguageSkillSelectionTableViewCell"];
//set attributes of the tableCell
}
}
else
{
//load in default order
}
return tableCell;
}
You can just play with the arrangement and presentation of the cells under this callback.
For the second problem, you have to store a flag or state for that selection picked by the user in a global variable within the class. Then everytime the cells are reloaded you can just update the selection state of that cell by setting a method for that cell that would update the selection state of the radio button.
For example:
If user selected English, then it would be like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *tableCell;
if(_loadedNewData)
{
if(indexPath.row < dataList.count && indexPath.row > 0)
{
tableCell = (DataTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"DataTableViewCell"];
//set attributes of the tableCell
}
else
{
tableCell = (LanguageSkillSelectionTablViewCell *)[tableView dequeueReusableCellWithIdentifier:#"LanguageSkillSelectionTableViewCell"];
//set attributes of the tableCell
[(LanguageSkillSelectionTablViewCell *)tableCell setLanguageSelectionState:canReadWrite];
}
}
else
{
//load in default order
}
return tableCell;
}
I have a custom UITableViewCell with a UITextField (which is linked to the custom cells class). I am trying to access the textField from my VC class.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
menuCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
if ([indexpath row] == 2) {
menuCell.nameTextField.delegate = self;
}
return cell;
}
-(void) textFieldDidEndEditing:(UITextField*) textfield
{
}
How do I get the textFields text from textFieldDidEndEditing?
Depending on where you want to access this text depends on how difficult it is.
Want to access the text in cellForRowAtIndex - (very easy)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
menuCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
if ([indexpath row] == 2) {
menuCell.nameTextField.delegate = self;
}
NSString * text = menuCell.nameTextField.text;
return cell;
If you want to access the text anywhere in the VC and the menuCell is unique (there is only one of them) - (medium difficult)
In your header file add the custom cell as a class
#class menuCell;
This means you can set it a variable in the interface
menuCell * _menuCell;
Next in cellForRowAtIndex you want to allocate this custom cell
- (UITableViewCell *)tableView:(UITableView *)tableView_ cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == bCustomCellSection) {
if (!_menuCell) {
_menuCell = [tableView_ dequeueReusableCellWithIdentifier:bProfileNameCell];
_menuCell.nameTextField.delegate = self;
}
_menuCell.nameTextField.placeholder = #"Name";
_menuCell.selectionStyle = UITableViewCellSelectionStyleNone;
return _menuCell;
}
...
}
This means that we now have access to the menu cell from anywhere in the VC and can get the text by calling
_menuCell.nameTextField.text
Multiple custom cells with multiple textfields - (tough)
I have never done this but would probably do it one of two ways
a) Create an array and as we are creating the custom cells add a pointer to the textFields to the array each time. We can then access the textField we want from that array
For this method I would add the custom cells to a mutable array defined in the interface
NSMutableArray * cellsArray;
remember to initialise it in viewDidLoad
cellsArray = [NSMutableArray new];
Then in cellForRowAtIndex i would add the cell each time
menuCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
[cellsArray addObject: menuCell];
This obviously depends on how many sections we have. If we have more than one section it gets more complicated again:
Then we would need to add an array for each section to an overall array. This is quite complicated and could have a whole question on its own, there is a good link of how to do this here:
Once you have an array of cells (or an array of arrays of cells) you can call the cell you want based on the indexPath and get the textField
b) Call a pointer to the specific cell we want
menuCell * menuCell = [self tableView:table cellForRowAtIndexPath:indexPath];
and then get the textField from this cell as we did previously.
Remember you can calculate your own indexPath if you want to create one outside of cellForRow:
NSIndexPath * indexPath = [self.tableView indexPathForCell:cell];
This method is pretty good if you want to access a specific cell but a bit cumbersome if you want to access it a lot and keep having to call this code all over your VC
Hope this helps
If you are asking how to get the text from the delegate method textFieldDidEndEditing, then you simply do this:
-(void) textFieldDidEndEditing:(UITextField*) textfield
{
NSString *textFieldText = textfield.text;
}
However, if you have multiple textFields and you want to know what textfield is calling the delegate, you could tag your textField:
[myTextField setTag:indexPath.row]
and then put a if statement in the delegate textFieldDidEndEditing like this:
-(void) textFieldDidEndEditing:(UITextField*) textfield
{
if(textfield.tag == index0) do something..
else if(textfield.tag == index1) do something..
}
Here are tableView data source and delegate implementation, and I set the maximum selection is 5.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if ([multiOptions count] > 5) {
[self tableView:tableView didDeselectRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selected = NO;
//show alert
}
...
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[multiOptions removeObject:selectedOption];
...
}
but here comes a question, if the options exceed the limit, the first click on cell will work just fine. but second time click the cell will call
didDeselectRowAtIndexPath
again, that's not what i expected, and I tried
[tableView deselectRowAtIndexPath:indexPath animated:YES];
in didSelectRowAtIndexPath, it didn't work, can someone give me a hint, how to correct it? thanks.
You have to check this in tableView:willSelectRowAtIndexPath:
Have a look at the UITableView class reference
especially at the last sentence:
Return Value An index-path object that confirms or alters the selected
row. Return an NSIndexPath object other than indexPath if you want
another cell to be selected. Return nil if you don't want the row
selected.
So something like this will work within tableView:willSelectRowAtIndexPath::
if ([multiOptions count] > 5) return nil;
I have a UITableView with static cells created in a storyboard. When the user touches a cell, another cell should hide/show. This is identical to how it looks in the built-in calendar app in iOS 7. It's basically the same question as this: How does one implement a view that slides out like the date picker in calendar? but I have a static table view and not a dynamic, otherwise the solution would have worked. If i try it, en exception is thrown.
As it is now, I can show and hide the cell at the row, but it is without animation, which isn't acceptable. This is the code I use:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 2 && indexPath.row == 0)
{
NSIndexPath *dateIndexPath = [NSIndexPath indexPathForRow:1
inSection:2];
UITableViewCell *dateCell = [self.tableView cellForRowAtIndexPath:dateIndexPath];
if (dateCell.hidden)
{
dateCell.hidden = NO;
}
else
{
dateCell.hidden = YES;
}
}
}
hye, i think you should refer this link, it will help you regarding hiding cells,
UITableView set to static cells. Is it possible to hide some of the cells programmatically?
I have a UITableViewController. I need to display a table cell followed by a cell that has an embedded UITextField. Basically i need to display the tableView datasource alternatively. Please help me on this.. Thanks.
EDIT #1: Imagine NSMutableArray *tableData; is the datasource for the table which has the following elements:
#"Apple"
#"Mango"
#"Watermelon"
I want the UITableView to be displayed as:
1st cell: Apple
2nd cell: text field to enter quantity
3rd cell: Mango
4th cell: text field to enter quantity
5th cell: Watermelon
6th cell: text field to enter quantity
7th cell: save button
Use dataSource method like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return ([m_tableData count]*2)+1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == [m_tableData count]*2)
{
//cell with button
}
else
{
if(indexPath.row == 0 || indexPath.row%2 == 0)
{
//cell with label for displaying values
}
else
{
//Load a cell that has an embedded UITextField
}
}
}