UITableViewCell何时完成布局子视图?

如何解决UITableViewCell何时完成布局子视图?

如下图所示,我想添加一个尖端(最大的UIView的子视图),该尖端与UITableViewCell中的UIStackView保持对齐。 UITableViewCell中UIStackView的宽度是动态的,因此我需要将提示视图放置在UITableViewCell布局的子视图之后。

我试图在willDisplayCell函数中添加提示视图,但是到达的位置不是最终位置。

此外,我尝试在UITableViewCell的layoutSubviews函数中设置笔尖视图的位置。由于多次调用此功能,因此笔尖最终会到达预期的位置,但开始时会闪烁。

那我应该在哪个函数中添加提示视图?

--------编辑--------

添加代码段以使其更清晰。我只想知道应该将以下代码放在哪里,以便rect.origin.x是stackview的最终位置。

UIView *view = self.view;
CGRect rect = [cell.stackView convertRect:cell.stackView.bounds toView:view];
[self.tipView.leadingAnchor constraintEqualToAnchor:view.leadingAnchor constant:rect.origin.x].active = YES;
[self.tipView.trailingAnchor constraintLessThanOrEqualToAnchor:view.trailingAnchor constant:-marginConstant].active = YES;
[self.tipView.bottomAnchor constraintEqualToAnchor:self.tableView.bottomAnchor constant:-TSkBubbleClickAreaHeight-marginConstant].active = YES;
[view layoutIfNeeded];

enter image description here

解决方法

修改

要尝试直接回答您的问题,您要知道对单元格所做的任何事情都将完全完成单元格内容的布局。因此,要确切知道单元的堆栈视图何时被布置,可以对堆栈视图进行子类化,并在该子类中实现layoutSubviews


由于尚不清楚您到底在做什么,我将提供几种方法...

如果您在表格视图上调用reloadData,则可以尝试以下操作:

[tableView reloadData];

dispatch_async(dispatch_get_main_queue(),^{
    [self showTipView:pth];
});

如果您呼叫insertRowsAtIndexPaths,则可以尝试以下操作:

[CATransaction begin];

[CATransaction setCompletionBlock:^{
    [self showTipView:pth];
}];

[self->tableView insertRowsAtIndexPaths:@[pth] withRowAnimation:UITableViewRowAnimationRight];

[CATransaction commit];

这是一个例子(我试图保持简单,并提供清晰的注释):

ExampleTableViewCell.h

//
//  ExampleTableViewCell.h
//  Created by Don Mag on 9/15/20.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
@interface ExampleTableViewCell : UITableViewCell
- (void) configureCell:(NSString *)s;
- (UIStackView *)getStackRef;
@end
NS_ASSUME_NONNULL_END

ExampleTableViewCell.m

//
//  ExampleTableViewCell.m
//  Created by Don Mag on 9/15/20.
//

#import "ExampleTableViewCell.h"

@interface ExampleTableViewCell ()
{
    UIStackView *stackView;
    UILabel *label;
}
@end

@implementation ExampleTableViewCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (void) commonInit {
    label = [UILabel new];
    label.backgroundColor = [UIColor yellowColor];

    stackView = [UIStackView new];
    stackView.translatesAutoresizingMaskIntoConstraints = NO;
    
    [stackView addArrangedSubview:label];
    
    [self.contentView addSubview:stackView];
    
    UILayoutGuide *g = self.contentView.layoutMarginsGuide;
    
    [NSLayoutConstraint activateConstraints:@[
        
        // constrain stack view Top: 0 / Trailing: 0 / Bottom: 0
        [stackView.topAnchor constraintEqualToAnchor:g.topAnchor constant:0.0],[stackView.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:0.0],[stackView.bottomAnchor constraintEqualToAnchor:g.bottomAnchor constant:0.0],]];

}
- (void) configureCell:(NSString *)s {
    label.text = s;
}

- (UIStackView *)getStackRef {
    return stackView;
}

@end

ExampleViewController.h

//
//  ExampleViewController.h
//  Created by Don Mag on 9/15/20.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
@interface ExampleViewController : UIViewController
@end
NS_ASSUME_NONNULL_END

ExampleViewController.m

//
//  ExampleViewController.m
//  Created by Don Mag on 9/15/20.
//

#import "ExampleViewController.h"
#import "ExampleTableViewCell.h"

@interface ExampleViewController () <UITableViewDataSource,UITableViewDelegate,UIScrollViewDelegate>
{
    NSMutableArray *myData;
    NSMutableArray *sampleStrings;
    
    UIView *tipView;
    
    UIButton *reloadButton;
    UIButton *insertButton;
    UITableView *tableView;
    
    NSInteger idx;
    NSInteger insertRow;
}
@end

