Reputation: 21883
this may have been discussed already but I cannot find the question.
I need to display/edit an address in a table view. Looking at the address cell in the iPhones contacts app, it appears that they use a single cell for both displaying and editing the address.
I first thought it was done by using 4 custom cells to edit the address, but I could not see how the address type field could span the 4 rows, in addition, when selected, it selected all 4 rows. This made me think it was done with a single table view cell, which has a custom arrangement of UItextFields.
Currently I'm going down this path. The thing that has me stuck at the moment is dealing with the grey lines between cells. I originally turned on the UItextField borders, but that didn't really look very good. So I'm looking into doing custom drawing. But that appears to not draw on top of the cell.
Does anyone have any idea how apple constructs this address cell?
Thanks
Upvotes: 1
Views: 4922
Reputation: 6533
Do the followings:
UITableViewCellStyleValue2
style for your cellnumberOfLines
properties of cell.detailsTextLabel
to a number of your choosing-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
method and return the height calculated using this formula: 44.0f + (numberOfLines - 1) * 19.0f
I read this somewhere on the Internet, but don't remember the source. Just tried this today, and it works flawlessly.
Upvotes: 2
Reputation: 8287
If you want a line between each cell in a table view, then use the style 'grouped' - see the Table View tab in Attributes Inspector in Interface Builder. Members of each group will have lines between them.
Did you consider using UITableViewCells instead of programmatically adding UIViews? You can easily add a label and a text field + vertical line to such a XIB. This works really well for me with the following code:
@protocol PersonDetailCellViewControllerDelegate
-(void)didUpdateTextField:(int)index withText:(NSString*)text;
@end
@interface PersonDetailCellViewController : UITableViewCell <UITextFieldDelegate> {
IBOutlet UILabel* keyLabel;
IBOutlet UITextField* valueTextField;
int index;
id<PersonDetailCellViewControllerDelegate> delegate;
}
@property (nonatomic, retain) IBOutlet UILabel* keyLabel;
@property (nonatomic, retain) IBOutlet UITextField* valueTextField;
@property (nonatomic, retain) id<PersonDetailCellViewControllerDelegate> delegate;
@property (nonatomic, assign) int index;
@end
and
@implementation PersonDetailCellViewController
@synthesize keyLabel, valueTextField, delegate, index;
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if(delegate) {
[delegate didUpdateTextField:index withText:[textField.text stringByReplacingCharactersInRange:range withString:string]];
}
return YES;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField {
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
return YES;
}
@end
with the corresponding UITableView method
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PersonDetailCellViewController *cell = (PersonDetailCellViewController*)[aTableView dequeueReusableCellWithIdentifier:CELL_KEY_VALUE_ID];
if(cell == nil) {
NSArray* topLevelObjects = [[NSBundle mainBundle]loadNibNamed:@"PersonDetailCellView" owner:nil options:nil];
for(id currentObject in topLevelObjects) {
if([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (PersonDetailCellViewController*)currentObject;
cell.valueTextField.backgroundColor = [UIColor clearColor];
cell.valueTextField.borderStyle = UITextBorderStyleNone;
cell.selectionStyle = UITableViewCellSelectionStyleGray;
if([Language sharedLanguage].rightToLeft) {
// set the alignment right because we are flipping the whole available text field, not just the area which actually has text
cell.keyLabel.textAlignment = UITextAlignmentRight;
cell.valueTextField.textAlignment = UITextAlignmentLeft;
// flip cell contents
cell.contentView.layer.transform = CATransform3DMakeRotation(M_PI, 0.0f, 1.0f, 0.0f);
// flip text back so that readable
cell.keyLabel.layer.transform = CATransform3DMakeRotation(M_PI, 0.0f, 1.0f, 0.0f);
cell.valueTextField.layer.transform = CATransform3DMakeRotation(M_PI, 0.0f, 1.0f, 0.0f);
}
cell.selectionStyle = UITableViewCellSelectionStyleGray;
break;
}
}
}
cell.keyLabel.text = [keys objectAtIndex:indexPath.section];
cell.valueTextField.placeholder = [hints objectAtIndex:indexPath.section];
cell.valueTextField.delegate = cell;
if(indexPath.section == 0) {
cell.valueTextField.text = self.name;
} else if(indexPath.section == 1) {
cell.valueTextField.text = self.mobile;
} else if(indexPath.section == 2) {
cell.valueTextField.text = self.home;
}
if(indexPath.section == 1) {
cell.valueTextField.keyboardType = UIKeyboardTypePhonePad;
} else {
cell.valueTextField.keyboardType = UIKeyboardTypeDefault;
}
// open keyboard
if(indexPath.section == 0) {
[cell.valueTextField becomeFirstResponder];
} else {
[cell.valueTextField resignFirstResponder];
}
cell.delegate = self;
cell.index = indexPath.section;
return cell;
}
Best regards, Thomas.
Upvotes: 1
Reputation: 21883
I've got something working, but I'm not sure if its built that well. I basically created a UIView which holds the UITextFields for the individual fields of an address. I built a custom controller for it that manages the data and draws the gray lines between the fields just like the one in contacts.
I then added this custom UIView to the UITableView cell. My understanding is that this is the recommended way to do this because any drawing in drawRect: then stays within the boundaries of the UITableViewCell. My experiments with using drawRect: in the UITableView cell class drew lines on the background of the UITableView, not the cell.
This basically works, however there is one thing I don't like. To get the gray lines to extend to the border of the UITableViewCell I had to ensure that the UIView I placed in it was exactly the same size so that any drawing done in drawRect: could extend right to the edge of the UITableViewCell.
However if I use a opaque background I loose the nice rounded corners of the cell because it is drawn over the top. So I had to use a transparent background. My understanding is that opaque backgrounds are recommended for performance reasons so I'm not sure if I'm really building this control correctly. Luckily there will not be any more that 2 or 3 on a screen.
Upvotes: 0