在表格视图单元格中动态调整子视图的大小

Resizing a subview dynamically in tableview cell

我有一个关于在 tableView Cell 中添加子视图的小问题。

我的单元格背景是动态的百分比计数..

我得到的百分比是正确的,我可以完美地设置背景,但是当我添加一个新条目时.. 一切都搞砸了

我得到的新条目是完美的,但即使在我调整它的大小之后,之前的单元格仍然保持不变。

神奇的是当我停下来并按照自己的方式完美地建造它时..

请帮帮我..

我使用下面的代码来实现这个...

-(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;

}

从第二个视图控制器添加条目

 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];

并且在视图中调用从数据库中获取更新条目的方法将出现方法..

 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];
}

整个代码在索引路径方法的行单元格中...

请帮帮我...提前致谢...

当您使用可重复使用的电池时 speedoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"speedoCell" forIndexPath:indexPath];

因此,一旦单元格被分配,它将被一次又一次地重复使用。

考虑一个案例,您第一次使用两个单元格创建 table,如屏幕截图 1 所示,医疗和旅行分别有 80% 和 20% 因此您创建了模糊视图并将其添加到白色视图,最后您在单元格的 contentView 的第 0 个索引上插入了 view1(包含模糊效果的白色背景视图)。

以上案例完美运行。

再次,您插入新条目(单元格)食物,一切都搞砸了!!! 这里的问题是,由于这两个单元格是早些时候为索引 0 和 1 创建的,因此它们被重复使用,这次数据被更改,因此您计算了模糊和白色区域,创建了视图并再次插入到索引 0 处的单元格的 contentView 上,问题来了。

已在索引处插入的视图将可见,而不管在父视图上的同一索引处添加的其他视图。

要解决此问题,如果单元格被重用,则首先必须检查重用单元格是否包含具有模糊效果的白色背景视图,然后必须先将其删除,重新计算模糊和白色区域,并再次在单元格的 contentView 的索引 0 处插入 view1。

这次单元格被重用了,所以首先我们从单元格的内容视图中删除索引 0 处已经插入的视图,再次创建白色+模糊视图并将新创建的视图插入到单元格的第 0 个索引处单元格的内容视图,并且始终会显示新创建的内容(因为一次会存在一个,之前的内容会被删除)。

好的,让我们试试这个,

为什么你在方法中做每件事 cellForRowAtIndexPath 它的工作是 return tableview 的单元格不处理单元格内的所有子视图

单元格是处理其中所有内容的单元格。它包含包含您的视图组件的内容视图,因此我们不允许单元格处理其视图组件。为此,我们需要将一些信息传递给它,例如您的案例百分比和标签文本以及您正在显示的图像,其余的将其留给单元格。如果您根据 (MVC) 模式修改某些内容或添加新组件,这也将使用完整的功能。

我不会只关注您的问题,在您的 cellForRowAtIndexPath 中,您每次都会继续添加新视图,即使是重复使用的单元格也是如此。只需删除所有视图处理代码(这将在自定义单元格中使用)

如果你只想创建一个新项目并尝试一下,真的我在这里尝试了你的代码并且我工作正常所以让我们尝试一个新项目以便你清楚地理解并且最后我还将添加 gif 文件以显示结果。

首先用UITableViewCell的子类创建一个新文件并给它起一个名字,我给它起的名字是CustomCell

CustomCell.h文件中

#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

CustomCell.m文件中

#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

然后来到主控制器 在主视图控制器中, 添加一个 tableview 并为其添加一个 outlet

//in ViewController.h
@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *aTableView;
@property (strong,nonatomic) NSMutableArray *aMutableArray; //to holde percentages

ViewController.m中实现数据源和委托

- (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];
}

点击运行按钮,结果如下

抱歉,我不得不压缩 gif 图像,质量有点低蓝色按钮用于向 tableview 添加新单元格,不需要标签

希望对你有帮助