I need a basic UITableView with key and value. I modify each cell to contain a UILabel, and a UITextArea. My problem is when I click the cell, the cell gives the blue click-response, but the keyboard does not appear, and the UITextField is not showing any response for editing.
In - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath I can get the textField, and set text to it, but I want to open the keyboard for writing in the textField.
When I modify the cell, I set all UITextFields to firstResponder, without luck.
Anyone?
As far as I remember, you can use the UITableViewStyleValue1 and just set the detailTextlabel to be an UITextlabel in your CellForRow. But take care that the TextLabel has a fitting width and height. Then you dont have to select the Cell but can directly tap the UITextLabel
I looked up one of my older projects and found out I handled things a little different back then. Here is what I did:
cell = [self.aTableView dequeueReusableCellWithIdentifier:kPlaceCell];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleValue1 reuseIdentifier:kPlaceCell] autorelease];
}
//PlaceField = An Instance of UITextfield, which I implemented as classvar.
[self.placeField removeFromSuperview];
// setting frame and font for your textfield. If you have static text in your Textlabel you should have an higher x so maybe CGRectMake (1, 100, 218, 39)
self.placeField.frame = CGRectMake(1, 1, 318, 39);
self.placeField.font = [UIFont boldSystemFontOfSize:18.0f];
//Adding your UITextfield to the UITableViewCell contentView
[cell.contentView addSubview: self.placeField];
}
If anyone wonders: I used this tableView so that the user can create an user account and used Placeholders for (Name, Date of birth,....) so I didn't need static text. ^^
Tell me how this works for you or if you need further explanations
Related
The code below has code that determines the frame size of a UILabel, and I think it does work, however when I place it within my rowAtIndexPath for a UItable I get wonky results.
Perhaps, I dont fully understand how or what the reuseIdentifier does, but I placed the code to calculate the frame only when the cell is nil. What happens is that the heights are calculated only for the first three cells, then it repeats in sequence for the rest of the cells. For example, cell one's height is used for cell four's height.
Maybe someone can point me in the right direction as to how I should setup my calculations.
Thanks!
if(cell == nil){
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:DisclosureButtonCellIdentifier] autorelease];
//start adding custom subviews to the table cell
//addSubview for Description
UILabel *descValue = [[UILabel alloc] init];
NSString *descString = rowData.summary;
CGSize maximumSize = CGSizeMake(185, 130);
UIFont *descFont = [UIFont fontWithName:#"HelveticaNeue" size:12];
CGSize descStringSize = [descString sizeWithFont:descFont
constrainedToSize:maximumSize
lineBreakMode:descValue.lineBreakMode];
CGRect descFrame = CGRectMake(125, 60, 185, descStringSize.height);
descValue.frame = descFrame;
descValue.backgroundColor = [UIColor redColor];
descValue.font = descFont;
descValue.tag = kDescriptionValueTag;
descValue.lineBreakMode = UILineBreakModeWordWrap;
descValue.numberOfLines = 0;
[cell.contentView addSubview:descValue];
[descValue release];
}
UILabel *desc = (UILabel *)[cell.contentView viewWithTag:kDescriptionValueTag];
desc.text = rowData.summary;
Using NSString UIKit Additions, you can get the width of a string using a particular font:
[myString sizeWithFont:myFont];
There are several other functions in that Additions set that can help figure out how big a piece of text will be, with different layout options, for single and multi-line text, etc.
The purpose of the reuseIdentifier is to let you reuse a cell -- with particular subviews in particular places -- without the device having to spend the execution time to do all that layout. Definitely more useful back in the iPhone 1 days when the processor was much slower. Until you are more familiar with reuseIdentifiers, I would suggest you just create a new cell every time that function is called.
Each time the OS calls your cellForRowAtIndexPath, you need to fill out the content correctly. Anything that needs to get resized or changed depending on the row should be set.
Frankly, I did not try understanding your code completely. That is nearly impossible especially because you close the method with brackets without returning anything but cellForRowAtIndexPath which I assume you are referring to, requires the return of a UITableViewCell object.
Apparently we are looking only at some fraction of the code.
However, layouting a cell properly is not the full task. You need to tell the table the height of each cell.
You may want to implement
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
for that task. That method is good if the cell height varies.
If the cell hight is different from the standard but does not vary from cell to cell then setting of the rowHeight property of the tableView will be sufficient.
I think that in your case the implementation of the method heightForRowAtIndexPath is mandatory.
BTW, you may want to look at subclassing the UITableCellView and implement the layoutSubviews method in your subclass.
You didn't show all of your code but usually to implement tableView:cellForRowAtIndexPath: you start with the following:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// get a cell from the queue of reusable cells, if any
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: DisclosureButtonCellIdentifier];
if (cell == nil) {
// No cell to reuse, need to create a new one
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:DisclosureButtonCellIdentifier] autorelease];
// add cell subviews here
}
// fill in cell content and resize subviews here
...
return cell;
}
Once you have created 3 (in your case) cells they get reused as the table scrolls so you don't have to keep creating cells. The call to dequeueReusableCellWithIdentifier will return one of the previously created cells if it was not longer in use (it scrolled off the top or the bottom).
i am using a UITextView inside a tableView cell in order edit text.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITextField *textName = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 270, 24)];
[cell addSubview:textName];
[textName release];
}
This works, but when running it on the iPad it isn't correct.
I've tried to determine the width of cell using
cell.contentView.frame.size.width
but this always returns 320.0 for both iPhone and iPad
Also on the iPad when in landscape mode shouldn't the width of cell be bigger?
Teo
Ideally you'd create a custom UITableViewCell and adjust your control sizes/positions in layoutSubviews.
If you're going to add the control in tableView:cellForRowAtIndexPath:, then you can get the width from the tableView itself:
UITextField *textName = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width-50, 24)];
The iPad cell is resized when it's added to the table, after your function returns. If you want the text field to resize with the cell, you can do something like textName.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight.
You should add custom views to contentView (i.e. [cell.contentView addSubview:textName]). The content view automatically shrinks to handle editing mode, among other things.
Subclassing UITableViewCell is a bit overkill if you just want to tweak layout — it's my impression that auto-resizing is faster than manual sizing using layoutSubviews.
I am new to iPhone development and I am currently working on a simple RSS reader app. The problem I am having is that I need to reposition the textLabel inside the UITableViewCells. I have tried setFrame or setCenter but it doesn't do anything. Does anyone know what I need to do inside the tableView:cellForRowAtIndexPath: method to reposition the textLabel at the top of the cell (x = 0, y = 0)?
Thank you
PS: The UITableViewCell is referenced by a variable called cell. I have tried [cell setFrame:CGRectMake(0, 0, 320, 20)] with no success.
You can create a subclass for UITableViewCell and customize de textLabel frame. See that answer: Labels aligning in UITableViewCell. It's works perfectly to me.
It's my subclass
#import "UITableViewCellFixed.h"
#implementation UITableViewCellFixed
- (void) layoutSubviews {
[super layoutSubviews];
self.textLabel.frame = CGRectMake(0, 0, 320, 20);
}
#end
It's my UITableViewControllerClass:
UITableViewCellFixed *cell = (UITableViewCellFixed *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCellFixed alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
You may try indentationLevel, separatorInset and other content indentation properties of UITableViewCell object.
Seems I solved my own problem. Here's some code, in case someone runs into the same problem:
UILabel *ttitle = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 20)] autorelease];
ttitle.font = [UIFont boldSystemFontOfSize:13];
ttitle.textColor = [UIColor blackColor];
ttitle.textAlignment = UITextAlignmentLeft;
[ttitle setText:[[stories objectAtIndex: storyIndex] objectForKey: #"title"]];
[cell.contentView addSubview:ttitle];
The idea is to create your own label object, because the textLabel is automatically positioned and can't be moved around.
Cheers.
The reason the original poster's code doesn't work is that it appears that the frame of the textLabel is set after the UITableViewCell has been returned from your delegate method.
I noticed that I can successfully alter many properties of the textLabel, such as the text alignment, color, font, etc, but altering the frame has no effect and when I print the frame to the debugger later (like on select), the frame isn't what I set. Therefore, I conclude that the UIKit framework is altering the frame of the textLabel after it is returned from the delegate method. No doubt this is likely done because Apple engineers wanted to make sure that your text was drawn to the screen, so they measure it and alter the frame so that it will fit. They probably figured that people such as ourselves who wanted to alter the position of the text would be able to do so by subclassing, or simply adding another UILabel (or whatever) as a subview. A novice developer might have a very hard time if his or her text didn't show up in the label or was truncated because they didn't adjust the frame.
In my case, I wanted the text to be center horizontally, to be a specific color/font/size, and to be slightly higher vertically in the cell. Being too lazy to subclass this, I first tried altering the frame. When that didn't work, I tried googling the answer (found this post).
My final solution was to set the numberOfLines property to 0 and add some trailing carriage returns to my text. Now THAT is lazy.
In Swift 3 it would be
override func layoutSubviews() {
super.layoutSubviews()
self.textLabel?.frame.origin.x = 50
}
I'm new to Objective-C and iPhone coding and was hoping someone could help me.
Basically I want a scrollable table that displays a name and a quantity of that item. For example:
Apples.........2
Oranges......4
Bananas......5
I want the name to be left-justified and the number to be right-justified.
Is there any way to do this with a UITableView or will I need to extend UIScrollView?
Thanks in advance.
Set cell.text to "Apples". Then create an new UILabel view with the text "2" and assigned it to cell.accessoryView.
Text is always on the left, and accessory views are always on the right. Optionally a UIImage in cell.image will be displayed to the left of the cell text if you choose to add one.
If you have a cell layout more complicated than that you have to add subviews to your cell manually.
One not too difficult option is to subclass UITableViewCell with one label for the text and one label for the number, then just set the label values.
If you want the ... that you've shown then you could probably use a standard UITableViewCell and write some code to feed the cell text that has been pre-modified to fit in the space alloted.
You could simply use another CellType, which is already provided by apple and change the color for the detailTextLabel:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CustomCellIdentifier = #"Cell";
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CustomCellIdentifier];
cell.textLabel.text = #"Apples";
cell.detailTextLabel.text = #"2";
cell.detailTextLabel.textColor = [UIColor blackColor];
return cell;
}
No need to bother with subclassing or adding labels on your own.
I have a UITableView with reorderable rows and I'm using the standard UITableViewCell.text property to display text. When I tap Edit, move a row, tap Done, then tap the row, the built-in UILabel turns completely white (text and background) and opaque, and the blue shade to the cell doesn't show behind it. What gives? Is there something I should be doing that I'm not? I have a hacky fix, but I want the real McCoy.
Here is how to reproduce it:
Starting with the standard "Navigation-Based Application" template in the iPhone OS 2.2.1 SDK:
Open RootViewController.m
Uncomment viewDidLoad, and enable the Edit button:
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
Specify that the table has a few cells:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 4;
}
In tableView:cellForRowAtIndexPath:, add a line to set the text property of a cell, and therefore to use the built-in UILabel subview:
// Set up the cell...
cell.text = #"Test";
To enable reordering, uncomment tableView:moveRowAtIndexPath:toIndexPath:. The default implementation is blank, which is fine in this case since the template doesn't include a data model.
Configure the project for the Simulator, OS 2.2.1, Build and Go. When the app comes up, tap Edit, then slide any row to a new position, tap Done, and then tap each row one at a time. Usually a tap will select a row, turn it blue, and turn its text white. But a tap on the row that you just moved does that and leaves the UILabel's background color as white. The result is a confusing white open space with blue strips on the edges. Oddly enough, after the first bogus tap, another tap appears to correct the problem.
So far I have found a hack that fixes it, but I'm not happy with it. It works by ensuring that the built-in UILabel is non-opaque and that it has no background color, immediately upon selection.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// hacky bugfix: when a row is reordered and then selected, the UILabel displays all crappy
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
for (UIView *view in cell.contentView.subviews) {
if ([[view class] isSubclassOfClass:[UILabel class]]) {
((UILabel *) view).backgroundColor = nil;
view.opaque = NO;
}
}
// regular stuff: only flash the selection, don't leave it blue forever
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
This appears to work, but I don't expect it to be a good idea forever. What is the Right Way to fix this?
This looks like a bug in UITableView's rendering, and you should file a Radar bug report on it. It's like the cells don't get refreshed properly after the move.
One way to work around this for now is to not use the built-in label, but roll your own in the cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
CGRect frame = cell.contentView.bounds;
frame.origin.x = frame.origin.x + 10.0f;
UILabel *textLabel = [[UILabel alloc] initWithFrame:frame];
[textLabel setAutoresizingMask:UIViewAutoresizingFlexibleRightMargin];
textLabel.tag = 1;
textLabel.textAlignment = UITextAlignmentLeft;
textLabel.backgroundColor = [UIColor clearColor];
textLabel.textColor = [UIColor blackColor];
textLabel.font = [UIFont boldSystemFontOfSize:20.0];
textLabel.numberOfLines = 1;
textLabel.highlightedTextColor = [UIColor whiteColor];
[cell.contentView addSubview:textLabel];
[textLabel release];
}
UILabel *textLabel = (UILabel *)[cell viewWithTag:1];
textLabel.text = #"Test";
return cell;
}
I tried this, and it doesn't exhibit the same sort of white blank rectangle you see with the built-in label. However, adding another non-opaque view to the table cell might not be the best for overall rendering performance.
I don't know how major of a glitch this is, because Apple doesn't want you to persist a selection highlight on a table row (they've been enforcing this lately during the review process). You're supposed to place a checkmark or move on to the next level in the navigation hierarchy with a selection, at which point this white box would only be on the screen for a fraction of a second.
The trick in the solution from Brad appears to be:
textLabel.backgroundColor = [UIColor clearColor];
If you leave the background as the default you still get the problem even when you roll your own cells UITableViewCells.
The reason I left it as the default is because the documentation says it is less computationally costly to use opaque backgrounds. Ideally I wouldn't want to use [UIColor clearColor] to fix this bug.
Maybe a completely custom painted cell would somehow fix it. I haven't tried those before though.
Does anyone else have a solution for this?
Thanks for the info, I was searching how to erase the background color from a UILabel.
I used the following line:
textLabel.backgroundColor = [UIColor clearColor];
and worked perfectly!!!
thanks
Alejandra :)
Selections aren't meant to be shown for extended periods! (We got knocked on this for several of our apps)
??? That means Apple would not approve their own Calendar app on iPhone! When you go to edit the start and end times of the event, the start time is selected indefinitely, it only changes once the user taps to the next field.