I'm new to iOS development and it seems that Auto Layout is the most confusing part to me.
I have a UITableViewCell which is a dynamic prototype.
On the cell, in the storyboard scene, I have created:
{ [UILABEL] [UILABEL] } <-- TableViewCell
I want the two labels to be aligned next to each other.
The first UILabel is a date (Month/Day) and the second UILabel is a title.
I know that the title will be too large. However, it still needs to sit next to the Date Label with only a tiny space between them.
Ex. 12/01 Example Title
I have literally tried everything in the Storyboard - from trying to allow Xcode to automatically "suggest the constraints" to creating my own by setting the right, left, and bottom constraints. As well as, configuring the content hugging property for the title label to be 1000 for vertical and horizontal.
The date label shows up correctly. However, the title label doesn't show up at all... other than some buggy white specs on the side. =(
If I press and hold down on the row, I can see the title in the background behind the date label and across the entire row.
I did configure the text of each row programmatically in the cellForRowAtIndexPath method, by doing this:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// get the label objects of the cell
UILabel *dateLabelOfCell = (UILabel *)[cell viewWithTag:0];
UILabel *titleLabelOfCell = (UILabel *)[cell viewWithTag:1];
dateLabelOfCell.text = date;
titleLabelOfCell.text = title;
Any ideas what I'm doing wrong?
UPDATE 1:
Looks like the label text is being set. The data is just not showing up. So, I looked more into setting the cell labels using viewwithtag and I found that other people were running into this issue:
UILabel with viewWithTag - (text not appearing)
However, none of their solutions work. Any ideas why the first UILabel shows up and the second one doesn't? I only see the second UILabel if I go to click on the row.
I determined the issue.
The reason why the 2nd UILabel wasn't showing up wasn't due to the Auto Layout at all.
The problem was because I was using 0 and 1 for my tag numbers. So, I changed both the tag numbers in my storyboard file and updated the code to match and they both appeared.
I believe the reason using 0 caused problems and interfered is because the tableviewcell's default tag number was 0 as well.
So, make sure the tag numbers you use are unique.
Related
I have different examples where we can update the UITableViewCell height based on growing UITextView which actually is working for me. The issue which I am facing is, I have more subviews below UITextView inside a UITableViewCell. This way, the cell's height updates but the position of the subviews remain fixed which causes overlap of UITextView and the subviews.
Just to mention, I am not using auto layout.
How do I fix this ?
These are the three screenshots which will help in understanding my issue :
1. Before TextView is shown :
2. After TextView is shown :
3. After text is entered :
I'm assuming you are using auto layout for this cell (but we could use a code example or Xcode screenshot to help you more specifically). If you are using auto layout, you'll want to make sure that:
You have a constraint between the UITextView and the other UIView subviews below it in the cell
The other UIView subviews are eventually constrained to the bottom of the cell.
Because UITableViewCells are reused, you will find that when adding objects to the contentView, those objects will also be reused without being removed, leading to overlapping subviews. The way around this it to start your cellForRowAtIndexPath with the following code:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
for (UIView * view in [cell.contentView subviews]) {
// clears the cell before reusing
[view removeFromSuperview];
}
Hope this helps.
Are you using auto layout? I have done this before several times with UITableViewCells though it’s mainly been with UILabel and not UITextView.
Your problem might be resolved with auto layout. You layout all your subviews (inside of UITableViewCell) relative to each other. If one view (i.e. UITextView) changes size the other views will then adjust relative to that view. Here are a few useful links.
This isn’t specific to UITableViewCell but has a lot of good examples of various scenarios.
Stanford University Developing iOS 7 Apps: Lecture 9 - Animation and Autolayout
https://www.youtube.com/watch?v=r1sc7NI6-wo
In my UITableView, if a section has 0 rows, I tell it to be set up like so:
if (top3ArrayForSection.count-1 < 1) {
// title of the item
cell.textLabel.text = #"No items found, but we'll keep a lookout for you!";
cell.textLabel.font = [UIFont systemFontOfSize:12];
cell.detailTextLabel.text = [NSString stringWithFormat:#""];
[cell.imageView setImage:[UIImage imageNamed:#""]];
}
This is so that detailTextLabel is blank, and the cell.imageView doesn't show. However, the cell ends up showing up like the picture below. The image is blank, but still taking up space, resulting in the textLabel being pushed off to the right like that. How can I remove the image all together for that specific cell?
I would use a different subclass of UITableViewCell to display the one without the image. That will be a lot easier than trying to move stuff around dynamically.
To follow up on #Almo's post:
Create a second variant of your custom table view (you could make it a subclass of your custom table view class; that way you don't have to duplicate code. In your subclass, skip the image and shift the label over.
Another way to do this would be with auto-layout and constraints. you could make the label's left edge link to the right edge of the image view, and pin the label's right edge to the edge of the cell. Then when the image view is zero width, the label would shift over. The problem there is padding. You'd still get the padding from both sides of the image view unless you added custom code to zero out the left edge padding on the image view when the image is empty.
I've got a UITableView with several different elements added programmatically. The one I'm having trouble with is the UITextView that displays correctly with correct color, size, font, etc... I have a button in one cell that increases the size of the font in the UITextView in another cell. It works fine and has no issues. The numerical value is placed in a Plist, and when you leave the view with the table and come back the size changes perfectly.
I've placed a reloadData in the button which does reload the table and gives the textView new size and resizes it to fit the new content plus resizes the cell perfectly. The issue I'm having is that when the reloadData is called, the old textView remains. So I have two texts, at two different sizes, or three or four and so on. How can I remove the previous textView when it's not set to global?
Everything is set up exactly how one would expect:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
// cell with textView. Everything is instanced and created for just that cell with tags
UITextView *t = [self setSizeAndTextOfTextView];
[cell.contentView addSubview:t];
// cell with button. simple, alloc's and init inside cell. Calls method in same class
cell.contentView addSubview:button];
//method to increases font size
write to Plist the new size
[self.tableView reloadData]; <-- tableView is iboutlet that does reload table
How are you getting the cell in the first place? Are you reusing? If you are you don't want to add the textview as a subview again you want to retrieve the existing one and adjust it
UPDATE:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if ([cell.contentView viewWithTag:1]) {
UITextView *t = (UITextView *)[cell.contentView viewWithTag:1];
//This version will take an existing textview and just resize it
[self setSizeAndTextOfTextView:t];
} else {
//This version creates a new text view
UITextView *t = [self setSizeAndTextOfTextView];
t.tag = 1
[cell.contentView addSubview:t];
}
You'll probably need to do something similar with you button as well
The reloadData won't wipe the existing cells, just the data displayed, so you'll get an old one to reuse
You may consider creating a custom subclass of UITableViewCell and associate that with your cell identifier. In your subclass, override the prepareForReuse method to set the cell back to a neutral state. Since cell objects are reused but are only initialized once, prepareForReuse is available to restore an already existing cell to its freshly initialized state.
I've been to a lot different questions on StackOverflow, But I just can't figure what is wrong here.
I have a view controller that receives data from a JSON, creating an array, and, then, it builds an UITableView, with fixed heights.
The issue is that I can't scroll to the bottom. It just bounces back.
- (UITableViewCell* )tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"SettingsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
[cell.detailTextLabel setNumberOfLines:2];
NSDictionary* place = [_placesData objectAtIndex:indexPath.row];
[cell.textLabel setText:[place valueForKey:#"nome"]];
[cell.detailTextLabel setText:[place valueForKey:#"endereco"]];
[cell.detailTextLabel setLineBreakMode:NSLineBreakByWordWrapping];
[cell.detailTextLabel sizeToFit];
UIImage* originalImage = [UIImage imageNamed:#"encontre.png"];
UIImage* resized = [UIImage imageWithCGImage:[originalImage CGImage]scale:(originalImage.scale * 1.8) orientation:(originalImage.imageOrientation)];
cell.imageView.image=resized;
cell.textLabel.font = [UIFont fontWithName:#"GillSans" size:17];
cell.textLabel.textColor = [UIColor whiteColor];
cell.detailTextLabel.font = [UIFont fontWithName:#"GillSans-Light" size:17];
self.tableView.scrollEnabled=YES;
self.tableView.bounces=YES;
[self.tableView setAlwaysBounceVertical:YES];
return cell;
}
I have no idea on what else to do. Already tried to set the contentSize.height manually, force bounces and scrollEnabled on almost evert piece of code on the view controller.
Regards.
The way UITableView works is that it requires to know each row height in order to be able to compute its size.
The default behavior is to assume each row height is 44px. Which was clearly not your case here as you said it was 70px. That's why you had to change it in order to be able to scroll all way down
For instance let's say you had 10 rows. With default row height your table view was only able to scroll down to 10*44 = 440px thus the bouncing effect you got.
By setting the row height to 70px your tableview now goes down to 10*70 = 700px
can you check in the xib of your ViewController, select your tableView and click "size inspecto" in the right menu and you change in "iOS 6/7 Deltas":
you can tape -20 in height
i think the problem is in adaptation with ios7 and 6
I just had the same problem.
My solution was to update the contentSize before reloading the table's data.
tableViewOffre.contentSize = CGSizeMake(tableViewOffre.frame.size.width, [app.offres count] * 105);
Where 105 is my row height.
I think it isn't the best way to solve the problem (pretty dirty way I guess) but it's the only solution found.
Try implementing the UITableViewDelegate method tableView: heightForRowAtIndexPath:, don't let it get assigned automatically (i.e. sizeToFit). UITableView can be very unpredictable if you are not very specific and if you don't override certain methods.I had a unique problem with tableView scrolling back up to top automatically after I called [tableView reloadData]; This problem was unique because it only happened on iPad mini and iOS 8, every other device and OS was working properly. Hope it helps someone...
Actually your problem is related to frame of the table. by setting "Row height" is working for you because by chance count of row in your table and row height giving a table height that is suitable to you. But its not the right way of doing this.
Somewhere you need to check height of the table may be something like
Blockquote
(nameArray.count<10?kSACellHeight*nameArray.count:kSACellHeight*11))
Just managed to solve it, if anyone is having this same issue.
What I did is, inside the size inspector for my UiTableView, I manually set "Row Height" at 70 (the exact size I'm using).
After this, everything worked as a charm. But, if anyone can give a comprehensive explanation on what is really happening in here, it would be really great.
I've met with same issue.In my situation,I drag a tableview to a custom view controller,which is presented by a push segue.If the amount of data showed in tableview exceeds some number,then I can't touch the cell on bottom of the tableview.
Many ways have been tried:set the frame/content size of the table view,and none works for me.Finally,I find the root cause and solve it in a simple way(although not gracefully).
First,the root cause:the table view created by IB has a width larger then the its parent view controller.Thus,any cell out of view's bound will not be touched.
So,the solution is simple:Go to StoryBoard,adjust the width of table view,making it smaller than the width of parent view.It seems that if one table view is created by StoryBoard,you can't change its frame by code.That's what I've found up to now. I guess it's a bug of StoryBoard.
Help it be useful for other guys.
Keep in mind, my solution uses constraints. I ran across this issue while making a UITableView that can have a dynamic number of cells expand with more details. Here was my structure:
UIView
UIStackView
UIView (My Tabs Segue View)
UIView (My First Tab View)
UITableView (My Table I Wanted to be Scrolled)
UIView (My View if that Table was Empty)
UIView (My Second Tab View)
UITableView (My Second Table I Wanted to be Scrolled)
UIView (My View if that Table was Empty)
So, what I found out was that when I was setting the height constraint of the tables to the contentSize of the tables themselves. This originally helped account for the expandable part of the cell. But, if you want a table to be scrollable, you need to have its height shorter than its content height. By making it shorter (and having all the xib checkboxes checked as mentioned in other posts), it will automatically scroll. Granted, you can set its height via constraint or any way you want, just make sure its not the same as its content height!
I've created a cell prototype in the Xcode 4.2 storyboard that consists of an image view in the center of the cell and some text below it but when I run the app the image is always moved to the left side. I've made the cell extra tall to ensure it wasn't a height issue. I also played with the autosize settings.
So far nothing I've tried will make the image move to the center of the tableViewCell when the code is actually running.
Note, this is done purely in the StoryBoard. The only code I've written is code to create a list of objects with a "name" and "image" and the minimum table view source/delegate code so I can fill in two entries in the table.
I suppose you use something like :
static NSString *identifier = #"ImageRecordCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
UILabel *label = (UILabel*)[cell viewWithTag:1];
UIImageView *pic = (UIImageView*)[cell viewWithTag:2];
label.text = #"test";
pic.image = [UIImage imageNamed:#"Default.png"];
return cell;
be sure not to set tag to zero
I had something that works just fine in iOS 4.x, but was doing something similar to what you describe in the iOS 5 simulator, moving a UIImageView down by about 120px for no apparent reason. Setting the Autosizing settings to have the top position outside the box frozen (if that makes sense) fixed the issue—though it was not at all clear to me why this behavior had changed in iOS 5 vs. previously.