I'm trying to add a UITextField as the contentView of a UITableViewcell. It works, and the field has focus, but the detailTextLabel slides up 10px. What's the deal here? As a secondary question, is there a better way to create an in-line edtiable UITableViewCell?
Here's my code. I'm trying to do this as result of a double tap on a tableview cell. I retrieve the actual cell that was tapped like this:
CGPoint swipeLocation = [recognizer locationInView:self.tableView];
NSIndexPath *swipedIndexPath = [self.tableView indexPathForRowAtPoint:swipeLocation];
UITableViewCell *swipedCell;
Then I try to add my textfield like this:
swipedCell = [self.tableView cellForRowAtIndexPath:swipedIndexPath];
NSInteger indent = swipedCell.indentationWidth;
UITextField * newText = [[UITextField alloc] initWithFrame:CGRectMake(indent, swipedCell.contentView.frame.origin.y, swipedCell.contentView.frame.size.width, swipedCell.contentView.frame.size.height)];
newText.font = swipedCell.textLabel.font;
newText.text = swipedCell.textLabel.text;
newText.textColor = [UIColor grayColor];
newText.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
swipedCell.textLabel.text = #"";
[swipedCell addSubview:newText];
[newText becomeFirstResponder];
Not entirely unlike yours, except that when I apply your code, both my text and the detaillabel end up in the center of the cell.
Without out seeing your code it's difficult to know what's going on. Here's the code I use to make a UITextField as a contentView cell that works without issue, hopefully it helps.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TaxCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
CGFloat optionalRightMargin = 10.0;
CGFloat optionalBottomMargin = 10.0;
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(275, 10, cell.contentView.frame.size.width - 270 - optionalRightMargin, cell.contentView.frame.size.height - 10 - optionalBottomMargin)];
textField.placeholder = #"Placeholder";
textField.delegate = self;
textField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.text = #"Textfield text"
cell.textLabel.text = #"Textlabel text"
cell.detailTextLabel.text = #"Detail text";
[cell.contentView addSubview:textField];
return cell; }
Related
I want to add 2 imageViews on the Left and Right and a cell textLabel on the Center on TableView.
The 2 imageViews has different role and action.
(Being able to touch, hidden and not hidden)
Now the left side imageView is on the top of the center textLabel.
So I want to change the textLabel's width and x position not to be on the top of imageViews.
I tried this code but it didn't work.
CGRect frame = CGRectMake(40, 0, 200, 40);
cell.textLabel.frame = frame;
and I also tried to add UILabel on the tableView.
But I will implement TableViewCell animation and if I add UILabel, it doesn't work.
So I don't use this way.
How can I solve it?
here is the code.
- (void)viewDidLoad {
tableView = [[UITableView alloc]initWithFrame:rect style:UITableViewStylePlain];
tableView.delegate = self;
tableView.dataSource = self;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.view addSubview: self.tableView];
self.tableView.backgroundColor = [UIColor clearColor];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
[self updateCell:cell atIndexPath:indexPath];
return cell;
}
- (void)updateCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *set = [self.section objectAtIndex:indexPath.row];
cell.backgroundColor = [UIColor blueColor];
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.font = [UIFont fontWithName:#"HiraKakuProN-W3" size:15];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.minimumScaleFactor = 10.0f;
cell.textLabel.numberOfLines = 0;
}
you need to override the layoutSubviews for your UItableviewCell class
- (void)layoutSubviews {
[super layoutSubviews];
CGSize size = self.bounds.size;
self.textLabel.frame = CGRectMake(2.0f, 4.0f, size.width, size.height); // or customize
self.textLabel.contentMode = UIViewContentModeScaleAspectFit;
}
Choice-2
crate the UILabel and subview to cell.contentView
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(4, 4, 200, 30)];
label.text = #"Test";
[cell.contentView addSubview:label];
Update
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
[self updateCell:cell atIndexPath:indexPath];
if (cell == nil){
myCellView = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"Cell"];
UILabel *orderLbl = [[UILabel alloc] initWithFrame:CGRectMake(1, 13, 176, 21)];
[orderLbl setTag:1];
orderLbl.textColor = [UIColor whiteColor];
[orderLbl setBackgroundColor:[UIColor clearColor]];
[orderLbl setTextAlignment:NSTextAlignmentCenter];
[cell.contentView addSubview:orderLbl];
}
[(UILabel *)[cell.contentView viewWithTag:1] setText:[NSString stringWithFormat:#"test"]];
return cell;
}
Better you can use Custom Textlabel with your desired frame requirement.
Give a tag for the textlabel and find out the label in cellForRowAtIndexPath as following :
UILabel *myLabel = (UILabel *)[cell.contentView viewWithTag:givenTagValue];
Then apply your required behaviour for this label as you want.
Hope it helps..
In such cases I prefer creating custom subclass and apply layout as I wanted so if I get any autolayout warning I always know it's because layout is not correct.
Actually, changing the frame the textLabel in cell is NOT allowed in TableView. The width of frame for the textlabel of each cell relates to the cell, developer couldn't set it programmatically. However, I worked out a feasible solution: we may not change the frame of the textLabel, but we may change the source text alternatively. If we can truncate the source string in advance, this problem is overcome.
//Assign each element in the array a row in table view
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var myCell = myTableView.dequeueReusableCell(withIdentifier: "The Cell")
if myCell == nil {
myCell = UITableViewCell(style: UITableViewCellStyle.value1, reuseIdentifier: "The Cell")
}
myCell?.accessoryType = UITableViewCellAccessoryType.none
// If the text is too long (longer than 25 chars), the text will be truncated
// The lenght of label cannot be set effectively here, so I truncate the source string alternatively
var myString: String = sectionArray[indexPath.row]
if myString.characters.count > 25 {
let myIndex = myString.index(myString.startIndex, offsetBy: 25)
myString = myString.substring(to: myIndex)
myString += "..."
}
myCell?.textLabel?.text = myString
myCell?.detailTextLabel?.text = "\(NSDate())"
return myCell!
}
That supports to work.
I have a UITableViewCell that has a UITextView. When the table loads all of the text in each UITextView appears in a single line. I created the UITextView in IB with a white text color. How do I get it to display in multiple lines, and why did the text color switch to black?
The height of each UITableViewCell is correct. It used to display the text in multiple lines after I refreshed the table by pulling down, but for some reason that stopped working too.
If there's any other information you require, please let me know.
Here's the relevant code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
BIDChatCell *cell = (BIDChatCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[BIDChatCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell
cell.backgroundColor = [UIColor clearColor];
cell.userLabel.text = [object objectForKey:#"username"];
NSString *time = [object objectForKey:#"time"];
NSString *date = [time substringToIndex:10];
cell.timeLabel.text = date;
NSString *chatText = [object objectForKey:#"text"];
UIFont *font = [UIFont systemFontOfSize:14];
CGSize size = [chatText sizeWithFont:font constrainedToSize:CGSizeMake(200.0f, 1000.0f) lineBreakMode:UILineBreakModeCharacterWrap];
cell.textStringView.frame = CGRectMake(75, 15, size.width +20, size.height + 20);
cell.textStringView.font = [UIFont fontWithName:#"Helvetica" size:14.0];
cell.textStringView.text = chatText;
[cell.textStringView sizeToFit];
[cell.textStringView.textContainer setSize:cell.textStringView.frame.size];
CGRect frame = cell.textStringView.frame;
frame.size.height = cell.textStringView.contentSize.height;
cell.textStringView.frame = frame;
[cell layoutSubviews];
return cell;
}
Here's an image:
Try setting the height of the textView like so:
CGRect frame = cell.textStringView.frame;
frame.size.height = cell.textStringView.contentSize.height;
cell.textStringView.frame = frame;
Does the UITextView have the proper autoresizingMask?
It likely needs it set to (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight) to allow the textview to grow (as it normally uses a UIScrollView instead)
I have a table view with three table view cells.
During cell configuration, I add a UITextField to each of the cells and I also set the placeholder value on all of the text fields.
When the table view loads the end results looks like this:
The issue I'm having, is that when I scroll any of the cells "off the screen" when they reappear the placeholder text get darker and darker, like here:
When I then attempt to change the UITextField string value by typing a name in, or by programatically changing the placeholder value on the last cell, the old value of those properties stays, and the new value gets overlaid in the cell, like this:
Here are the methods responsible for configuring those cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
[self configureCell:cell forIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath
{
for (UIView *subview in cell.contentView.subviews) {
[subview removeFromSuperview];
}
cell.backgroundColor = [UIColor whiteColor];
cell.autoresizesSubviews = YES;
cell.clearsContextBeforeDrawing = YES;
CGRect textFieldFrame = cell.bounds;
textFieldFrame.origin.x += 10;
textFieldFrame.size.width -= 10;
UITextField *textField = [[UITextField alloc] initWithFrame:textFieldFrame];
textField.adjustsFontSizeToFitWidth = YES;
textField.textColor = [UIColor lightGrayColor];
textField.enabled = YES;
textField.userInteractionEnabled = NO;
textField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
textField.clearsContextBeforeDrawing = YES;
textField.clearsOnBeginEditing = YES;
if (indexPath.section == ATTAddNewTimerSectionName) {
textField.placeholder = #"Name";
textField.userInteractionEnabled = YES;
textField.delegate = self;
textField.returnKeyType = UIReturnKeyDone;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
} else if (indexPath.section == ATTAddNewTimerSectionDate) {
textField.placeholder = #"Date/Time";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else if (indexPath.section == ATTAddNewTimerSectionCalendar) {
if (self.userCalendarEvent == nil) {
textField.placeholder = #"See list of calendar events";
} else {
textField.placeholder = nil;
textField.placeholder = self.userCalendarEvent.title;
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
[cell addSubview:textField];
}
As you can see, I have tried various things, like removing all the subviews before adding a new view to the cell or setting -[UIView setClearsContextBeforeDrawing:YES] on both the cell and the UITextView and even setting the placeholder value to nil without success.
Any pointers would be much appreciated!
You are making a classic error that so many people make. Cells get reused as a table is scrolled.
As written, your code keeps creating and adding a new text field every time the cell is used. So you are seeing the result of having multiple text fields in a cell.
You want to only add one text field to a cell. Update your code so it only adds the text field if it isn't there already.
It seems you have a logic problem in the code. You add the text field directly to the cell but you try to remove it from the cell's contentView.
Change this:
[cell addSubview:textField];
to:
[cell.contentView addSubview:textField];
I have a simple tableView with 20 rows. I created a subclass custom UITableview cell, and in cellforRowAtIndex, I add a textfield to the cell once every other 3 rows. When I scroll up and down text fields show up in the wrong rows. Note, I can't make UItextfield part of my custom cell, because this can be anything, checkbox, radio button, but for simplicity I chose UITextfield... What am I doing wrong?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TestCellIdentifier";
testCell *cell = (testCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if(!cell)
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
else{
//HMMM I also tried removing it before adding it- it doesn't work neither
for(UIView *v in cell.subviews){
if(v.tag == 999 ){
[v removeFromSuperview];
}
}
//add UItextField to row if it's divisible by 3
if(indexPath.row %3 ==0){
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(400, 10, 300, 30)];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.font = [UIFont systemFontOfSize:15];
textField.placeholder = [NSString stringWithFormat:#"%d",indexPath.row];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.keyboardType = UIKeyboardTypeDefault;
textField.returnKeyType = UIReturnKeyDone;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.tag = 999;
[cell addSubview:textField];
}
}
cell.textLabel.text = [NSString stringWithFormat:#"%d",indexPath.row];
return cell;
}
don't use the Reusability ?
in this scene,i will not use the reusability
Reusing cells is a good thing and you should be able to do it.
You could consider removing the text field from the cell when it goes offscreen, before it is queued for reuse, in the delegate protocol method:
– tableView:didEndDisplayingCell:forRowAtIndexPath:
Knowing the row number you would know whether or not to remove the textfield.
Edited to add explanation:
On first glance your code looks OK, so I did a little test project.
The problem with your original code is that you're adding the textfield to the wrong "view" -- UITableViewCells have some structure that you need to pay attention to. Look at the documentation for the UITableViewCell contentView property. It says, in part:
If you want to customize cells by simply adding additional views, you
should add them to the content view so they will be positioned
appropriately as the cell transitions into and out of editing mode.
So the code should add to and enumerate subviews of the cell's contentView:
for(UIView *v in cell.contentView.subviews){
if(v.tag == 999 ){
[v removeFromSuperview];
}
}
...
textField.tag = 999;
[cell.contentView addSubview:textField];
I've added a tableView and dragged a table view cell into it.
in the utilities panel, I changed the style to subtitle.
I've also tried changing it in code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.textAlignment = UITextAlignmentCenter;
cell.detailTextLabel.textAlignment = UITextAlignmentCenter;
cell.textLabel.text = [myArray objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [myArray2 objectAtIndex:indexPath.row];
return cell;
The center alignment doesn't work!
I've tried adding a label object to the cell to have a workaround. But I don't know how to access it. even though I assigned an outlet to it, this wouldn't work:
cell.labelForCell....
What should I do?
any suggestions on how I make it work the usual way, without adding a label to the cell or something?
For the UITableViewCellStyleSubtitle text alignment cannot be changed
You will have to put a label and add your alignment to it,
To do that you could use this code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *myLabel;
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
myLabel = [[UILabel alloc] initWithFrame:Your_Frame];
//Add a tag to it in order to find it later
myLabel.tag = 111;
//Align it
myLabel.textAlignment= UITextAlignmentCenter;
[cell.contentView addSubview:myLabel];
}
myLabel = (UILabel*)[cell.contentView viewWithTag:111];
//Add text to it
myLabel.text = [myArray objectAtIndex:indexPath.row];
return cell;
}
The problem with the subtitle style is that it does a [self.textLabel sizeToFit] when it lays out. When you center in a container that is the perfect size of the contents, nothing changes.
Try this. In a subclass of UITableViewCell, set your textAlignment, and use this as your layoutSubviews code:
- (void)layoutSubviews
{
[super layoutSubviews];
{
CGRect frame = self.textLabel.frame;
frame.size.width = CGRectGetWidth(self.frame);
frame.origin.x = 0.0;
self.textLabel.frame = frame;
}
{
CGRect frame = self.detailTextLabel.frame;
frame.size.width = CGRectGetWidth(self.frame);
frame.origin.x = 0.0;
self.detailTextLabel.frame = frame;
}
}
This makes the textLabel's frame full width, and thus allows the centering effect to be noticeable.
Note: since this overrides layoutSubviews, there is a performance cost as it will be called often.
I think the reason is that: the textLabel's width depends on the text length, if the text is too long to show all in a signal line, and you have already set the line break mode and set the number of lines to 0, you will find that the text alignment will be work.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (nil == cell)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier] autorelease];
cell.textLabel.textAlignment = UITextAlignmentLeft;
cell.textLabel.textColor = [UIColor redColor];
cell.detailTextLabel.textColor = [UIColor greenColor];
cell.detailTextLabel.textAlignment = UITextAlignmentCenter;
cell.textLabel.lineBreakMode = UILineBreakModeTailTruncation;
cell.textLabel.numberOfLines = 0;
}
cell.textLabel.text = [NSString stringWithFormat:#"You can initialize a very long string for the textLabel, or you can set the font to be a large number to make sure that the text cann't be shown in a singal line totally:%d", indexPath.row];
return cell;
}
I think adjusting the frame will work. I had style of UITableViewCellStyleValue2 but If i have a bit lengthy text in textLabel, it getting truncated at tail and textAlignment does not work here, so thought of increase the width textLabel.
-(void)layoutSubviews{
[super layoutSubviews];
if ([self.reuseIdentifier isEqualToString:#"FooterCell"]) {
CGRect aTframe = self.textLabel.frame;
aTframe.size.width += 40;
self.textLabel.frame = aTframe;
CGRect adTframe = self.detailTextLabel.frame;
adTframe.origin.x += 70;
self.detailTextLabel.frame = adTframe;
}
}
It is impossible to change frame for textLabel and detailTextLabel in UITableViewCell
right in cellForRowAtIndexPath: method.
If you don't want to subclass your cell you can implement a small hack using
performSelector:withObject:afterDelay:
with zero delay for changing geometry right after default layoutSubviews:
[self performSelector:#selector(alignText:) withObject:cell afterDelay:0.0];
See details at here
Hi please add the following instead of your code,
cell.textLabel.textAlignment = UITextAlignmentCenter;
cell.detailTextLabel.textAlignment = UITextAlignmentCenter;
change to
cell.textLabel.textAlignment = NSTextAlignmentCenter;
cell.detailTextLabel.textAlignment = NSTextAlignmentCenter;
it will work fine.