Reputation: 284
I have a smaller issue regarding adding a subview in tableView Cell .
I my background for cell is dynamic from the percentage count ..
I am getting the percentage correctly , and the background i can set perfectly , but when i add a new entry .. all screwed up
New entry i get is perfect but the cells which was before remain same even after i resize it .
the magical thing is when i stop and build its all perfect its way ..
Please help me out ..
i use the following code to achieve this ...
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// Dequeue the cell.
speedoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"speedoCell" forIndexPath:indexPath];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
CGRect rect = cell.frame;
NSLog(@"Cell width = %f",rect.size.width);
float cell_width=rect.size.width;
float per;
float viewSize=0.0;
if (self.recent_calls.count == 0) {
cell.title.text =@"No records";
cell.desc.text =@"";
}
else{
NSInteger indexOfFirstname = [self.dbManager.arrColumnNames indexOfObject:@"ex_category"];
NSInteger indexOfSecondname = [self.dbManager.arrColumnNames indexOfObject:@"totle"];
NSString *totle_cat=[NSString stringWithFormat:@"%@", [[self.recent_calls objectAtIndex:indexPath.row] objectAtIndex:indexOfSecondname]];
int x=[totle_cat intValue];
NSLog(@"%d--yoyoyoyoyoyoyoyoyoyo--%d",x,amount_totle);
float result=0;
result=((float)x/(float)amount_totle)*100;
// cell_width is static = 343.0 ..... result is percentage we found
viewSize=(cell_width*result)/100;
NSLog(@"%f----------",viewSize);
UIView *view,*view1;
view=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
view1=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
view1.frame=CGRectMake(5, 5, cell.frame.size.width-10, cell.frame.size.height-3);
[view1.layer setCornerRadius:8.0f];
[view1.layer setMasksToBounds:YES];
[view1.layer setBorderWidth:0.5f ];
CGRect frame = view.frame;
frame.size.width = viewSize;
frame.size.height=cell.frame.size.height-3;
view.frame = frame;
NSLog(@"%f",view.frame.size.width);
[view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"road_panorama1.jpg"]]];
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *visualEffectView;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = CGRectMake(0, 0, viewSize, cell.frame.size.height-3);
[view addSubview:visualEffectView];
[view1 setBackgroundColor:[UIColor whiteColor]];
[view1 insertSubview:view atIndex:0];
[cell.contentView insertSubview:view1 atIndex:0];
UIImage *image;
if ([category isEqualToString:@"Travel"]) {
image=[UIImage imageNamed:@"taxi13.png"];
}
else if ([category isEqualToString:@"Food"]) {
image=[UIImage imageNamed:@"fastfood6.png"];
}
else if ([category isEqualToString:@"Medical"]) {
image=[UIImage imageNamed:@"stethoscope11.png"];
}
else if ([category isEqualToString:@"Shopping"]) {
image=[UIImage imageNamed:@"shopping-cart13.png"];
}
else{
image=[UIImage imageNamed:@"question-mark2.png"];
}
[cell.img setImage:image];
}
return cell;
}
Adding the entry from second view controller
NSString *query= [NSString stringWithFormat:@"insert into ex_man_last (ex_title,ex_amount,ex_description,ex_date,ex_category,ex_upload_date,ex_image,ex_my) values ('%@','%@','%@','%@','%@','%@','%@','%@')",_ex_title.text,_ex_amount.text,_ex_description.text,_ex_date.text,_ex_category.text,datestring,imageName,my ];
// Execute the query.
[self.dbManager executeQuery:query];
and calling the method to get updated entry from db in view will appear method ..
NSString *query =[NSString stringWithFormat:@"SELECT *,sum(ex_amount) as totle FROM ex_man_last where ex_my='%@' GROUP BY ex_category ",query_date];
if (self.recent_calls != nil ) {
self.recent_calls = nil;
}
self.recent_calls = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
NSLog(@"--->%@",_ex_main);
NSLog(@"%lu",(unsigned long)[self.recent_calls count]);
NSInteger indexOfSecondname = [self.dbManager.arrColumnNames indexOfObject:@"totle"];
for (int i=0; i<[self.recent_calls count]; i++) {
NSString *amount=[[self.recent_calls objectAtIndex:i] objectAtIndex:indexOfSecondname] ;
amount_totle=amount_totle+[amount intValue];
}
The whole code is in cell for row at index path method ...
Please help me out ... Thanks in advance ...
Upvotes: 0
Views: 1458
Reputation: 8402
oky , lets try this,
why you are doing every thing in the method cellForRowAtIndexPath
its job is to return the cell for the tableview not to handle all the subviews inside the cell
Cell is the one which handle every thing inside of it. it contains content view which contains your view components, so wy not we allow the cell to handle its view components. For this we need to pass some information to it for example in your case percentage and label texts and the images that u are displaying and rest leave it to cell. This will be use full in feature also if u are modifying the something or adding new components according to (MVC) pattern.
i am not going to do all things just focusing on your issue, in your cellForRowAtIndexPath
you are keep on adding the new views each time even for reused cell also. just remove all view handling code (this will be used in the custom cell)
if u want to just just create a new project and try it out, really i tried your code here and i it is working fine so lets try it a new project so that u are clearly understand and at the end i will also add the gif file to show how the result.
first create a new file with the subclass of UITableViewCell
and give it a name i give it as CustomCell
in CustomCell.h
file
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@interface CustomCell : UITableViewCell
//creating the properties for all view components and also for percentage value that we need for calculating of width
//i took your code hear
@property (nonatomic, assign) CGFloat percentage;
@property (nonatomic, assign) CGFloat viewWidth;
@property (nonatomic, strong) UIView *view;
@property (nonatomic, strong) UIView *view1;
@property (nonatomic, strong) UIBlurEffect *blurEffect ;
@property (nonatomic, strong) UIVisualEffectView *visualEffectView;
@property (nonatomic, strong) UILabel *percentageLabel ;
@end
in CustomCell.m
file
#import "CustomCell.h"
@implementation CustomCell
//we are using this to create new cell just override it and call super
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
{
[self initiliseViewComponents]; //hear we are adding views to cell
}
return self;
}
- (void)setPercentage:(CGFloat)percentage
{
float result=0;
result=((float)percentage/(float)100)*100;
_percentage = result;
_viewWidth = result*343 / 100;
_percentageLabel.text = [NSString stringWithFormat:@"%d",(int)_percentage]; //to show the percentage
}
//at this point we don't no the size of cell,
//same what u are doing in your project just initialising and add it to cell's content view
- (void)initiliseViewComponents
{
_view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
_view1 = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
_blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
_visualEffectView = [[UIVisualEffectView alloc] initWithEffect:_blurEffect];
_percentageLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
[_view addSubview:_visualEffectView];
[_view1 setBackgroundColor:[UIColor whiteColor]];
[_view1 insertSubview:_view atIndex:0];
[self.contentView insertSubview:_view1 atIndex:0];
[self.contentView addSubview:_percentageLabel];
}
- (void)awakeFromNib {
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
//in this method just set frames for your subviews this method will be called automatically
//dont change the cell's frame just the subviews frame
- (void)layoutSubviews
{
_percentageLabel.frame = CGRectMake(self.contentView.bounds.size.width - 50, self.contentView.bounds.origin.y + 10, 50, 50);
CGRect cellFrame = self.contentView.frame;
cellFrame.origin.x += 5;
cellFrame.origin.y += 5;
cellFrame.size.width -= 10;
cellFrame.size.height -= 3;
_view1.frame=cellFrame;
[_view1.layer setCornerRadius:8.0f];
[_view1.layer setMasksToBounds:YES];
[_view1.layer setBorderWidth:0.5f ];
// [_view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"images2.jpg"]]];
[_view setBackgroundColor:[UIColor redColor]];
self.backgroundColor = [UIColor clearColor];
CGRect frame = _view.frame;
frame.size.width = _viewWidth;
frame.size.height = self.frame.size.height-3;
_view.frame = frame;
_visualEffectView.frame = CGRectMake(0, 0, _viewWidth, frame.size.height);
NSLog(@"%f",_view.frame.size.width);
[super layoutSubviews]; //finally call super
}
@end
and come to main controller in main view controller , add a tableview and curette a outlet for it
//in ViewController.h
@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *aTableView;
@property (strong,nonatomic) NSMutableArray *aMutableArray; //to holde percentages
in ViewController.m
implement data source and delegates
- (void)viewDidLoad
{
[super viewDidLoad];
_aMutableArray = [[NSMutableArray alloc]initWithObjects:@(20),@(30),@(50), nil]; //initially it has 3 values we will add some more dynamically
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _aMutableArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL"];
if(cell == nil)
{
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CELL"];
}
cell.percentage = [[_aMutableArray objectAtIndex:indexPath.row] floatValue];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60.0f;
}
//this action method to add new cell dynamically at the top of the tableview
- (IBAction)addButtonAction:(id)sender
{
CGFloat nextPerent = arc4random_uniform(80) % 100; //i took some random percentage values
[_aMutableArray insertObject:[NSNumber numberWithFloat:nextPerent] atIndex:0];
[_aTableView reloadData];
}
so hit run button and the result will be like below
sorry for the gif image i had to compress it the quality is bit low the button with blue color is to add new cell to tableview and the label it not required
hope this helps u
Upvotes: 1
Reputation: 5967
As you are using the reusable cell using speedoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"speedoCell" forIndexPath:indexPath];
so, once the cell is allocated it will be reused again and again.
Consider a case, for the first time you create table with two cells as shown in screenshot 1, with Medical and Travel having 80 & 20% respectively accordingly you created the blur view and added it over white view, finally you inserted view1(view with white background containing blur effect) over the 0th index of contentView of cell.
The above case works perfectly.
Again, you insert new entry (cell) Food, all things messed up!!! The issue here is that as the two cells were created earlier for index 0 and 1 so they were reused, this time data was changed and accordingly you calculated the blur and white area, created the view and inserted again on cell's contentView at index 0, here is the problem.
A view already inserted at index will be visible irrespective of the other views added at the same index over a superview.
To resolve this issue, if the cell is reused than first you have to check if the reuse cell contains the white background view with blur effect then you have to remove it first, recalculate the blur and white area and again insert the view1 at index 0 of the cell's contentView.
This, time as the cell was reused, so first we remove the already inserted view at index 0 from the cell's content view, created the white+blur view again and inserted the newly created view on the 0th index of the cell's content view, and always the newly created one will be shown(as at a time one one will exist and earlier is removed).
Upvotes: 1