Normally in iOS, the cells in a tableview are loading on scrolling. In this time I'm setting a label text. In this case I'm setting this text dynamically. When I'm scrolling down it's working as I expected. But when It's scrolling up, it's not working as expected. Here what I tried.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"moduleCell";
DateTableViewCell *cell = (DateTableViewCell*)[tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"DateTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.backgroundColor = [UIColor clearColor];
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#""]];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
if (self.newsSegmentControl.selectedSegmentIndex == 1) {
[cell.dateView setHidden:NO];
}else{
[cell.dateView setHidden:YES];
}
NSString *day = [self getDayLabel:date];
if ([dateReturned isEqualToString:day]) {
[cell.lblDate setText:#""];
if (self.newsSegmentControl.selectedSegmentIndex == 1) {
[cell.dateView setHidden:YES];
}
}else{
[cell.lblDate setText:day];
dateReturned = day;
}
}
How may I avoid re-draw the label text in cell on scrolling?
Related
When the tableview appears, at first there are no images. But when I drag it, the images in the tableviewcells will appear. I am using a custom tableviewcell class.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UserCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = [[UserCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
NSLog(#"%d",indexPath.row);
[cell setUser:_chatContent[indexPath.row]];
[cell initUI];
return cell;
}
This is my custom cell class:
- (void)awakeFromNib {
[super awakeFromNib];
}
-(BOOL)initUI{
BOOL isSuccess;
self.userImageView = self.user.userImageView;
UIView *superView = self.contentView;
[superView addSubview:self.userImageView];
[self.userImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(superView.mas_top).with.mas_offset(8);
make.bottom.equalTo(superView.mas_bottom).with.mas_offset(-8);
make.left.equalTo(superView.mas_left).with.mas_offset(8);
make.width.equalTo(superView.mas_height).with.mas_offset(-16);
}];
self.userImageView.layer.cornerRadius = self.userImageView.frame.size.width/2;
self.imageView.clipsToBounds = YES;
isSuccess = YES;
return isSuccess;
}
Finally, this is my imageview code:
User *user = _chatContent[i];
NSString *fileName = [NSString stringWithFormat:#"%d",i];
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:#"jpg"];
user.userImageView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:filePath]];
Set the cell's imageView.image to nil before setting image for imageView because tableView reloads cells every time it is scrolled.
After setting imageView.image call setNeedsDisplay and reloadInputViews of UITableViewCell to set image immediately.
[cell reloadInputViews];
[cell setNeedsDisplay];
Hope it helps.
I have two different kind of cell layouts in my tableView.One for normal height and other for expanded height.Both of them are made in XIB.The problem is that the expanded cell is overwriting data.(For example the labels are set with some text which keeps on adding on top of previous text as I go on expanding different cells).
Here's how the cells are loaded.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"Cell";
static NSString *expandedCellIdentifier = #"ExpandedCell";
if (!isExpanded)
{
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 = [[bArray objectAtIndex:indexPath.row]valueForKey:#"Name"];
return cell;
}
else
{
expCell =(ExpandedCell*) [tableView dequeueReusableCellWithIdentifier:expandedCellIdentifier];
if (expCell==nil)
{
NSArray *nibs = [[NSBundle mainBundle]loadNibNamed:#"ExpandedCell" owner:self options:nil];
expCell = nibs[0];
}
UILabel *jTime = [[UILabel alloc]initWithFrame:CGRectMake(27, 6, 72, 10)];
jTime.text = [NSString stringWithFormat:#"%#",timeRequired];
[expCell.background_View addSubview:jTime];
return expCell;
}
return nil;
}
Your label gets added every time when the cell is reused. Use this code in else part of your if condition to avoid that:
expCell = (ExpandedCell*) [tableView dequeueReusableCellWithIdentifier:expandedCellIdentifier];
if (expCell == nil)
{
NSArray *nibs = [[NSBundle mainBundle]loadNibNamed:#"ExpandedCell" owner:self options:nil];
expCell = nibs[0];
UILabel *jTime = [[UILabel alloc]initWithFrame:CGRectMake(27, 6, 72, 10)];
[jTime setTag:100]; //or any value
[expCell.background_View addSubview:jTime];
}
UILabel *jTimeLabel = (UILabel *)[expCell.background_View viewWithTag:100];
jTimeLabel.text = [NSString stringWithFormat:#"%#",timeRequired];
return expCell;
Through this code, your label will get added only once.
You are adding new subview to your expcell every time it's dequeued.
Because of these lines:
UILabel *jTime = [[UILabel alloc]initWithFrame:CGRectMake(27, 6, 72, 10)];
jTime.text = [NSString stringWithFormat:#"%#",timeRequired];
[expCell.background_View addSubview:jTime];
That will add new UILabel everytime the cell is reused.
I have a tableview and I am setting its cells in xib. I have a button in it and when I click it, it changes button color from red to green. When I scroll tableview and come back to green button, it returns to red again. Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"ProgramCell";
ProgramCell *cell = (ProgramCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ProgramCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
[cell.btnHatirlat addTarget:self action:#selector(remind:)
forControlEvents:UIControlEventTouchUpInside];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell.contentView setUserInteractionEnabled: NO];
return cell;
}
- (void) remind:(UIButton *)sender {
UIButton *btnTemp = (UIButton *)sender;
int iTag = btnTemp.tag;
// I want to change image of sender
[btnTemp setBackgroundColor:[UIColor greenColor]];
}
EDIT: I have added my solution as an answer. I hope it will help.
I'd do this:
The Tableview doesn't know how to "remember" the button state when it reuses the cell.
I'd create a NSMutableArray which holds a BOOL (or any other) flag wether the button is "on" or "off". Init that Array with all "off" if you like and then change the value at the index corresponding with the indexPath.row accordingly on click to "on".
Read the value in cellForRowAtIndexPath and change the color accordingly.
If you got multiple sections, create an Array for each section and let it hold an Array for the respective number of cells.
If that tableView is backed up by a DB add a flag for the state (on/off), and save it. Out of my head I don't know wether this requires a reloadData for everything to work as expected.
You need store pressed button's cell index.
Try this->
- (void)remind:(UIButton *)sender {
UIButton *btnTemp = (UIButton *)sender;
self.iTag = btnTemp.tag;
/*For many buttons
[btnTemp setSelected:![btnTemp isSelected]];
self.buttonStates[btnTemp.tag] = #([btnTemp isSelected);
*/
// I want to change image of sender
[btnTemp setBackgroundColor:[UIColor greenColor]];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"ProgramCell";
ProgramCell *cell = (ProgramCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ProgramCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (self.iTag == indexPath.row) {
[cell.btnHatirlat setBackgroundColor:[UIColor greenColor]];
}
/*For many buttons
[cell.btnHatirlat setSelected:[self.buttonStates[indexPath.row] boolValue]];
if ([cell.btnHatirlat isSelected]) {
[cell.btnHatirlat setBackgroundColor:[UIColor greenColor]];
}
*/
[cell.btnHatirlat addTarget:self action:#selector(remind:)
forControlEvents:UIControlEventTouchUpInside];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell.contentView setUserInteractionEnabled: NO];
return cell;
}
Good luck!
Here is my solution and I want to thank again to #Bernard Grabowski and #MobiDevCom. I have saved clicked button's section and row number and checked if it is clicked or not.
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"ProgramCell";
ProgramCell *cell = (ProgramCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ProgramCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSString* strTemp = [NSString stringWithFormat: #"%d/%d", indexPath.section, indexPath.row ];
//To check clicked button at current section and row is clicked
for (int i = 0; i < buttonClickedArray.count; i++)
{
if([[self.buttonClickedArray objectAtIndex:i] isEqualToString:strTemp])
[cell.btnHatirlat setBackgroundColor:[UIColor greenColor]];
}
NSString *str = [[etkinlikArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
[cell.btnHatirlat addTarget:self action:#selector(remind:)
forControlEvents:UIControlEventTouchUpInside ];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell.contentView setUserInteractionEnabled: NO];
}
return cell;
}
- (void) remind:(UIButton *)sender
{
//to get clicked button's indexpath
UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
NSIndexPath *clickedButtonPath = [self.tableProgram indexPathForCell:clickedCell];
self.currentIndexPathStr = [NSString stringWithFormat: #"%d/%d", clickedButtonPath.section, clickedButtonPath.row];
[self.buttonClickedArray addObject:currentIndexPathStr];
[btnTemp setBackgroundColor:[UIColor greenColor]];
}
I have a UITableView with a Custom Cell. Some custom cells are being loaded with an image.
And I'm adding a custom separator for the cells that have an image. The problem arises on scrolling. Whenever I scroll, the UIView opacity changes.
Here is my code :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
if (cell && (NSNull*) imageString != [NSNull null])
{
UIView* separatorLineView; = [[UIView alloc] initWithFrame:CGRectMake(0, -1, 320, 5)];
separatorLineView.backgroundColor = [UIColor blackColor];
separatorLineView.alpha = 0.2;
[cell.contentView addSubview:separatorLineView];
}
Alpha for the view given is 0.2 and on scrolling it becomes thicker and thicker. How can I solve this issue?
Do what #rmaddy and #rdelmar have suggested but since you're using a custom cell anyways, the quickest way, imho, would be:
Add this line to the cell's contentView via the Interface Builder directly
#property (strong, nonatomic) IBOutlet UIView *vwLine;
also #synthesize vwLine;
Set it's frame, background color & alpha value (obviously)
Set it's hidden property to YES
When you do the imageString != [NSNull null] check
if TRUE then [cell.vwLine setHidden:NO];
Example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell"
owner:self
options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
if (imageString != [NSNull null]) {
[cell.vwLine setHidden:NO];
}
}
I think the problem is that you're adding a separatorLineView to cells that already have one as you scroll, so what you're seeing is lines on top of other lines. You could fix that by adding a tag to your line view, and checking if the cell has a subview with that tag, and if so, don't add another line.
In your code might be problem of reusability of cell. So try with following code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
.
.
.
.
if(cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
if(cellHasImage == YES)
{
//// just initialize UIView and add as addSubview of cell.contentView
UIView* separatorLineView; = [[UIView alloc] init];
separatorLineView.frame = CGRectMake(0, -1, 320, 5);
separatorLineView.tag = 111; // set whatever you like
[cell.contentView addSubview:separatorLineView];
}
}
.
.
.
/// get UIView base on it's tag
if(cellHasImage == YES)
{
UIView* separatorLineView; = (UIView *) [cell.contentView viewWithTag:111];
separatorLineView.backgroundColor = [UIColor blackColor];
separatorLineView.alpha = 0.2;
}
.
.
.
return cell;
}
In cellForRowAtIndexPath I am adding a UIImageView to cell.contentView. The problem is that when the cell scrolls off the screen and back on, it adds the same image again on top of the one that is already there. This happens continuously until I get a very stacked-up blurry image.
Do you have to keep removing any image views that you add to cell.contentView? If so, in what delegate method do you do that in?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellIdentifier";
MyTableCell *cell = (MyTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.jpg"]];
imageView.center = CGPointMake(310, 48);
[cell.contentView addSubview:imageView];
[imageView release];
return cell;
}
If you don't want to keep putting imageViews in your cell, you have to do all the customization inside the if(cell==nil) block, otherwise it will add one every time a cell recycles. When using cell recycling you always want to keep anything that is consistent for all of your cells in that block so that they only get added once.
Ex:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellIdentifier";
MyTableCell *cell = (MyTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
//Add custom objects to the cell in here!
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.jpg"]];
imageView.center = CGPointMake(310, 48);
[cell.contentView addSubview:imageView];
[imageView release];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
If each cell should need a different image, you can try something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellIdentifier";
static const int ImageViewTag = 1234; //any integer constant
MyTableCell *cell = (MyTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UIImageView *imageView;
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
//Add custom objects to the cell in here!
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0, imgWidth, imgHeight)];
imageView.center = CGPointMake(310, 48);
imageView.tag = ImageViewTag;
[cell.contentView addSubview:imageView];
[imageView release];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
else
{
imageView = [cell viewWithTag:ImageViewTag];
}
imageView.image = yourUIImageForThisCell;
return cell;
}