判断一个tablecell是否真的被用户在tableview中看到
Determine if a tablecell is really seen by user in tableview
我正在尝试找到一种方法来检查我的几个 table 单元格是否真的被用户看到了(比方说,如果单元格至少显示 1px,我认为它被看到了).并且还需要确保如果用户上下滚动,我将需要触发该方法。 (这应该很容易,因为我可以将检查放在像 DidScroll 之类的侦听器方法中)
似乎使用 indexPathsForVisibleRows
只能给我在屏幕上几乎 100% 可见的行。
我正在寻找解决方案,看起来使用 rectForRowAtIndexPath
并使用 contentOffset
做一些数学运算可能会给我想要的东西。不知道有没有更好的方法。
有人可以帮忙吗?非常感谢!
“似乎使用 indexPathsForVisibleRows
只能给我在屏幕上几乎 100% 可见的行。”
我不确定这是否正确。快速测试表明,即使只有单元格的第一个点可见,它也包含在内。
但是,您可以通过实施 willDisplay cell
:
来完成此操作
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
bSeen[indexPath.row] = @YES;
}
看看这个例子。只需将 UITableViewController
放入导航控制器并将其 class 分配为 SeenRowsTableViewController
:
@interface SeenRowsTableViewController ()
{
NSMutableArray *bSeen;
NSArray *colors;
NSInteger nRows;
}
@end
@implementation SeenRowsTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSAssert(self.navigationController, @"Example must be in a Navigation Controller");
// series of row background colors
// to make it easy to see the last / next row
colors = @[
[UIColor colorWithRed:1.00 green:0.75 blue:0.75 alpha:1.0],
[UIColor colorWithRed:0.75 green:1.00 blue:0.75 alpha:1.0],
[UIColor colorWithRed:0.75 green:0.75 blue:1.00 alpha:1.0],
[UIColor cyanColor],
[UIColor yellowColor],
[UIColor magentaColor],
];
nRows = 500;
// add a right bar button
UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithTitle:@"Check It" style:UIBarButtonItemStyleDone target:self action:@selector(checkIt)];
[self.navigationItem setRightBarButtonItem:btn];
// init array with number of rows all set to FALSE
bSeen = [NSMutableArray new];
for (int i = 0; i < nRows; i++) {
[bSeen addObject:@NO];
}
// use default basic cell
[self.tableView registerClass:UITableViewCell.class forCellReuseIdentifier:@"c"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [bSeen count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *c = [tableView dequeueReusableCellWithIdentifier:@"c" forIndexPath:indexPath];
c.textLabel.text = [NSString stringWithFormat:@"Row %ld", (long)indexPath.row];
c.contentView.backgroundColor = colors[indexPath.row % colors.count];
return c;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
bSeen[indexPath.row] = @YES;
}
- (void)checkIt {
NSUInteger idx = [bSeen indexOfObject:@NO];
self.title = [NSString stringWithFormat:@"Not Seen: %ld", (long)idx];
}
@end
我们为单元格使用了一系列颜色,以便于查看它们的边框。每次点击“Check It”栏按钮时,我们将导航栏标题更改为第一行未被查看的索引.
因此,在启动时(在 iPhone 8 上),当我们点击“检查”时,我们会得到这个:
缓慢滚动一点后,下一个单元格可见 1 磅,点击“检查”会得到以下信息:
这是底部的 zoomed-in 图片:
如您所见,只有行分隔符和下一个单元格的第一个点可见,但我们的代码已将其正确标记为“已看到”。
这里有一个 Swift 版本,供任何感兴趣的人使用:
class SeenRowsTableViewController: UITableViewController {
// series of row background colors
// to make it easy to see the last / next row
let colors: [UIColor] = [
UIColor(red: 1.00, green: 0.75, blue: 0.75, alpha: 1.0),
UIColor(red: 0.75, green: 1.00, blue: 0.75, alpha: 1.0),
UIColor(red: 0.75, green: 0.75, blue: 1.00, alpha: 1.0),
.cyan,
.yellow,
.magenta,
]
let nRows = 500
var bSeen: [Bool] = []
override func viewDidLoad() {
super.viewDidLoad()
guard navigationController != nil else {
fatalError("Example must be in a Navigation Controller")
}
// add a right bar button
let btn = UIBarButtonItem(title: "Check It", style: .done, target: self, action: #selector(checkIt))
self.navigationItem.rightBarButtonItem = btn
// init array with number of rows all set to FALSE
bSeen = Array(repeating: false, count: nRows)
// use default basic cell
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "c")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return bSeen.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: "c", for: indexPath)
c.textLabel?.text = "Row \(indexPath.row)"
c.contentView.backgroundColor = colors[indexPath.row % colors.count]
return c
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
bSeen[indexPath.row] = true
}
@objc func checkIt() -> Void {
if let idx = bSeen.firstIndex(of: false) {
// set NavBar title to first row that has
// NOT been seen
self.title = "Not Seen: \(idx)"
}
}
}
我正在尝试找到一种方法来检查我的几个 table 单元格是否真的被用户看到了(比方说,如果单元格至少显示 1px,我认为它被看到了).并且还需要确保如果用户上下滚动,我将需要触发该方法。 (这应该很容易,因为我可以将检查放在像 DidScroll 之类的侦听器方法中)
似乎使用 indexPathsForVisibleRows
只能给我在屏幕上几乎 100% 可见的行。
我正在寻找解决方案,看起来使用 rectForRowAtIndexPath
并使用 contentOffset
做一些数学运算可能会给我想要的东西。不知道有没有更好的方法。
有人可以帮忙吗?非常感谢!
“似乎使用 indexPathsForVisibleRows
只能给我在屏幕上几乎 100% 可见的行。”
我不确定这是否正确。快速测试表明,即使只有单元格的第一个点可见,它也包含在内。
但是,您可以通过实施 willDisplay cell
:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
bSeen[indexPath.row] = @YES;
}
看看这个例子。只需将 UITableViewController
放入导航控制器并将其 class 分配为 SeenRowsTableViewController
:
@interface SeenRowsTableViewController ()
{
NSMutableArray *bSeen;
NSArray *colors;
NSInteger nRows;
}
@end
@implementation SeenRowsTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSAssert(self.navigationController, @"Example must be in a Navigation Controller");
// series of row background colors
// to make it easy to see the last / next row
colors = @[
[UIColor colorWithRed:1.00 green:0.75 blue:0.75 alpha:1.0],
[UIColor colorWithRed:0.75 green:1.00 blue:0.75 alpha:1.0],
[UIColor colorWithRed:0.75 green:0.75 blue:1.00 alpha:1.0],
[UIColor cyanColor],
[UIColor yellowColor],
[UIColor magentaColor],
];
nRows = 500;
// add a right bar button
UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithTitle:@"Check It" style:UIBarButtonItemStyleDone target:self action:@selector(checkIt)];
[self.navigationItem setRightBarButtonItem:btn];
// init array with number of rows all set to FALSE
bSeen = [NSMutableArray new];
for (int i = 0; i < nRows; i++) {
[bSeen addObject:@NO];
}
// use default basic cell
[self.tableView registerClass:UITableViewCell.class forCellReuseIdentifier:@"c"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [bSeen count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *c = [tableView dequeueReusableCellWithIdentifier:@"c" forIndexPath:indexPath];
c.textLabel.text = [NSString stringWithFormat:@"Row %ld", (long)indexPath.row];
c.contentView.backgroundColor = colors[indexPath.row % colors.count];
return c;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
bSeen[indexPath.row] = @YES;
}
- (void)checkIt {
NSUInteger idx = [bSeen indexOfObject:@NO];
self.title = [NSString stringWithFormat:@"Not Seen: %ld", (long)idx];
}
@end
我们为单元格使用了一系列颜色,以便于查看它们的边框。每次点击“Check It”栏按钮时,我们将导航栏标题更改为第一行未被查看的索引.
因此,在启动时(在 iPhone 8 上),当我们点击“检查”时,我们会得到这个:
缓慢滚动一点后,下一个单元格可见 1 磅,点击“检查”会得到以下信息:
这是底部的 zoomed-in 图片:
如您所见,只有行分隔符和下一个单元格的第一个点可见,但我们的代码已将其正确标记为“已看到”。
这里有一个 Swift 版本,供任何感兴趣的人使用:
class SeenRowsTableViewController: UITableViewController {
// series of row background colors
// to make it easy to see the last / next row
let colors: [UIColor] = [
UIColor(red: 1.00, green: 0.75, blue: 0.75, alpha: 1.0),
UIColor(red: 0.75, green: 1.00, blue: 0.75, alpha: 1.0),
UIColor(red: 0.75, green: 0.75, blue: 1.00, alpha: 1.0),
.cyan,
.yellow,
.magenta,
]
let nRows = 500
var bSeen: [Bool] = []
override func viewDidLoad() {
super.viewDidLoad()
guard navigationController != nil else {
fatalError("Example must be in a Navigation Controller")
}
// add a right bar button
let btn = UIBarButtonItem(title: "Check It", style: .done, target: self, action: #selector(checkIt))
self.navigationItem.rightBarButtonItem = btn
// init array with number of rows all set to FALSE
bSeen = Array(repeating: false, count: nRows)
// use default basic cell
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "c")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return bSeen.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: "c", for: indexPath)
c.textLabel?.text = "Row \(indexPath.row)"
c.contentView.backgroundColor = colors[indexPath.row % colors.count]
return c
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
bSeen[indexPath.row] = true
}
@objc func checkIt() -> Void {
if let idx = bSeen.firstIndex(of: false) {
// set NavBar title to first row that has
// NOT been seen
self.title = "Not Seen: \(idx)"
}
}
}