My recent frustration is a UIButton subview in each UITableViewCell of my UITableView which I want to setHidden: according to a specific clause for each indexPath. My code is pretty much the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[self initCell:cell forIndexPath:indexPath];
}
[self updateCell:cell forIndexPath:indexPath];
return cell;
}
and the init and update methods are the following:
- (void)initCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath
{
...
UIButton *btnMy = [UIButton buttonWithType:UIButtonTypeCustom];
btnMy.tag = kButtonMyTag;
[btnMy setFrame:CGRectMake(170, 45, 100, 30)];
[btnMy setBackgroundImage:[UIImage imageNamed:#"btn_image"] forState:UIControlStateNormal];
btnMy.adjustsImageWhenHighlighted = YES;
[btnMy setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
btnMy.titleLabel.font = [UIFont fontWithName:#"MyFont" size:14];
[btnMy addTarget:self action:#selector(btnMyPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:btnMy];
UIImageView *imgViewAccessory = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"table_accessory"]];
cell.accessoryView = imgViewAccessory;
[imgViewAccessory release];
}
- (void)updateCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath
{
UIButton *btnMy = (UIButton *)[cell viewWithTag:kButtonMyTag];
MyObject *object = (MyObject *)[self.dataSource objectAtIndex:indexPath.row];
if(object.meetsCondition)
{
btnMy.hidden = NO;
}
else
{
btnMy.hidden = YES;
}
...
}
The frustrating result is that when scrolling the button shows and hides randomly and not as expected according the if clause in the updateCell method.
Any help would be much appreciated. Thanks in advance!
You should make custom cell and depending upon the condition show and hide the button
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *nib;
static NSString *cellIdentifier= #"cell";
UITableViewCell *theCell = [self.tblView dequeueReusableCellWithIdentifier:cellIdentifier];
if([theCell.contentView subviews]){
for(UIView *view in [theCell.contentView subviews]){
[view removeFromSuperview];
}
}
if(theCell== nil)
{
nib = [[NSBundle mainBundle] loadNibNamed:#"Your custom cell name" owner:self options:nil];
theCell = [nib objectAtIndex:0];
theCell.selectionStyle = UITableViewCellSelectionStyleNone;
}
UIButton *btn=(UIButton*)[theCell.contentView viewWithTag:101];
if(yourcondition)
//hide button
else
//show button
}
This will do
Use this code in your CellForRowAtIndexPath Also.
MyObject *object = (MyObject *)[self.dataSource objectAtIndex:indexPath.row];
if(object.meetsCondition) {
btnMy.hidden = NO;
}
else {
btnMy.hidden = YES;
}
Related
Im trying to add a button into a new cell in a tableview, for example, I need a button under cell '1' if dim is not 0.
However I'm unable to do it. Please enlighten me.
- (void)viewDidLoad
{
[super viewDidLoad];
_displaynum = [NSArray arrayWithObjects:#"1",#"2",#"3", nil];
_displayID = [NSArray arrayWithObjects:#"ID = 1",#"ID = 2",#"ID = 3", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [_displaynum count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *lightIdentifier = #"lightIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:lightIdentifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:lightIdentifier];
}
UISwitch *switchLights = [[UISwitch alloc] initWithFrame:CGRectMake(1.0, 1.0, 20.0, 20.0)];
cell.textLabel.text = [_displayLights objectAtIndex:indexPath.row];
cell.detailTextLabel.text =[_displayLightsID objectAtIndex:indexPath.row];
cell.accessoryView = switchLights;
switchLights.on = NO;
int dim = 1;
if ((dim =! 0)) {
NSArray *insertIndexPaths = [NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:1 inSection:0],
nil];
NSArray *deleteIndexPaths = [NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:2 inSection:0],nil];
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];
[tableView deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
return cell;
}
}
First of all, cellForRowAtIndexPath: is not the right place to insert or delete rows the way you are doing.
cellForRowAtIndexPath: gets called every time a new cell is drawn by iOS. So, this is the place where you can modify your cells and simply return it.
That said, this is what you need to do:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *lightIdentifier = #"lightIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:lightIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:lightIdentifier];
}
int dim = 1;
if (dim != 0 && indexPath.row == 1) {
CGRect buttonRect = CGRectMake(210, 25, 65, 25);
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = buttonRect;
// set the button title here if it will always be the same
[button setTitle:#"Action" forState:UIControlStateNormal];
button.tag = 1;
[button addTarget:self action:#selector(myAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button];
}
return cell;
}
What I want to achieve is something like this. its kind of Facebook or twitter functionality where you have a tableview in which you have a Thread and the thread contains different number of articles. the number of articles varies in each row. So basically Its like i'm sending a post on facebook and people respond to that post and those posts are added under that particular Thread(I'm just concern about the How to display it every thing else is been taken care).here is the picture
I know how to create cell and all but I don't know how to set its size dynamically. any tutorial or any piece of advise to achieve this??
Any Help is appreciated..
thanks
Perhaps this will help you. I am sending you my code, I am using a Custom Cell , which having an Emial on first index, PhoneNumber on second index and Address on third index (in your case Article). I am dynamically changing the height of Address label in CellForRowAtIndexPath ,,, and also cell height in heightForRowAtIndexPath mehthod. Here is my code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"FeedCell";
FeedDetailCell *cell = (FeedDetailCell*)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell==nil) {
cell = (FeedDetailCell*)[[[NSBundle mainBundle] loadNibNamed:#"FeedDetail" owner:nil options:nil] objectAtIndex:0];
}
[tableView setSeparatorColor:[UIColor grayColor]];
switch (indexPath.section) {
case 0:
if (indexPath.row == 0) {
cell.nameLabel.text = #"Telephone";
[cell.detailLabel setText:[_feedDictionary valueForKey:#"mobile"]];
}
else {
cell.nameLabel.text = #"Mobile";
[cell.detailLabel setText:[_feedDictionary valueForKey:#"iPhone"]];
}
break;
case 1:
cell.nameLabel.text = #"E-mail";
[cell.detailLabel setText:[_feedDictionary valueForKey:#"Email"]];
break;
case 2:
cell.nameLabel.text = #"address";
[cell.detailLabel setText:[_feedDictionary valueForKey:#"address"]];
CGSize size = [[_feedDictionary valueForKey:#"address"] sizeWithFont:[UIFont systemFontOfSize:14.0]
constrainedToSize:CGSizeMake(200.0, 400.0) lineBreakMode:UILineBreakModeWordWrap];
CGRect frm = cell.detailLabel.frame;
frm.size.height = size.height;
[cell.detailLabel setFrame:frm];
default:
break;
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 2) {
NSString *address = [_feedDictionary valueForKey:#"address"];
CGSize recommendedSize = [address sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(320, INT_MAX)];
return 44 + recommendedSize.height;
}
else {
return 44;
}
}
You can use this for dynamic cell height
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath;
you can use switch cases and check indexPath.row and indexPath.section to return the required height
take a custom UITableViewCell ,
in .h file
#interface PartnerCell : UITableViewCell {
UILabel *user_name,*lbldate,*lbldesc;
LoadImage *img_trade;
UIImageView *partnerimage;
}
#property (nonatomic, strong) UILabel *user_name,*lbldate,*lbldesc;
#property (nonatomic, strong) LoadImage *img_trade;
#property (nonatomic, strong) UIImageView *partnerimage;
#end
in .m file,
#import "PartnerCell.h"
#implementation PartnerCell
#synthesize user_name,lbldate,lbldesc;
#synthesize img_trade,partnerimage;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
user_name = [[UILabel alloc] initWithFrame:CGRectMake(75,8,200,15)];
[user_name setBackgroundColor:[UIColor clearColor]];
user_name.font = [UIFont fontWithName:#"Arial-BoldMT" size:15];
[user_name setTextColor:[UIColor colorWithRed:70/255.00f green:70/255.00f blue:70/255.00f alpha:1.0]];
[self addSubview:user_name];
lbldate = [[UILabel alloc] initWithFrame:CGRectMake(75,28,200,15)];
[lbldate setBackgroundColor:[UIColor clearColor]];
lbldate.font = [UIFont fontWithName:#"Arial" size:14];
[lbldate setTextColor:[UIColor darkGrayColor]];
[self addSubview:lbldate];
lbldesc = [[UILabel alloc] initWithFrame:CGRectMake(75,45,170,35)];
[lbldesc setBackgroundColor:[UIColor clearColor]];
lbldesc.font = [UIFont fontWithName:#"Arial" size:13];
lbldesc.numberOfLines = 2;
[lbldesc setTextColor:[UIColor darkGrayColor]];
[self addSubview:lbldesc];
img_trade = [[LoadImage alloc] initWithFrame:CGRectMake(3, 5, 54, 55)];
img_trade.userInteractionEnabled = YES;
[self addSubview:img_trade];
}
return self;
}
in main table view class write this code,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"%#",[[Partarray objectAtIndex:indexPath.row-1] valueForKey:#"part_id"]];
cell = (PartnerCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell=nil;
if (cell == nil)
{
cell = [[PartnerCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
//cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[Partarray objectAtIndex:indexPath.row]] autorelease];
cell.selectionStyle= UITableViewCellSelectionStyleGray;
cell.backgroundColor = [UIColor clearColor];
cell.user_name.frame=CGRectMake(75,8,340,15);
cell.lbldate.frame=CGRectMake(75,28,340,15);
cell.lbldesc.frame=CGRectMake(75,45,340,35);
cell.user_name.text = #"user name";
cell.lbldate.text = #"date";
cell.lbldesc.text = #"description";
}
return cell;
}
take condition and add number of objects based on that condition.
Please, explain me: how to programmatically create an UITextView in UITableViewCell (UITableView has a grouped style). The text view size should be equal to size of the cell.
The UITextView has a gap between its text and its border (top left corner), so I need the correct coordinates to properly place the text view on a cell.
UPDATE: I've solved my question. See my self-answer below. Thanks!
It was simple:
textView.frame = CGRectMake(0, 0, cell.contentView.frame.size.width, cell.contentView.frame.size.height);
Here you go:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Prototype Cell"];
UITextField *textfield;
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:#"Prototype Cell"];
textfield = [[UITextField alloc] init];
[cell.contentView addSubview:textfield];
textfield.tag = TEXT_FIELD_TAG; //Suppose you defined TEXT_FIELD_TAG someplace else
}
else
{
textfield = [self.view viewWithTag: TEXT_FIELD_TAG];
textfield.frame = cell.frame;
}
return cell;
}
Set "contentInset" of UITextView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *sCellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:sCellIdentifier];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDetail
reuseIdentifier:sCellIdentifier];
}
UITextView *textView = [UITextView alloc]init];
textView.contentInset = UIEdgeInsetsMake(-8,-8,-8,-8); //Change according ur requirement
textView.frame = cell.frame;
[textView setUserInteractionEnabled:FALSE];
[textView setBackgroundColor:[UIColor clearColor]];
[cell.contentView addSubView:textView];
return cell;
}
I am trying to create a 'blank_star icon' in every cell of a table view, the star should become a 'solid' star after the user clicks on it.
I have created a subclass of UIButton as seen below
//.h file
#interface Bleh : UIButton {
}
+(id)specialInit;
-(void)vvv;
#end
//.m file
#implementation Bleh
+(id) specialInit
{
Bleh* button=[super buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:#"blank_star.png"] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:#"star.png"] forState:UIControlStateDisabled];
[button addTarget:button action:#selector(vvv) forControlEvents:UIControlEventTouchUpInside];
NSLog(#"%d",[button isEnabled]);
return button;
}
-(void)vvv
{
NSLog(#"button tapped");
[self setEnabled:false];
}
#end
I added the subclass of UIButton in my table view's cellforRow: method as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
int row = indexPath.row;
NSString *cc = [array objectAtIndex:row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Configure the cell...
Bleh *button = [Bleh specialInit];
button.frame = CGRectMake(0, 0, 100, 100);
NSLog(#"Button:%# at row number: %i",button, indexPath.row);
cell.textLabel.text = cc;
[cell.contentView addSubview:button];
}
return cell;
}
However I am getting an issue when running the app. For instance, if I click on the cell marked 'a', the star becomes solid as expected.
The strange thing is that after scrolling down, I see some other cells with the solid star as well (see cell 'e').
Can anyone help to explain why this is happening? It seems like the state of the cell is being re-used in other cells. How can I avoid this happening?
You can store the state of the button in a NSMutableArray and when you draw the cell you set if it is enabled or disabled based on the NSMutableArray. To change the value on the Array you should Tag the cell and make the change on your vvv selector.
//.h file
#interface Bleh : UIButton {
NSMutableArray *data;
}
On your function
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
// Configure the cell...
Bleh *button = [Bleh specialInit];
[button setTag:row] // row is the id of the button
if([data objectAtIndex:row] isEqualToString:#"ENABLED"]) [button setEnabled:TRUE];
else [button setEnabled:FALSE];
...
}
On your vvv selector
-(void)vvv:(id)sender {
if([sender isEnabled]) {
[sender setEnabled:FALSE];
[data replaceObjectAtIndex:[sender tag] withObject:#"DISABLED"];
}
else {
[sender setEnabled:TRUE];
[data replaceObjectAtIndex:[sender tag] withObject:#"ENABLED"];
}
}
And you should init the array on your viewDidLoad, lets say for 10 cells
- (void)viewDidLoad
{
...
data = [[NSMutableArray alloc] initWithCapacity:10];
for ( int i = 0; i < 10; i++ ) {
[data addObject:#"ENABLED"];
}
...
}
Cells ARE re-used. I had this problem once myself too.
This might be a bit more memory intensive as it doesn't delete old cells from memory, but it does make coding simpler.
One trick is to do this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int row = indexPath.row;
NSString *CellIdentifier = [NSString stringWithFormat#"Cell %i", row];
NSString *cc = [array objectAtIndex:row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Configure the cell...
Bleh *button = [Bleh specialInit];
button.frame = CGRectMake(0, 0, 100, 100);
NSLog(#"Button:%# at row number: %i",button, indexPath.row);
cell.textLabel.text = cc;
[cell.contentView addSubview:button];
}
i have a uitableview cell added some labels something like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UIImage* myImage = [UIImage imageNamed:#"AccessoryForDealsMain.png"];
UIImageView *MyimageView = [[UIImageView alloc] initWithImage:myImage];
MyimageView.contentMode=UIViewContentModeScaleToFill;
cell.accessoryView=MyimageView;
[MyimageView release];
UILabel *BluePatti = [[UILabel alloc] init];
BluePatti.frame=CGRectMake(0,0,4,44);
BluePatti.backgroundColor = BLUEPATTI;//[UIColor blueColor];
UILabel *BlackLine = [[UILabel alloc] init];
BlackLine.frame=CGRectMake(3,0,1, 45);
BlackLine.backgroundColor = BLACK_LINE;
[BluePatti addSubview:BlackLine];
[BlackLine release];
[cell.contentView addSubview:BluePatti];
[BluePatti release];
UILabel *Seperator = [[UILabel alloc] initWithFrame:CGRectZero];
Seperator.backgroundColor = [UIColor colorWithRed:234/256.0 green:234/256.0 blue:234/256.0 alpha:1.0]; //[UIColor lightGrayColor];
Seperator.frame = CGRectMake(4,43,316,1);
[cell.contentView addSubview:Seperator];
[Seperator release];
}
if(indexPath.section==5)
{
cell.textLabel.text=[self.GenderCellData objectAtIndex:indexPath.row];
cell.textLabel.textColor=CELL_TEXT_COLOR;
cell.textLabel.font=CELL_FONT;
}
else
{
cell.textLabel.text=#"Cells";
cell.textLabel.font=CELL_FONT;
}
return cell;
}
now when i touch cell it shows blue selection above all subviews.How do i change selection frame and colour?
You can create a custom selectedBackgroundView in UITableViewCell that has your own frame and color. This will be shown when the cell is selected instead of the default blue background.
For example:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(10, 20, 30, 40)];
view.backgroundColor = [UIColor redColor];
cell.selectedBackgroundView = view;
[view release];
I face the same problem today , and I solved via this code
First , Inside my custom cell init
self.customerbgImageview = [UIImageView new];
[self.customerbgImageview setFrame:CGRectMake(0 , 11, Width, 66)];
[self.customerbgImageview setBackgroundColor:UIColor_RGB(0, 255, 255, 0.5)];
[self addSubview:self.customerbgImageview];
Second set selectionStyle none
cell.selectionStyle = UITableViewCellSelectionStyleNone;
third in the table method
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
CustomOrderTableViewCell *cell = (CustomOrderTableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
[cell.customerbgImageview setHidden:NO];
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
CustomOrderTableViewCell *cell = (CustomOrderTableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
[cell.customerbgImageview setHidden:YES];
}