How to set the same width between custom UITableViewCells and UITableView? - ios

I created several cells with Interface Builder, and I'm using them to fill a UITableView. In other words, I have 3 classes for 3 different kinds of cell, and an other view which contains a UITableView.
- My UITableView containing different kinds of cells :
Here's my problem :
On the iPhone emulator, it looks great. But on the iPad emulator, the custom cells width is fixed. The UITableView width fits to the screen width, so it's good, but the UITableViewCells does not fit to the UITableView. I want to force the custom UITableViewCells to take the UITableView width.
Is there anything to do in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPathmethod, where I instanciate my custom cells ?
Or do I have to write a thing like self.fitToParent; in the custom cells header file ?
EDIT (schema) :
EDIT 2 (cellForRowAtIndexPath method) :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifierType1 = #"cellType1";
static NSString *cellIdentifierType2 = #"cellType2";
NSString *currentObjectId = [[myTab objectAtIndex:indexPath.row] type];
// Cell type 1
if ([currentObjectId isEqualToString:type1])
{
CelluleType1 *celluleType1 = (CelluleType1 *)[tableView dequeueReusableCellWithIdentifier:cellIdentifierType1];
if(celluleType1 == nil)
celluleType1 = [[CelluleType1 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifierType1];
celluleType1.lblAuteur.text = #"Type1";
return celluleType1;
}
// Cell type 2
else if ([currentObjectId isEqualToString:type2])
{
CelluleType2 *celluleType2 = (CelluleType2 *)[tableViewdequeueReusableCellWithIdentifier:cellIdentifierType2];
if(celluleType2 == nil)
celluleType2 = [[CelluleType2 alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifierType2];
celluleType2.lblAuteur.text = #"Type2";
return celluleType2;
}
else
return nil;
}
}

I think uitableviewcell's width is the same as the tableview's width.You can try to set cell's background color to test it. cell.backgroundColor = [UIColor redColor] ;
You should create a class which inherit from UITableViewCell and override it's method - (void)layoutSubviews , adjust your content's frame there.

I resolved my problem using the following code in each custom cell class. It's not very clean, but I can't spend one more day on this issue...
- (void)layoutSubviews
{
CGRect contentViewFrame = self.contentView.frame;
contentViewFrame.size.width = myTableView.bounds.size.width;
self.contentView.frame = contentViewFrame;
}
Thank you for your help KudoCC.

