IOS TableView height of rows - ios

i need to have 2 kinds of rows. One with 44 px of height and other with 90px:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0)
return 90.0;
else
return 44.0;
}
The problem is when i called - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath because i need to add to the cell with 90px an scrollView that have 90px of height but it's added on the middle of the cell instead on the top.
if (indexPath.section == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:ScrolledCellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ScrolledCellIdentifier];
//cell.textLabel.text = #"hi";
[cell addSubview:self.scrollView];
}
Trying to set the textLabel of the cell works, the problem is adding the scrollView.
If i add this line to the code:
self.scrollView.frame = CGRectMake(0,-45, 320, 90);
It works perfectly but it sounds some weird for me. What is happening?

Set the frame of your scrollView to the bounds of your cell before you add it.
So
self.scrollView.frame = cell.bounds;
[cell addSubview:self.scrollView];
Debug... NSLog.... output the frames of things so you can see where they are getting positioned as opposed to where you want them to be positioned. Use this for outputting frame coordinates:
NSLog(#"Frame is: ", NSStringFromCGRect(self.scrollView.frame));
or define a nice shortcut, as I use this all the time
#define LogCGRect(rect) NSLog(#"CGRect:%#", NSStringFromCGRect(rect));
then you can just do
LogCGRect(self.scrollview.frame);

It just fits the scrollview into the tableviewcell, no matter if it's height is 44 or 90.

I solved my problem using this code:
cell = [tableView dequeueReusableCellWithIdentifier:ScrolledCellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ScrolledCellIdentifier];
cell.frame = CGRectMake(0, 0, 320, 90);
self.scrollView.frame = CGRectMake(0,0, 320, 90);
[cell addSubview:self.scrollView];
i don't know if it's wrong but it works...

Related

Do not add an existing item in the cellForRowAtIndexPath

In my TableViewController I use custom cell, this cell has a scrollView. My cellForRowAtIndexPath method looks like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
// iOS 7 separator
if ([cell respondsToSelector:#selector(setSeparatorInset:)]) {
cell.separatorInset = UIEdgeInsetsZero;
}
}
UIView *subview = [cell viewWithTag:indexPath.row + 1];
if (!subview) {
//... Set up the new cell
[self addScrollViewForCell:cell andCellIndx:indexPath.row];
}
else {
// ... Reuse the cell
}
return cell;
}
If view already exist - I'm trying do not add scrollView. If not - add.
addScrollViewForCell: method:
- (void)addScrollViewForCell: (CustomCell *)tCell andCellIndx:(NSInteger)cIndx {
UIScrollView * myScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(5, 62, 350, 61)];
myScrollView.accessibilityActivationPoint = CGPointMake(100, 100);
//Some settings
// ...
UILabel *lblH = [[UILabel alloc] init];
lblH.textAlignment = NSTextAlignmentCenter;
lblH.text = strWeekIdntfr;
lblH.textColor = [UIColor blueColor];
lblH.frame = CGRectMake(offsetScores, 0, cCurrWeekBallsWidth, 15);
[myScrollView addSubview:lblH];
myScrollView.tag = cIndx + 1;
[tCell addSubview:myScrollView];
}
The problem is - when I scroll table to the bottom or to the up, scrollView begin to be added. Checking view by tag I try to differentiate reusable and new one cells, but this didn't work. How Can I solve this?
The reason is because an instance of UITableViewCell is reused when you scroll.
Each time it's being reused, this line UIView *subview = [cell viewWithTag:indexPath.row + 1]; will query for view with different tag. Say, you have 100 cells in this UITableView, a cell might be asked for tag 1, 6, 11, 16, 21 ... 96, which clearly it doesn't have. So it's likely to create a new view every time it's being reused. Multiply this with every cell in the pool and you will get hell load of new scroll views added to them.
To solve this: Just use a fix tag number.
So the line.
UIView *subview = [cell viewWithTag:indexPath.row + 1];
become:
UIView *subview = [cell viewWithTag:1];
And:
myScrollView.tag = cIndx + 1;
become:
myScrollView.tag = 1;
And as #AdamPro13 pointed out, a better and much more elegant way is that you create the scroll view as part of your custom cell. Just put it in initWithFrame:style: of the UITableViewCell's subclass.
The best way that I found it just clear all subview from scrollView. For example like that:
[myCell.scrollView.subviewsmakeObjectsPerformSelector:#selector(removeFromSuperview)];

Using autolayout for UITableViewCells and dynamic heights

So I have looked over this answer. But I am still not getting the heights to return correctly for iOS7. I have a table view with a cell that I laid out in autolayout that is fairly complicated. Whenever I try to override the heightForRowAtIndex (to make it iOS7 compatible) I get row heights that don't seem to be calculated correctly. When I don't override heightForRowAtIndex everything works great, except that it doesn't work on iOS7. I am also trying to layout the whole thing automatically using xibs. There isn't really any logic in my DipticCell.m. It's all in the UITableView subclass.
-(id)init{
//Implementation details go BELOW
self.dataSource = self;
self.delegate = self;
[self registerNib:[UINib nibWithNibName:#"DipticCell" bundle:nil] forCellReuseIdentifier:#"dipticCell"];
[self registerClass:[UITableViewCell class] forCellReuseIdentifier:#"cell2"];
self.rowHeight = UITableViewAutomaticDimension;
offScreenCells = [[NSMutableDictionary alloc] init];
return self;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *reuseIdentifier = #"dipticCell";
if (indexPath.row > 0){
reuseIdentifier = #"cell2";
}
UITableViewCell *cell = [offScreenCells objectForKey:reuseIdentifier];
if (!cell) {
cell = [self dequeueReusableCellWithIdentifier:reuseIdentifier];
[offScreenCells setObject:cell forKey:reuseIdentifier];
}
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
height += 1.0f;
return height;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == 0){
DipticCell *cell = [tableView dequeueReusableCellWithIdentifier:#"dipticCell"];
if (cell == nil) {
cell = [[DipticCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"dipticCell"];
}
return cell;
}else{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell2"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell2"];
}
cell.textLabel.text = #"one";
return cell;
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 10;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
Just to confirm that everything is in the contentView.
Also, when I override the heightForRowAtIndexPath I get an "Unable to simultaneously satisfy constraints." warning. But when I don't override that then things seem to work (which makes sense because the cell should just adapt to the height of the content and now I'm trying to override it with a height of 1.)
Here is a link to the project if you want to run it. AutoLayoutCells
What worked for me most of the time is to make sure, that you have a constraint path going from the top of the cell down to the bottom of the cell.
So if your cell as three labels: label1, label2, label3 and all shall be displayed below each other. Than add constraints:
cell.top to label1.top
label1.bottom to label2.top
label2.bottom to label3.top
label3.bottom to cell.bottom
that way the height of your cell is defined by constraints. So make sure to connect all your subviews that define the height of the cell in such a chain.

how to change contentView frame in cellforrowatindexpath?

I have made a custom cell and i want to change the frame of contentView. My cell is a CustomCell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"hey");
static NSString *CellIdentifier = #"CustomCellReuseID";
AbcCustomCell *cell = [tabel_Abc dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[AbcCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *name= [arrayTabel_Abc objectAtIndex:indexPath.section];
[cell setBackgroundColor:[UIColor clearColor]];
[cell.label_CellList setText:name];
cell.contentView.frame = CGRectMake (100,0,500,20);
return cell;
}
I have use
cell.contentView.frame = CGRectMake (100,0,500,20);
but its not working for me. I want to change the contentView of customCell, Can any one guide me?? Thanks in advance.
You can't change the contentView. UITableViewCell contentView's height is determined by – tableView:heightForRowAtIndexPath: delegate method and its width is the tableView's width normally.
If you can add a view as subview of contentView and change the view's frame.
You need to re-assign the frame for the cell's contentView.
CGRect oldFrame = cell.contentView.frame;
cell.contentView.frame = CGRectMake( oldFrame.origin.x,
oldFrame.origin.y,
oldFrame.size.width + 20,
oldFrame.size.height );
or you may use custom cell
you can't change the frame of contentView of a cell. you can change the height of a cell by using
tableView:heightForRowAtIndexPath:
But you can't change the width.
Also you can use a view if you want to make as if the divider is big, if you want something like that.
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.contentView.frame.size.width - paddingX*2, 1)];
separatorLineView.backgroundColor = [UIColor redColor];
[cell.contentView addSubview:separatorLineView];
Can you be more specific to which frame you want to change(whether it is out of bounds)?

dequeueReusableCellWithIdentifier with cells of different size

STEP 1 - this is working fine
I have UITableView that loads custom UITableViewCells
STEP 2 - this is kinda works
I change the UITableViewCell height so that all the data contained in the cell within a UITextView is visible
I manage to get the UItextView data and resize it by using the following code:
UITextView *dummy = [[UITextView alloc] init];
dummy.font = [UIFont systemFontOfSize:14];
dummy.text = cell.textView.text;
CGSize newSize = [dummy sizeThatFits:CGSizeMake(270.0f, 500.0f)];
//get the textView frame and change it's size
CGRect newFrame = cell.textView.frame;
newFrame.size = CGSizeMake(270.0f, fmaxf(newSize.height, 60));
cell.textView.frame = newFrame;
//resize the cell view I add +95 because my cell has borders and other stuff...
CGRect cellFrame = CGRectMake(0, 0, 320, newFrame.size.height+95);
cell.cellView.frame = cellFrame;
I then manage to set the UITableViewCell height using the delegate function heightForRowAtIndexPath:
Now when I run the code and scroll up and down the table cells the behavious isn't always as expected... i.e the cell size isn't always the right size, but if I scroll up and down it sometimes loads up the right size again.
I am thinking that perhaps the dequeueReusableCellWithIdentifier is the issue
cellIdentifier = #"tableCell";
ctTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
Since I am recycling cells of different size with the same identifier...
Can anybody give me some guidelines on how best to solve this issue?
Thanks!!!
I would start by adding UITextView dynamically inside cellForRowAtIndexPath method. assumptions(data array contains the content to be displayed inside cell)
// Defines
#define CELL_TEXTVIEW_WIDTH = 320
#define CELL_TEXTVIEW_HEIGHT = 9999
#define PADDING = 5
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"tableCell";
ctTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if(cell == nil){
cell = [[tableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *_data = [data objectAtIndex:indexPath.row];
CGSize _data_contentsize = [_data sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(CELL_TEXTVIEW_WIDTH, CELL_TEXTVIEW_HEIGHT) lineBreakMode:NSLineBreakModeWordWrap];
UITextView *dummy=[[UITextView alloc] initWithFrame:CGRectMake(5, 5, 290, _data_contentsize +(PADDING * 2))];
// add Font and text color for your textview here
[cell.contentView addSubview:dummy];
return cell;
}
After this calculate the height of the cell under heightForRowAtIndexPath method.
have you implemented following method ?
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
https://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDelegate/tableView:heightForRowAtIndexPath:
you should set height for each row , if they are different from each other

Set frame size image inside UITableView

I have an image size : CGRectMake(100,70,50,50) inside cellForRowAtIndexPath. I need to change the frame size image when the cells is odd
Code is:
if(indexPath.row %2)
{
CGRectMake(200,70,50,50)
}
else
{
CGRectMake(100,70,50,50)
}
In the first time when I load TableView, it's work ok, but when I scroll again and again, the frame size image display is in the wrong position. It changes very funny, I don't know why.
Can you help me
Thanks a lot.
You have set set the frame on your UIImageView subview:
if(indexPath.row %2) {
cell.yourImageView.frame = CGRectMake(200,70,50,50)
} else {
cell.yourImageView.frame = CGRectMake(100,70,50,50)
}
You can do it following way.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UIImageView * imageView;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
if(indexpath.row%2 == 0)
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(200, 70, 50, 50)];
else
{
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 70, 50, 50)];
[cell.contentView addSubview:imageView];
imageView.tag=11;
[imageView release];
}
}
else
{
imageView = (UIImageView*)[cell.contentView viewWithTag:11];
}
// here are couple of other statements
...............
}
Personally, I would create a custom table cell and do something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ImageCell";
ImageCell *cell = (ImageCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[cell configureWithRow:indexPath.row];
}
Then in your custom table cell, create an IBOutlet for your resizable image view and add a method:
-(void)configureWithRow:(NSInteger)row
{
if(indexPath.row %2)
{
self.resizableImageView.frame = CGRectMake(200,70,50,50)
}
else
{
cell.resizableImageView.frame = CGRectMake(100,70,50,50)
}
}
This does a couple of things
You don't have to check for a nil cell because you are guaranteed to get a cell back dequeueReusableCellWithIdentifier as long as the identifier matches one in your storyboard and your view controller is a UITableViewController.
You move the logic for the configuration of the cell to the custom table view cell, which is where it really should be. The view controller shouldn't care about the size of the image in the cell.

Resources