@implementation ExampleViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // row number to insert and show the tipView
    insertRow = 7;
    
    // init some sample data
    myData = [NSMutableArray new];
    for (int i = 0; i < 30; i++) {
        NSString *s = [NSString stringWithFormat:@"Row %i",i];
        [myData addObject:s];
    }
    
    // a few example strings
    sampleStrings = [NSMutableArray new];
    [sampleStrings addObject:@"Short text example."];
    [sampleStrings addObject:@"A little more text example."];
    [sampleStrings addObject:@"Considerably longer text for this example."];
    
    // index for sampleStrings array
    idx = -1;

    // create a "tip view"
    //  red background view with
    //  green background label
    //  label is inset 4-pts on each side
    tipView = [UIView new];
    tipView.backgroundColor = [UIColor redColor];
    UILabel *tipLabel = [UILabel new];
    tipLabel.backgroundColor = [UIColor greenColor];
    tipLabel.text = @"This is the tip!";
    
    tipView.translatesAutoresizingMaskIntoConstraints = NO;
    tipLabel.translatesAutoresizingMaskIntoConstraints = NO;
    
    [tipView addSubview:tipLabel];
    [NSLayoutConstraint activateConstraints:@[
        [tipLabel.topAnchor constraintEqualToAnchor:tipView.topAnchor constant:4.0],[tipLabel.leadingAnchor constraintEqualToAnchor:tipView.leadingAnchor constant:4.0],[tipLabel.bottomAnchor constraintEqualToAnchor:tipView.bottomAnchor constant:-4.0],[tipLabel.trailingAnchor constraintEqualToAnchor:tipView.trailingAnchor constant:-4.0],]];
    
    // init buttons
    reloadButton = [UIButton new];
    [reloadButton setTitle:@"Reload" forState:UIControlStateNormal];
    [reloadButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [reloadButton setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
    [reloadButton setBackgroundColor:[UIColor blueColor]];

    insertButton = [UIButton new];
    [insertButton setTitle:@"Insert" forState:UIControlStateNormal];
    [insertButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [insertButton setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
    [insertButton setBackgroundColor:[UIColor blueColor]];
    
    // init table view
    tableView = [UITableView new];
    
    for (UIView *v in @[reloadButton,insertButton,tableView]) {
        v.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:v];
    }
    
    UILayoutGuide *g = self.view.safeAreaLayoutGuide;
    
    [NSLayoutConstraint activateConstraints:@[
        
        // buttons at top
        [reloadButton.topAnchor constraintEqualToAnchor:g.topAnchor constant:20.0],[reloadButton.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:24.0],[insertButton.topAnchor constraintEqualToAnchor:g.topAnchor constant:20.0],[insertButton.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-24.0],[insertButton.leadingAnchor constraintEqualToAnchor:reloadButton.trailingAnchor constant:20.0],[insertButton.widthAnchor constraintEqualToAnchor:reloadButton.widthAnchor],// constrain tableView Top: 20-pts from buttons / Leading: 0 / Trailing: 0 / Bottom: 0
        [tableView.topAnchor constraintEqualToAnchor:reloadButton.bottomAnchor constant:20.0],[tableView.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:0.0],[tableView.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:0.0],[tableView.bottomAnchor constraintEqualToAnchor:g.bottomAnchor constant:0.0],]];
    
    [tableView registerClass:[ExampleTableViewCell class] forCellReuseIdentifier:@"exCell"];

    tableView.delegate = self;
    tableView.dataSource = self;
    
    [reloadButton addTarget:self action:@selector(btnTap:) forControlEvents:UIControlEventTouchUpInside];
    [insertButton addTarget:self action:@selector(btnTap:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [tipView removeFromSuperview];
}
- (void)btnTap:(UIButton *)btn {
    
    // remove tipView if it's showing
    [tipView removeFromSuperview];

    NSString *s = sampleStrings[++idx % 3];

    if (btn == reloadButton) {
        [self reloadMethod:s];
    } else {
        [self insertMethod:s];
    }
}
- (void)insertMethod:(NSString *)s {
    
    // IndexPath for cell you want
    __block NSIndexPath *pth = [NSIndexPath indexPathForRow:insertRow inSection:0];
    
    [myData insertObject:s atIndex:pth.row];
    
    [CATransaction begin];
    
    [CATransaction setCompletionBlock:^{
        [self showTipView:pth];
    }];

    [self->tableView insertRowsAtIndexPaths:@[pth] withRowAnimation:UITableViewRowAnimationRight];
    
    [CATransaction commit];
}
- (void)reloadMethod:(NSString *)s {

    // IndexPath for cell you want
    __block NSIndexPath *pth = [NSIndexPath indexPathForRow:insertRow inSection:0];

    [myData insertObject:s atIndex:pth.row];

    [tableView reloadData];

    dispatch_async(dispatch_get_main_queue(),^{
        [self showTipView:pth];
    });
    
}
- (void)showTipView:(NSIndexPath *)pth {
    
    // get a reference to the cell
    ExampleTableViewCell *cell = [tableView cellForRowAtIndexPath:pth];
    
    // if row is not visible
    if (!cell) {
        return;
    }
    
    // get a reference to the cell's stack view
    UIStackView *stack = [cell getStackRef];
    
    // add tipView to self.view
    [self.view addSubview:tipView];
    
    // constrain tipView
    //  Leading to stack view's Leading
    //  Bottom to cell's Top - 4
    [NSLayoutConstraint activateConstraints:@[
        [tipView.leadingAnchor constraintEqualToAnchor:stack.leadingAnchor constant:0.0],[tipView.bottomAnchor constraintEqualToAnchor:cell.topAnchor constant:-4.0],]];
    
    // if we want to "fade-in" the tipView
    [tipView setAlpha:0.0];
    [UIView animateWithDuration:0.3
                     animations:^{
        [self->tipView setAlpha:1.0];
    }];
    
}

- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
    ExampleTableViewCell *c = (ExampleTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"exCell" forIndexPath:indexPath];
    [c configureCell:myData[indexPath.row]];
    return c;
}

- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [myData count];
}

@end

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-