Scenario:
Attempting to make a basic n x n collection flow layout.
I merely placed a one-char UILabel with a tag #1 in the middle of a stock cell.
I intended to grab this UILabel and populate it with a single weekday initial.
I do this by grabbing the UILabel from the cell and set its value:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NSInteger item = indexPath.item;
BOOL isTitleRow = (item <= 6);
if (isTitleRow) {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kWeekDayHeaderCell forIndexPath:(NSIndexPath *)indexPath];
UILabel *label = (UILabel *)[cell.contentView viewWithTag:1];
label.text = [self dayHeaderStringFor:item];
return cell;
} else {
InspectionCalendarCollectionViewCell *cell = (InspectionCalendarCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:kMonthDayCell forIndexPath:(NSIndexPath *)indexPath];
return cell;
}
return nil;
}
But I'm not getting anything, so I start checking to find that the UILabel is nil (even though by default it should have the letter 'W'):
(lldb) po label
nil
(lldb) po cell
<UICollectionViewCell: 0x7fdc93f4b180; frame = (0 0; 32 32); clipsToBounds = YES; autoresizesSubviews = NO; layer = <CALayer: 0x7fdc93f4a050>>
(lldb) po cell.contentView
<UIView: 0x7fdc93f4b730; frame = (0 0; 0 0); gestureRecognizers = <NSArray: 0x7fdc93f4c630>; layer = <CALayer: 0x7fdc93f49fd0>>
(lldb) po cell.contentView.subviews
<__NSArrayI 0x7fdc93f00bc0>(
)
Why is the cell's contentView layout is zeroes?
Why no subviews listed within cell? --- IB has them.
What am I missing here?
Related
I am trying to have 10 pixels gap between cells and the edge of the screen. I implemented willDisplayCell:forRowAtIndexPath and also the heightForCell since am using two different prototype cells in my table view.
The problem am having is really weird. The cells are only adjusted when i pull the list up, am guessing only when they are reused! check the images please.![enter image description here][1]
This is the initial screen:
https://www.dropbox.com/s/epl2n8a5zohhdmz/Edited.screenShot.01.png?dl=0
This is the screen after the table view is scrolled:
https://www.dropbox.com/s/c81dx9wmaq0mgr5/Edited.screenShot.02.png?dl=0
Here is my code:
- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.layer.borderWidth = 5.0f;
cell.layer.borderColor = [UIColor grayColor].CGColor;
cell.layer.cornerRadius = 7.0;
cell.layer.bounds = CGRectMake(0, 0, 260, cell.bounds.size.height - 10);
cell.backgroundColor = [UIColor colorWithRed:207/255.0 green:207/255.0 blue:207/255.0 alpha:1.0];
CGRect cellFrame = CGRectMake(20, cell.frame.origin.y, 280, cell.frame.size.height);
cell.frame = cellFrame;
cell.contentView.frame = cellFrame;
[cell.contentView alignmentRectForFrame:cellFrame];
[cell setNeedsLayout];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[self.namesList[indexPath.row] objectForKey:#"Relation"] length] == 0) {
return 69.0;
} else {
return 89.0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableString *details = [[NSMutableString alloc] init];
UITableViewCell *cell = [[UITableViewCell alloc] init];
UILabel *nameLabel;
UILabel *relationLabel;
UILabel *ageLabel;
UILabel *dayLabel;
UILabel *dateLabel;
Helper *dateConvert = [[Helper alloc] init];
if ([[self.namesList[indexPath.row] objectForKey:#"Relation"] length] == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell2" forIndexPath:indexPath];
} else {
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell3" forIndexPath:indexPath];
relationLabel = (UILabel *) [cell viewWithTag:2];
relationLabel.text = [self.namesList[indexPath.row] objectForKey:#"Relation"];
}
nameLabel = (UILabel *) [cell viewWithTag:1];
ageLabel = (UILabel *) [cell viewWithTag:3];
dayLabel = (UILabel *) [cell viewWithTag:4];
dateLabel = (UILabel *) [cell viewWithTag:5];
[details appendString:[self.namesList[indexPath.row] objectForKey:#"Age"]];
[details appendString:#")"];
ageLabel.text = details;
dayLabel.text = [dateConvert getWeekDay:[self.namesList[indexPath.row] objectForKey:#"Date"]];
dateLabel.text = [self.namesList[indexPath.row] objectForKey:#"Date"];
return cell;
}
I have spent days trying to find the problem :( every help is greatly appreciated :)
Why not make your life easier and design the cell in Interface Builder to have the 10 px space already. You can add a UIView, make that 10 px from top, left, right and bottom, then put you UI elements inside of that. I would suggest subclassing your UITableViewCells and have code in those to display your data and set the borders.
There is a custom cell. In it there is two labels. One of them called nameLabel's height has to change dynamically. It can be 1,2 or 3 lines sometimes. But the rows are on eachother, they cross their own row lines. How can I solve this problem?
The labels and Custom Cell object's Use Autolayout option is disabled.
The label height has to change dynamic, And then the CustomCell's. And then tableRow. My head is confused. And why can't I see CustomCell's background color is changing?
Thanks
Here is my code for :
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UILabel *label = [[UILabel alloc] init];
label.numberOfLines = 0; // allows label to have as many lines as needed
label.text = [[self.dataList objectAtIndex:indexPath.row] objectForKey:#"NAME"];
CGSize labelSize = [label.text sizeWithFont:label.font constrainedToSize:CGSizeMake(320, 63) lineBreakMode:NSLineBreakByWordWrapping];
CGFloat h = labelSize.height;
NSInteger x=0.0;
if (h==63.0) x=30;
if (h==42.0) x=20;
if (h==21.0) x=10;
return h+30;
}
- (UITableViewCell*)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cellid";
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil)
{
cell = (CustomCell*)[[[NSBundle mainBundle]
loadNibNamed:#"CustomCell" owner:nil options:nil]
lastObject];
}
// customization
NSDictionary *d = [self.dataList objectAtIndex:indexPath.row];
cell.nameLabel.text = [d objectForKey:#"NAME"];
cell.cityLabel.text = [d objectForKey:#"CODE"];
cell.indexPath = indexPath;
return cell;
}
At this link there is picture of simulator and xib of the Custom Cell to understand easy the problem:
http://compfreek.wordpress.com/2013/08/14/custom-cell-for-table-row-height-changes-dynamic/
Hear is another way try this change according to ur code it may different, but it may solve your problem.I am putting all views through code only, because it is easy for me check this out.
//in your subclassed class
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
//may be u did same i am adding the label to cell
UILabel *nameLabel = [[UILabel alloc]initWithFrame:CGRectZero];
nameLabel.numberOfLines = 5; //set number of lines
nameLabel.tag = 100;
[self addSubview:nameLabel];
UILabel *otherLabel = [[UILabel alloc] initWithFrame:CGRectZero];
otherLabel.tag = 200;
[self addSubview:otherLabel];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
//do your customisation when cell is selected
}
-(void)layoutSubviews
{
//in this method i am setting the frames for label
[super layoutSubviews];
UILabel *nameLabel = (UILabel *) [self viewWithTag:100];
nameLabel.text = self.nameString;
CGSize maxSize = CGSizeMake(self.bounds.size.width / 2, MAXFLOAT);//set max height
CGSize nameSize = [self.nameString sizeWithFont:[UIFont systemFontOfSize:17]
constrainedToSize:maxSize
lineBreakMode:NSLineBreakByWordWrapping];
nameLabel.frame = CGRectMake(self.bounds.origin.x +2,self.bounds.origin.y+3, nameSize.width, nameSize.height);
UILabel *otherLabel = (UILabel *) [self viewWithTag:200];
otherLabel.frame = CGRectMake(nameLabel.frame.size.width+15,self.bounds.origin.y+3, 100, 40);
otherLabel.text = self.otherString;
}
//in your main class
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
if(cell == nil)
{
cell = [[[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CustomCell"]autorelease];
}
//change it for ur need
NSString *name = #"hear is your long length name uzamaki naruto from uzamaki clan";
NSString *other = #"other name";
cell.nameString = name;
cell.otherString = other;
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *name = #"hear is your long length name uzamaki naruto from uzamaki clan";
//replace it your height logic
float cellWidth = 350; // ur cell width
CGSize maxSize = CGSizeMake( cellWidth / 2, MAXFLOAT);//set max height
CGSize nameSize = [name sizeWithFont:[UIFont systemFontOfSize:17]
constrainedToSize:maxSize
lineBreakMode:NSLineBreakByWordWrapping];
return nameSize.height + 10;// for ur height
}
When working on UICollectionView, I am loading a cell from nib like below
- (void)viewDidLoad
{
[super viewDidLoad];
/* Uncomment this block to use nib-based cells */
UINib *cellNib = [UINib nibWithNibName:#"NibCell" bundle:nil];
[self.collectionView registerNib:cellNib forCellWithReuseIdentifier:#"cvCell"];
// Configure layout
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
self.collectionView.contentInset = UIEdgeInsetsMake(10.0f, 0.0f, 10.0f, 0.0f);
[flowLayout setItemSize:CGSizeMake(300, 200)];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
[self.collectionView setCollectionViewLayout:flowLayout];
}
And my nib file looks like below
The top label is used to displayed the number of cell and the middle label is used to display a certain text
in method cellForItemAtIndexPath, I just want to set the text to the cell of certain row ( in this example, I am doing it at row of 1 ) :
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// Setup cell identifier
static NSString *cellIdentifier = #"cvCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:100];
UILabel *cellLablel = (UILabel *)[cell viewWithTag:200];
cellLablel.text = self.dataArray[0][indexPath.row];
if ( indexPath.row == 1)
[titleLabel setText:#"this is row 1"];
return cell;
}
When running the app, there is a problem on it. Not only is titleLabel of cell at row1
set to This is row 1, but also the titleLabel of row5 and row9 and row10 is set as well:
If anybody knows what I am doing wrong in the middle. please help.
My colleciton is containing 1 section and 15 row for this section.
Cells are reused. As soon as you scroll down and Cell 1 gets invisible, the collection view makes it available again. Just set the text for all cells, e.g.
titleLabel.text = [NSString stringWithFormat:#"this is row %d", indexPath.row];
I encountered a weird problem. I am creating a custom selected view for my tableviews. However, this selection view doesn't fit well. I found out that this is because my selection view is 300px while the cell itself is 320px. The weird part is that the UITableView's width is actually just 300px only. How will I adjust the cell width of my table?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *tableIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier] autorelease];
if (tableView == bandTable)
{
UIImageView *imageBg = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"column1_selected.png"]];
[imageBg setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
[cell setSelectedBackgroundView:imageBg];
[imageBg release];
NSArray *array = [bandDictionary objectForKey:#"Bands"];
cell.textLabel.text = [array objectAtIndex:indexPath.row];
NSLog(#"CELL: %f", cell.bounds.size.width);
}
return cell;
}
Just set
cell.frame = CGRectMake(0,
0,
self.tableView.frame.size.width,
cell.frame.size.height);
in cellForRowAtIndexPath.
Add this two lines after your cell gets created,
[[cell contentView] setFrame:[cell bounds]];
[[cell contentView] setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
#IvorPrebeg, you shouldn't set the frame for the UITableViewCell inside cellForRowAtIndexPath. The UITableViewCell will automatically be set to the width of the UITableView after the cell did execute layoutSubviews. This will be done automatically after setting a value on the label you inserted in the cell.
Its just important to calculate inside heightForRowAtIndexPath a size based on the font and the text inserted into the cell which is equal to the one inside your cell. In my case it looks like this:
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath{+
ChatMessage *message =
[self.fetchedResultsController objectAtIndexPath:indexPath];
CGSize size = [message.text sizeWithFont:self.messageCell.labelMessage.font
constrainedToSize:CGSizeMake(self.tableView.frame.size.width * 0.8f, HUGE_VAL)
lineBreakMode:NSLineBreakByWordWrapping];
return size.height;
}
And than inside the UITableViewCell:
- (void)layoutSubviews{
[super layoutSubviews];
if( _fInitWidth == 0 ){
self.labelMessage.preferredMaxLayoutWidth =
self.bounds.size.width * 0.8f;
}
[self.contentView setNeedsDisplay];
}
Like you can see, the prefferedMaxLayoutWidth of the UILabel inside my UITableViewCell will be 0.8 of the cells width (320 * 0.8). LayoutSubviews will be excecuted inside cellForRowAtIndex after setting up the cells properties. After that, UITableView will call the heightForRowAtIndexPath and calculate the size for the height. Therefore I calculate the UILabels size by passing a width * 0.8 for constrainedToSize ( tableview width is 320.0 * 0.8 ) the same as in the cell.
The example values are for iPhone devices, they will change on bigger screens of course.
On C#:
public UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath){
UITableViewCell cell = new UITableViewCell();
cell.Frame = new CoreGraphics.CGRect(0, 0,this.selectSchoolTableview.Frame.Width, cell.Frame.Size.Height);
cell.ContentView.AutosizesSubviews = true;
return cell;
}
Another trick:
public UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath){
UITableViewCell cell = new UITableViewCell();
cell.Accessory = UITableViewCellAccessory.None;
cell.ContentView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth;
cell.ContentView.AutoresizingMask = UIViewAutoresizing.FlexibleHeight;
return cell;
}
I have a UITableView that has 1 blank row at the top of it, and I cannot figure out why. Here is the relevant code, do you folks have any idea what's going on here?
The UITableView loads up with no content. This method is what kicks off each data refresh after:
- (IBAction)updateButton:(id)sender
{
if (questionsTextField.isFirstResponder) {
[questionsTextField resignFirstResponder];
[self assignQuestionsCount];
}
if (currentNumberOfQuestions > 0) {
// do work calculating
currentTest = nil;
currentTest = [self retrieveCurrentTest];
currentTest.numberOfQuestions = currentNumberOfQuestions;
currentTest.decimalPlacesToDisplay = 0;
currentTest.roundingBreakPoint = 0.5;
currentGradeScale = nil;
currentGradeScale = [currentTest generateGradingScale];
[scoresTableView reloadData];
}
else {
// my error handling on text boxes here....
}
}
Here is my implementation of the UITableView methods:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.currentGradeScale count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"scoresIndentifier";
static int missedTag = 1, correctTag = 2, gradeTag = 3;
UILabel *missedLabel, *correctAndTotalLabel, *letterGradeLabel;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//if a cell does not exist, get it then initialize it
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
// populate data
missedLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 100, 50)];
missedLabel.tag = missedTag;
missedLabel.font = [UIFont systemFontOfSize:14.0];
missedLabel.textAlignment = UITextAlignmentCenter;
missedLabel.textColor = [UIColor blackColor];
missedLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight |UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
[cell.contentView addSubview:missedLabel];
}
// if it does, just reassign the properties
else {
missedLabel = (UILabel *)[cell.contentView viewWithTag:missedTag];
}
missedLabel.text = [[self.currentGradeScale objectAtIndex:indexPath.row] determineLetterGrade:0.5];
return cell;
}
Thanks for the help folks, I really appreciate it.
The most obvious explanation which you've probably already considered is that the first row of the table has been set with blank data (i.e. self.currentGradeScale objectAtIndex:0 returns nil or #"" for "determined letter grade 0.5.")
If you put a breakpoint on cellForRowAtIndexPath in the debugger at the line where you assign a value to the label text is it definitely setting a non-null/non-blank value for row 0?
Also side note there is a memory leak on missedLabel - adding it as a subview to the cell will retain it so you should autorelease on alloc, or release after adding as a subview.
I had this same problem and found that there was a value in the Scroll View Size / Content Insets / Top area. See attached image. Once I set that to 0 and saved, the blank area at the top went away. I hope this helps.