- (void)awakeFromNib {
[super awakeFromNib];
// anything you write in this section is taken with respect to default frame of width 320.
}
awakeFromNib is called when [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; is processed- anything you write in section is taken with respect to default frame of width 320.
You need to make another custom function and call it after cell gets initialized.
For eg:-
#implementation CheckinTableViewCell{
UILabel *NameLabel;
UILabel *rollLabel;
}
- (void)awakeFromNib {
[super awakeFromNib];
NameLabel = [[UILabel alloc] initWithFrame:CGRectZero];
rollLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:NameLabel];
[self.contentView addSubview:rollLabel];
}
-(void) bindView{
NameLabel.frame = CGRectMake(10, 10, self.contentView.frame.size.width-20, 20);
rollLabel.frame = CGRectMake(10, 30, NameLabel.frame.size.width, 20);
}
and call this function in tableview cellForRowAtIndex:-
-(UITableViewCell*) tableView: (UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
CheckinTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if(cell ==nil){
cell = [[CheckinTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.name = #"Harry";
cell.rollno = #"123456";
[cell bindView];
return cell;
}

Related

How to dynamically set a cell position in a UITableView

I am creating a tableView with 4 cells. And the cells must be divided into various size depending on the orientation of the device.
1st column and 2nd column will have the same width, while 3rd column will be the largest of them all and the 4th column will be a smaller than the 3rd column but not smaller than the 1st nor 2nd.
Is there a way to do it dynamically?
Here is the template
I am having trouble in computing the width, here's what I have so far. I haven't created l2,l3 and l4 yet cause I am having a hard time in computing the width of it
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cells" forIndexPath:indexPath];
UIInterfaceOrientation newOrientation = [UIApplication sharedApplication].statusBarOrientation;
UILabel *typeLabel = [[UILabel alloc] init];
if (cell==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cells"];
}
if(newOrientation == UIInterfaceOrientationLandscapeLeft || newOrientation == UIInterfaceOrientationLandscapeRight)
{
l1 = [[UILabel alloc] initWithFrame:CGRectMake((self.tableView.bounds.size.width/15+20), 50, self.tableView.bounds.size.width/12, 21)];
}
else
{
l1 = [[UILabel alloc] initWithFrame:CGRectMake((self.tableView.bounds.size.width/15+50), 50, self.tableView.bounds.size.width/12, 21)];
}
[cell.contentView l1];
[cell.contentView l2];
[cell.contentView l3];
[cell.contentView l4];
return cell;
}
Create a custom TableView Cell named "CustomCell". You can create it using new File with xib option.
CustomCell.h
#interface CustomCell : UITableViewCell
#end
CustomCell.m
#implementation MessagesTableViewCell
//perform your custom implementation here.
#end
CustomCell.xib
Adjust the labels in the cell in the user interface using auto-layout. You can add 4 labels as you need with first 2 labels having a constant width and last one with the width you want and let the center(3rd) label stretch across 2nd label and 4th label. It will help you manage the UI in much easier way. Auto-Layout is a feature which helps to build content for different sizes. You can find dynamic table view cell using auto layout at https://www.sitepoint.com/self-sizing-cells-uitableview-auto-layout/
Using it in your TableView Class
static NSString *cellIdentifier = #"CustomCell";
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
return cell;
}
I hope this helps you.
Updated code implementation with programmatic computation and Orientation change
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/////////////////////////Programatic Implementation///////////////////////////////////
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(cell==nil){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
if (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)) {
//orientation is Portrait
long widthForL1L2 = tableView.frame.size.width * .10;
long widthForL3 = tableView.frame.size.width * .60;
long widthForL4 = tableView.frame.size.width * .20;
UILabel *l1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, widthForL1L2, cell.frame.size.height)];
l1.backgroundColor = [UIColor redColor];
[cell addSubview:l1];
UILabel *l2 = [[UILabel alloc] initWithFrame:CGRectMake(widthForL1L2, 0, widthForL1L2, cell.frame.size.height)];
l2.backgroundColor = [UIColor yellowColor];
[cell addSubview:l2];
UILabel *l3 = [[UILabel alloc] initWithFrame:CGRectMake(l2.frame.origin.x+widthForL1L2, 0, widthForL3, cell.frame.size.height)];
l3.backgroundColor = [UIColor greenColor];
[cell addSubview:l3];
UILabel *l4 = [[UILabel alloc]initWithFrame:CGRectMake(l3.frame.origin.x+widthForL3, 0, widthForL4,cell.frame.size.height)];
l4.backgroundColor = [UIColor blueColor];
[cell addSubview:l4];
}else{
//orientation is Landscape
//perform the same calculation as above or modify it according to your needs in landscape orientation.
}
return cell;
}
Do not forget to include this function of orientation change. This function calls table reload when phone orientation changes.
//Available iOS version >=8.0
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
//Reload the tableview on orientation change, to match the new width of the table.
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[self.tableView reloadData];
} completion:nil];
}

UItableviewcells with background image not filling the whole width of screen?

