如何消除 UITableView 左侧的边距,而不在右侧创建间隙?
How do I eliminate the margin on the left side of a UITableView, without creating a gap on the right?
我的目标是 iOS 7 和 8,我想消除下面这个 UITableView 中图像左侧出现的边距。如果解决方案是 simple/elegant,我什至愿意接受仅适用于 iOS 8 的解决方案。 (我只接受 iOS 7 的边距,因为它消失了)。
这就是我想要的样子:
我在 Stack Overflow (such as this one), or ones specific to grouped UITableViews (here and here) 上通读了许多类似的问题,但似乎无法正确解决任何问题。
例如,如果我尝试使用 contentInset 解决问题(SO 上的常见答案):
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, -16, self.tableView.contentInset.bottom, self.tableView.contentInset.right);
self.tableView.separatorInset = UIEdgeInsetsMake(0, 33, 0, 0);
}
然后我在 tableview 的右侧得到了空白:
我明白为什么会这样了,整个表视图都被转移了,如调试视图层次结构屏幕所示:
但是,我已经尝试调整 tableView 框架大小来补偿,但它似乎永远无法正常工作。另外这看起来很老套;一定有更好的方法。
作为记录,这是我的 cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// get a cell that we can use]
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"VideoCell" forIndexPath:indexPath];
cell.textLabel.numberOfLines = 0;
cell.selectedBackgroundView = selectionColor;
cell.accessoryView = [[UIImageView alloc] initWithImage:[PTStyleKit imageOfArrow]];
// Create the attributed string (text + attributes)
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:[videos objectAtIndex:indexPath.row] attributes:attributes];
// Set it in our UILabel and we are done!
[cell.textLabel setAttributedText:attributedText];
NSString* filename = [filenames objectAtIndex:indexPath.row];
if (filename == nil)
{
filename = cell.textLabel.text;
}
UIImage *imageOne = [UIImage imageNamed:[NSString stringWithFormat:@"medium-%@", filename]];
cell.imageView.image = [UIImage imageWithCGImage:imageOne.CGImage scale:imageOne.size.height/44 orientation:imageOne.imageOrientation];
return cell;
}
看来我能找到的唯一解决方案是子类化 UITableViewCell,然后覆盖 imageView 和 textLabel 的布局。在研究这种方法时,我发现 this related answer。 (我想我一直没有意识到我正在搜索最初在 iOS 6 中的 tableview 行为。)
我的子类只有一个被重写的方法:
- (void)layoutSubviews
{
[super layoutSubviews];
// Slide image to the left, eliminating gutter
self.imageView.frame = CGRectMake(0, 0, self.imageView.frame.size.width, self.imageView.frame.size.height);
// Slide text label to the left, and extend width by additional
// space gained by eliminating the left-most gutter
self.textLabel.frame = CGRectMake((self.imageView.frame.origin.x + self.imageView.frame.size.width + 15), 0, self.textLabel.frame.size.width + 15, self.textLabel.frame.size.height);
}
我生成的表格视图现在看起来完全符合我的要求:
我想我想出了一个简单的解决方案,我在 Whosebug 上找到了它,这是一种调整单元格边距的方法,请在您的代码中添加此方法
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[tableView setLayoutMargins:UIEdgeInsetsZero];
}
if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
cell.preservesSuperviewLayoutMargins = NO;
[cell setLayoutMargins:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setSeparatorInset:)]){
[cell setSeparatorInset:UIEdgeInsetsZero];
}
}
这解决了我的问题。
Swift 3 和 4
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
cell.separatorInset = .zero
}
if (cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins))) {
cell.preservesSuperviewLayoutMargins = false
}
if (cell.responds(to: #selector(setter: UIView.layoutMargins))) {
cell.layoutMargins = UIEdgeInsets.zero
}
if tableView.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
tableView.separatorInset = .zero
}
}
为您的 table 视图设置清晰的背景并设置 contentInset
属性。
代码:
tableView.contentInset = UIEdgeInsetsMake(0, -15, 0, 0);
tableView.backgroundColor = [UIColor clearColor];
但通过设置框架将 table 视图的宽度增加 15 像素。
iOS 8+
在您的 table 视图中:
table.separatorInset = UIEdgeInsets.zero // or UIEdgeInsetsZero
您可能还需要:
table.layoutMargins = UIEdgeInsets.zero
归功于 。
1.在 iOS 13
关键是连同其他东西一起设置
cell.contentView.layoutMargins
到 .zero
:
/// view controller
...
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "identifier")
tableView.separatorInset = .zero
tableView.directionalLayoutMargins = .zero
tableView.layoutMargins = .zero
...
/// data source
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "identifier")!
cell.textLabel?.text = "Text"
cell.directionalLayoutMargins = .zero
cell.layoutMargins = .zero
cell.contentView.directionalLayoutMargins = .zero
cell.contentView.layoutMargins = .zero
return cell
}
如果你正在使用 UITableViewController,除了以上所有你还需要应用这个:
tableViewController.viewRespectsSystemMinimumLayoutMargins = false
2。在 iOS 12 岁及以下
似乎无法使用 layoutMargins 等将标准 UITableViewCell.textLabel 相对于 table 的偏移量设为零。我找到的最简单也是唯一的方法是子类化单元格并像这样覆盖 layoutSubviews
:
class MyCell: UITableViewCell {
...
override func layoutSubviews() {
super.layoutSubviews()
let leading = contentView.directionalLayoutMargins.leading
textLabel?.frame.origin.x = leading
}
...
}
当然,您需要正确设置布局边距才能正常工作
你可以试试;
[cell.textLabel setTranslatesAutoresizingMaskIntoConstraints:false];
[cell.textLabel.centerYAnchor constraintEqualToAnchor:cell.contentView.centerYAnchor].active = YES;
[cell.textLabel.leadingAnchor constraintEqualToAnchor:cell.contentView.leadingAnchor constant:22].active = YES;
我的目标是 iOS 7 和 8,我想消除下面这个 UITableView 中图像左侧出现的边距。如果解决方案是 simple/elegant,我什至愿意接受仅适用于 iOS 8 的解决方案。 (我只接受 iOS 7 的边距,因为它消失了)。
这就是我想要的样子:
我在 Stack Overflow (such as this one), or ones specific to grouped UITableViews (here and here) 上通读了许多类似的问题,但似乎无法正确解决任何问题。
例如,如果我尝试使用 contentInset 解决问题(SO 上的常见答案):
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, -16, self.tableView.contentInset.bottom, self.tableView.contentInset.right);
self.tableView.separatorInset = UIEdgeInsetsMake(0, 33, 0, 0);
}
然后我在 tableview 的右侧得到了空白:
我明白为什么会这样了,整个表视图都被转移了,如调试视图层次结构屏幕所示:
但是,我已经尝试调整 tableView 框架大小来补偿,但它似乎永远无法正常工作。另外这看起来很老套;一定有更好的方法。
作为记录,这是我的 cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// get a cell that we can use]
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"VideoCell" forIndexPath:indexPath];
cell.textLabel.numberOfLines = 0;
cell.selectedBackgroundView = selectionColor;
cell.accessoryView = [[UIImageView alloc] initWithImage:[PTStyleKit imageOfArrow]];
// Create the attributed string (text + attributes)
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:[videos objectAtIndex:indexPath.row] attributes:attributes];
// Set it in our UILabel and we are done!
[cell.textLabel setAttributedText:attributedText];
NSString* filename = [filenames objectAtIndex:indexPath.row];
if (filename == nil)
{
filename = cell.textLabel.text;
}
UIImage *imageOne = [UIImage imageNamed:[NSString stringWithFormat:@"medium-%@", filename]];
cell.imageView.image = [UIImage imageWithCGImage:imageOne.CGImage scale:imageOne.size.height/44 orientation:imageOne.imageOrientation];
return cell;
}
看来我能找到的唯一解决方案是子类化 UITableViewCell,然后覆盖 imageView 和 textLabel 的布局。在研究这种方法时,我发现 this related answer。 (我想我一直没有意识到我正在搜索最初在 iOS 6 中的 tableview 行为。)
我的子类只有一个被重写的方法:
- (void)layoutSubviews
{
[super layoutSubviews];
// Slide image to the left, eliminating gutter
self.imageView.frame = CGRectMake(0, 0, self.imageView.frame.size.width, self.imageView.frame.size.height);
// Slide text label to the left, and extend width by additional
// space gained by eliminating the left-most gutter
self.textLabel.frame = CGRectMake((self.imageView.frame.origin.x + self.imageView.frame.size.width + 15), 0, self.textLabel.frame.size.width + 15, self.textLabel.frame.size.height);
}
我生成的表格视图现在看起来完全符合我的要求:
我想我想出了一个简单的解决方案,我在 Whosebug 上找到了它,这是一种调整单元格边距的方法,请在您的代码中添加此方法
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[tableView setLayoutMargins:UIEdgeInsetsZero];
}
if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
cell.preservesSuperviewLayoutMargins = NO;
[cell setLayoutMargins:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setSeparatorInset:)]){
[cell setSeparatorInset:UIEdgeInsetsZero];
}
}
这解决了我的问题。
Swift 3 和 4
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
cell.separatorInset = .zero
}
if (cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins))) {
cell.preservesSuperviewLayoutMargins = false
}
if (cell.responds(to: #selector(setter: UIView.layoutMargins))) {
cell.layoutMargins = UIEdgeInsets.zero
}
if tableView.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
tableView.separatorInset = .zero
}
}
为您的 table 视图设置清晰的背景并设置 contentInset
属性。
代码:
tableView.contentInset = UIEdgeInsetsMake(0, -15, 0, 0);
tableView.backgroundColor = [UIColor clearColor];
但通过设置框架将 table 视图的宽度增加 15 像素。
iOS 8+
在您的 table 视图中:
table.separatorInset = UIEdgeInsets.zero // or UIEdgeInsetsZero
您可能还需要:
table.layoutMargins = UIEdgeInsets.zero
归功于 。
1.在 iOS 13
关键是连同其他东西一起设置
cell.contentView.layoutMargins
到 .zero
:
/// view controller
...
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "identifier")
tableView.separatorInset = .zero
tableView.directionalLayoutMargins = .zero
tableView.layoutMargins = .zero
...
/// data source
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "identifier")!
cell.textLabel?.text = "Text"
cell.directionalLayoutMargins = .zero
cell.layoutMargins = .zero
cell.contentView.directionalLayoutMargins = .zero
cell.contentView.layoutMargins = .zero
return cell
}
如果你正在使用 UITableViewController,除了以上所有你还需要应用这个:
tableViewController.viewRespectsSystemMinimumLayoutMargins = false
2。在 iOS 12 岁及以下
似乎无法使用 layoutMargins 等将标准 UITableViewCell.textLabel 相对于 table 的偏移量设为零。我找到的最简单也是唯一的方法是子类化单元格并像这样覆盖 layoutSubviews
:
class MyCell: UITableViewCell {
...
override func layoutSubviews() {
super.layoutSubviews()
let leading = contentView.directionalLayoutMargins.leading
textLabel?.frame.origin.x = leading
}
...
}
当然,您需要正确设置布局边距才能正常工作
你可以试试;
[cell.textLabel setTranslatesAutoresizingMaskIntoConstraints:false];
[cell.textLabel.centerYAnchor constraintEqualToAnchor:cell.contentView.centerYAnchor].active = YES;
[cell.textLabel.leadingAnchor constraintEqualToAnchor:cell.contentView.leadingAnchor constant:22].active = YES;