Hi i am new for ios and in my app i have created one UITableView and i have set background image for UITableViewcell but image not filling the whole width of screen as like below screen. Why this problem is occuring?
I mean UITableViewCell left and right sides gap is coming images is not filling whole cell width.
please help me someone
my code:-
#import "TableViewController.h"
#interface TableViewController ()
{
UITableView * tableList;
TableCell * Cell;
}
#end
#implementation TableViewController
- (void)viewDidLoad {
[super viewDidLoad];
tableList = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen]bounds].size.width, [[UIScreen mainScreen]bounds].size.height) style:UITableViewStylePlain];
tableList.delegate = self;
tableList.dataSource = self;
tableList.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.view addSubview:tableList];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"MyCell";
Cell = (TableCell *)[tableList dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (Cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableCell" owner:self options:nil];
Cell = [nib objectAtIndex:0];
}
//UIImageView *imageBackground = [[UIImageView alloc] init];
if (indexPath.row == 0) {
Cell.backGroundImage.image = [UIImage imageNamed:#"cell_top.png"];
} else if (indexPath.row == 9) {
Cell.backGroundImage.image = [UIImage imageNamed:#"cell_bottom.png"];
} else {
Cell.backGroundImage.image = [UIImage imageNamed:#"cell_middle.png"];
}
//imageBackground.contentMode = UIViewContentModeScaleToFill;
//Cell.backgroundView = imageBackground;
return Cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 44.0;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
if ([cell respondsToSelector:#selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:#selector(setPreservesSuperviewLayoutMargins:)]) {
[cell setPreservesSuperviewLayoutMargins:NO];
}
if ([cell respondsToSelector:#selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
#end
Try to set the layoutMargins property of the cells and the UITableView to UIEdgeInsetsZero.
- (void) viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
tableList.layoutMargins = UIEdgeInsetsZero;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
[...]
Cell.layoutMargins = UIEdgeInsetsZero;
return Cell;
}
Also check for the contentMode of the UIImageview.
Cell.backGroundImage.contentMode = UIViewContentModeScaleAspectFill;
try set contentInset on Left = 0
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
Use Debug View Hierarchy to figure out UITableView, UITableViewCell or UIImage is not filling the whole width of screen
http://www.raywenderlich.com/98356/view-debugging-in-xcode-6
Please check your "TableCell" in the storyboard. Did you select custom insets option for your custom cell?
Rather than setting up your table view with code, you want to do this in a storyboard. Then you'll want to use auto layout to connect constraints from the table view to the view controller's view. There are lots of tutorials available to teach you how to do this. Learning this will make things much easier in the long run.
Change the name of your tableList property to tableView. That will make more sense to other developers (including yourself in the future), since that's what it is (a UITableView instance).
Your cell is named Cell with a capital C, but you don't want to name properties with capital letters. Also, it doesn't need to be a class property the way it's being used. Remove it from the #interface section.
Coding Guidelines for Cocoa
Remove the -numberOfSectionsInTableView: method. The default is 1, so you don't need code to return the default value.
Instead of -dequeueReusableCellWithIdentifier:, use -dequeueReusableCellWithIdentifier:forIndexPath:. Then you won't need to follow it with a test to see if a cell was returned (it always will be). You'll need to register your nib with -registerNib:forCellReuseIdentifier:. Or better yet, just design it in the storyboard.
It appears that your custom table view cell has a UIImageView named backGroundImage. That should be added as a subview to the cell's backgroundView property (which you'll need to create - the view, not the property, which is already part of UITableViewCell). Set the image view's autoresizingMask so it will resize with the backgroundView:
- (void)awakeFromNib
{
[super awakeFromNib];
self.backgroundView = [[UIView alloc] initWithFrame:self.bounds];
self.backGroundImage.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.backGroundImage.frame = self.backgroundView.bounds;
[self.backgroundView addSubview:self.backGroundImage];
}
Remove the -tableView:heightForRowAtIndexPath: method. You only want to use this if you return different values. The default row height is 44.0, so you don't need to do anything else.

UITableView Cell's expanded view doesn't show subviews?

I am expanding a UITableView cell on click.When the cell expands I have to load a UIView into it.My problen is that I am able to see the UIView on few occasions and sometimes it doesn't display ? The UIView is to be loaded in each and every expanded cell.
Expansion is done like this:-
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat kExpandedCellHeight =300;
CGFloat normalCellHeight = 94;
if ([self.expandedCells containsObject:indexPath]) {
return kExpandedCellHeight;
}else{
return normalCellHeight;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"Cell";
ListCell *cell =(ListCell*) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell==nil) {
NSArray *nibs = [[NSBundle mainBundle]loadNibNamed:#"ListCell" owner:self options:nil];
cell = nibs[0];
}
cell.Name.text = [[nameArray objectAtIndex:indexPath.row]valueForKey:#"opName"];
if (isExpanded) {
backgroundView = [[UIView alloc]initWithFrame:CGRectMake(0, 95, 320,205)];
[backgroundView setBackgroundColor:[UIColor colorWithRed:(235/255) green:(235/255) blue:(235/255) alpha:0.1]];
[cell.contentView addSubview:backgroundView];
container = [[UIView alloc]initWithFrame:CGRectMake(40, 67, 240, 120)];
container.backgroundColor = [UIColor whiteColor];
//I am adding buttons to this scrollview after webservice response,once buttons are loaded I am trying to load the above container on the background view.
container_scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(20, 5, 220, 110)];
[container_scrollView setBackgroundColor:[UIColor whiteColor]];
[container addSubview:container_scrollView];
}
return cell;
}
Now I do get response from webservice.Buttons are added as well.However I can see the container view loaded sometimes and sometimes it doesn't show.What must be the reason?What is causing this behaviour?
This is how I load the container onto background view.
//After container is loaded with buttons.
if(backgroundView){
[backgroundView addsubView:container];
}
Declaration stuff:
#interface ListViewController ()
{
UIView *backgroundView;//Used in expanded cell.
UIView *container;
BOOL isExpanded; //I set this to NO in viewDidLoad initially.
UIScrollView *container_scrollView;
}
You should consider having two different cells on your storyboard or two xib files, each with its correspoding cellidentifier. One will be your normal cell and the other the expanded cell. Then whenever a user taps on one normal cell you should 'replace'(redraw) that specific cell with your second type cell (an expanded cell).
UPDATE
For performing the update of the cells you could use any of these methods. more here
reloadData
reloadRowsAtIndexPaths:withRowAnimation:
reloadSections:withRowAnimation:
Those will cause that some of your Table View Data Source delegate methods get called again, you should then use some logic to decide which kind of cell to draw. A quick draft:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier;
// Here you should implement your custom logic to check if you want a basic or expanded cell.
if (IWantBasicCell) {
cellIdentifier = #"basicCell";
} else {
cellIdentifier = #"expandedCell"
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
[cell myCustomLoadInformationMethod:myCustomData];
return cell;
}

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