Dấu tách UITableView của iOS 8 chèn 0 không hoạt động


662

Tôi có một ứng dụng trong đó UITableViewphần chèn dấu phân cách được đặt thành giá trị tùy chỉnh - Phải 0, Trái 0. Điều này hoạt động hoàn hảo iOS 7.x, tuy nhiên trong iOS 8.0tôi thấy rằng phần chèn phân cách được đặt thành mặc định 15ở bên phải. Mặc dù trong các tệp xib được đặt 0, nó vẫn hiển thị không chính xác.

Làm cách nào để xóa UITableViewCelllề phân tách?


Bạn đã thử đặt inet thành 0,001 thay vì 0 chưa? Tôi nhớ có một vấn đề tương tự trong đó phần chèn cạnh sẽ không phản ứng với 0 nhưng đã phản ứng với 0,001 (hoặc một cái gì đó tương tự nhỏ).
chào mừng

Tôi đã thử điều đó và nó cũng không hoạt động ..
user3570727

4
Sau đó, tôi sẽ đề nghị thiết lập màu phân cách [UIColor clearColor]và vẽ dải phân cách của riêng bạn. Bạn linh hoạt hơn nhiều theo cách đó.
chào mừng

1
Tôi vẫn không thể tin rằng đây vẫn không phải là một trong những UITableViewCellSeparatorStylemặc định. Ngay cả câu trả lời được chấp nhận là một hack thực sự bẩn theo ý kiến ​​của tôi.
Enrico Susatyo

Câu trả lời:


1071

iOS 8.0 giới thiệu thuộc tính layoutMargins trên các ô VÀ chế độ xem bảng.

Thuộc tính này không khả dụng trên iOS 7.0, vì vậy bạn cần đảm bảo kiểm tra trước khi gán nó!

Cách khắc phục dễ dàng là phân lớp ô của bạn và ghi đè thuộc tính lề bố cục theo đề xuất của @ user3570727. Tuy nhiên, bạn sẽ mất mọi hành vi hệ thống như kế thừa lợi nhuận từ Vùng an toàn, vì vậy tôi không đề xuất giải pháp dưới đây:

(Mục tiêu)

-(UIEdgeInsets)layoutMargins { 
     return UIEdgeInsetsZero // override any margins inc. safe area
}

(nhanh 4.2):

override var layoutMargins: UIEdgeInsets { get { return .zero } set { } }

Nếu bạn không muốn ghi đè lên tài sản hoặc cần đặt nó một cách có điều kiện, hãy tiếp tục đọc.


Ngoài thuộc layoutMarginstính, Apple đã thêm một thuộc tính vào ô của bạn để ngăn không cho nó kế thừa các cài đặt lề của Chế độ xem bảng của bạn. Khi thuộc tính này được đặt, các ô của bạn được phép định cấu hình lề riêng của chúng độc lập với chế độ xem bảng. Hãy nghĩ về nó như một ghi đè.

Thuộc tính này được gọi preservesSuperviewLayoutMarginsvà thiết lập nó NOsẽ cho phép layoutMargincài đặt của ô ghi đè lên bất cứ thứ gì layoutMarginđược đặt trên TableView của bạn. Cả hai đều tiết kiệm thời gian ( bạn không phải sửa đổi cài đặt của Chế độ xem bảng ) và ngắn gọn hơn. Vui lòng tham khảo câu trả lời của Mike Abdullah để được giải thích chi tiết.

LƯU Ý: những gì tiếp theo là một triển khai rõ ràng cho cài đặt lề cấp độ ô , như được thể hiện trong câu trả lời của Mike Abdullah. Đặt ô của preservesSuperviewLayoutMargins=NObạn sẽ đảm bảo rằng Chế độ xem bảng của bạn không ghi đè cài đặt ô. Nếu bạn thực sự muốn toàn bộ chế độ xem bảng của mình có lề nhất quán, vui lòng điều chỉnh mã của bạn cho phù hợp.

Thiết lập lề di động của bạn:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Remove seperator inset
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
           [cell setSeparatorInset:UIEdgeInsetsZero];
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
        [cell setPreservesSuperviewLayoutMargins:NO];
    }

    // Explictly set your cell's layout margins
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

Swift 4:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // Remove seperator inset
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // Prevent the cell from inheriting the Table View's margin settings
    if cell.responds(to: #selector(setter: UITableViewCell.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // Explictly set your cell's layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}

Đặt thuộc preservesSuperviewLayoutMarginstính trên ô của bạn thành KHÔNG sẽ ngăn chế độ xem bảng của bạn ghi đè lên lề của ô. Trong một số trường hợp, nó dường như không hoạt động đúng.

Nếu tất cả đều thất bại, bạn có thể ép buộc lề của Chế độ xem bảng:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    // Force your tableview margins (this may be a bad idea)
    if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [self.tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [self.tableView setLayoutMargins:UIEdgeInsetsZero];
    }
} 

Swift 4:

func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // Force your tableview margins (this may be a bad idea)
    if tableView.responds(to: #selector(setter: UITableView.separatorInset)) {
        tableView.separatorInset = .zero
    }
    if tableView.responds(to: #selector(setter: UITableView.layoutMargins)) {
        tableView.layoutMargins = .zero
    }
}

...Và ở đó bạn đi! Điều này sẽ hoạt động trên iOS 7 và 8.


EDIT: Mohamed Saleh mang đến cho tôi sự thay đổi có thể có trong iOS 9. Bạn có thể cần phải đặt Chế độ xem bảng cellLayoutMarginsFollowReadableWidththành NOnếu bạn muốn tùy chỉnh phần trong hoặc lề. Số dặm của bạn có thể thay đổi, điều này không được ghi chép lại rất tốt.

Thuộc tính này chỉ tồn tại trong iOS 9, vì vậy hãy chắc chắn kiểm tra trước khi cài đặt.

if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
    myTableView.cellLayoutMarginsFollowReadableWidth = NO;
} 

Swift 4:

if myTableView.responds(to: #selector(setter: self.cellLayoutMarginsFollowReadableWidth)) {
    myTableView.cellLayoutMarginsFollowReadableWidth = false
}

(mã trên từ dấu phân cách UITableView của iOS 8 không hoạt động )

EDIT: Đây là một cách tiếp cận Trình tạo giao diện thuần túy:

TableViewAttributInspector TableViewCellSizeInspector

LƯU Ý: iOS 11 thay đổi và đơn giản hóa phần lớn hành vi này, một bản cập nhật sẽ đến ...


2
Để xem bảng trong một UIPopoverCont kiểm soát, tôi đã phải thực hiện cả hai điều này như được hiển thị ở trên, thay vì chỉ trong willDisplayCell.
Zhang

44
Tôi cũng thấy rằng mặc dù tất cả các mã ở trên mà tôi vẫn phải thêm cell.preservesSuperviewLayoutMargins = NOđề xuất của mỗi @ bffmike hoặc sau khi cuộn một cách các phần tử sẽ xuất hiện. (wtf ??)
inorganik

Điều gì xảy ra nếu chúng ta chỉ muốn đặt lề cho một loại ô trong bảngView được nhóm?
SAH

Bạn có thể thử đặt nó trong willDisplayCell và xem điều đó có thực sự hoạt động không (bạn có một tay cầm trên ô để nó không đáng kể). Nếu không, chúng ta cần phải báo lỗi. Biên độ bố trí cụ thể của tế bào nên có thể, IMO.
cdstamper

2
Điều này làm việc cho tôi với việc bổ sung cell.preservesSuperviewLayoutMarginstrong phương pháp nguồn dữ liệu của mình:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
mts

257

Tranh cãi !!! Sau khi chơi xung quanh hoặc làm điều này trong Celllớp con của bạn :

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

hoặc đặt cell.layoutMargins = UIEdgeInsetsZero;cố định nó cho tôi.


13
giải pháp đầu tiên trong câu trả lời này có hiệu quả với tôi, giải pháp thứ hai không hiệu quả.
spybart

5
Đừng chỉ sử dụng cell.layoutMargins = UIEdgeInsetsZero; vì nó sẽ sập trên iOS 7.x. Tốt hơn là kiểm tra xem bộ chọn có tồn tại trước khi sử dụng nó không. Xem giải pháp của tôi dưới đây.
Ricky

3
Anh ta không thiết lập cell.layoutMargins ... Giải pháp này hoạt động rất tốt khi bạn đã có các ô tùy chỉnh.
Sjoerd Perfors

11
Điều này sẽ hoạt động tốt trong iOS 7, vì phương thức sẽ không được gọi! Tuy nhiên, bạn cũng cần đặt layoutMargins của chế độ xem bảng, hoặc nó sẽ không hoạt động.
cdstamper

2
ghi đè người truy cập làm việc cho tôi. nhưng tất cả các giải pháp khác thì không. thậm chí cấu hình separatorInsettrong IB không hoạt động. cũng có một vấn đề với màu nền xem bảng. Đây thực sự là một thứ bệnh hoạn.
glasz

178

Hãy dành một chút thời gian để hiểu vấn đề trước khi sạc một cách mù quáng để cố gắng khắc phục nó.

Một cú chọc nhanh trong trình gỡ lỗi sẽ cho bạn biết rằng các đường phân cách là các cuộc phỏng vấn của UITableViewCell. Có vẻ như chính tế bào này chịu trách nhiệm khá lớn cho việc bố trí các đường này.

iOS 8 giới thiệu khái niệm lề bố cục . Theo mặc định, lề bố cục của chế độ xem nằm 8ptở tất cả các phía và chúng được kế thừa từ chế độ xem của tổ tiên.

Như tốt nhất chúng ta có thể nói, khi đặt ra đường phân cách của nó, UITableViewCellchọn cách tôn trọng lề bố cục bên trái, sử dụng nó để hạn chế phần bên trái.

Đặt tất cả những thứ đó lại với nhau, để đạt được mức độ mong muốn thực sự bằng không, chúng ta cần phải:

  • Đặt lề bố cục bên trái thành 0
  • Ngăn chặn bất kỳ lợi nhuận thừa kế ghi đè rằng

Nói như vậy, đó là một nhiệm vụ khá đơn giản để đạt được:

cell.layoutMargins = UIEdgeInsetsZero;
cell.preservesSuperviewLayoutMargins = NO;

Những điều cần lưu ý:

  • Mã này chỉ cần được chạy một lần cho mỗi ô (bạn chỉ định cấu hình các thuộc tính của ô) và không có gì đặc biệt khi bạn chọn thực thi nó. Làm những gì có vẻ sạch sẽ nhất với bạn.
  • Đáng buồn là không có thuộc tính nào có sẵn để định cấu hình trong Trình tạo giao diện, nhưng bạn có thể chỉ định thuộc tính thời gian chạy do người dùng xác định preservesSuperviewLayoutMarginsnếu muốn.
  • Rõ ràng, nếu ứng dụng của bạn cũng nhắm mục tiêu phát hành HĐH trước đó, bạn sẽ cần tránh thực thi mã trên cho đến khi chạy trên iOS 8 trở lên.
  • Thay vì cài đặt preservesSuperviewLayoutMargins, bạn có thể định cấu hình các chế độ xem của tổ tiên (chẳng hạn như bảng) để có 0lề trái, nhưng điều này dường như dễ bị lỗi hơn khi bạn không kiểm soát toàn bộ hệ thống phân cấp đó.
  • Có lẽ sẽ sạch hơn một chút khi chỉ đặt lề trái 0và để các lề khác.
  • Nếu bạn muốn có một dấu 0 trên các dấu phân cách "phụ" được UITableViewvẽ ở cuối các bảng kiểu đơn giản, tôi đoán rằng sẽ yêu cầu chỉ định các cài đặt tương tự ở cấp bảng (bạn cũng chưa thử cài đặt này!)

3
Cảm ơn bạn! Đây thực sự là câu trả lời ngắn gọn hơn. Tốt hơn nhiều so với việc ghi đè hai phương thức và vũ phu buộc nó.
LunaCodeGirl

16
Trong iOS 8, đối với tôi, điều này sẽ không hoạt động mà không có[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)];
davetw12

1
Bạn có phiếu bầu của tôi, cảm ơn vì lời giải thích rõ ràng. Trong một số trường hợp, tôi sẽ chỉ đề cập rằng bản thân TableView cũng có layoutMargins có thể cần được đặt ngoài dấu phân cách, trong một số trường hợp.
cdstamper

@ davetw12 và @cdstamper Bạn có thể cung cấp bất kỳ bằng chứng nào về điều này không? Tất cả các khám phá của tôi cho đến nay nói rằng thiết lập cả hai layoutMarginspreservesSuperviewLayoutMarginstrên tế bào là tất cả những gì được yêu cầu. Bất cứ điều gì khác cảm thấy như tin tưởng vào voodoo.
Mike Abdullah

3
Không, đó không phải là một hình thức của voodoo @MikeAbdullah. Để bạn tránh mặc định separatorInsetcủa UITableViewCelliOS 8, bạn phải đặt cài đặt thành UIEdgeInsets0 trên cả UITableViewUITableViewCell. Nếu bạn không làm cả hai, bạn vẫn sẽ có một hình nhỏ bên trái lớn hơn 0. Tôi đã xác nhận điều này nhiều lần.
davetw12

58

Tôi tin rằng đây là cùng một câu hỏi mà tôi đã hỏi ở đây: Xóa Tách bộ cài đặt trên iOS 8 UITableView cho Trình mô phỏng iPhone XCode 6

Trong iOS 8 , có một thuộc tính mới cho tất cả các đối tượng được kế thừa từ đó UIView. Vì vậy, giải pháp để thiết lập SeparatorInsettrong iOS 7.x sẽ không thể xóa khoảng trắng bạn nhìn thấy trên UITableView trong iOS 8.

Thuộc tính mới được gọi là " layoutMargins ".

@property(nonatomic) UIEdgeInsets layoutMargins
Description   The default spacing to use when laying out content in the view.
Availability  iOS (8.0 and later)
Declared In   UIView.h
Reference UIView Class Reference

Bộ cài đặt UITableView của iOS 8 Bộ cài đặt ứng dụng: UIEdgeInsetsZero setLayoutMargins: UIEdgeInsetsZero

Giải pháp:-

-(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 ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
   }
}

Nếu bạn đặt cell.layoutMargins = UIEdgeInsetsZero;mà không kiểm tra xem layoutMarginscó tồn tại hay không, ứng dụng sẽ sập trên iOS 7.x. Vì vậy, cách tốt nhất sẽ là kiểm tra nếu layoutMarginstồn tại trước tiên setLayoutMargins:UIEdgeInsetsZero.


Cách tiếp cận này có thể được sử dụng nếu mục tiêu triển khai được đặt thành iOS 7?
Petar

Tôi đặt mã cho tableView trong viewDidLoad và đang hoạt động tốt. Tôi nghĩ rằng không cần thiết phải gọi cho họ mỗi lần trong willDisplayCell ().
Abdullah Umer

46

Bạn có thể sử dụng UIAppurdy một lần, khi khởi động ứng dụng của bạn (trước khi UI được tải), để đặt nó làm cài đặt chung mặc định:

// iOS 7:
[[UITableView appearance] setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[[UITableView appearance] setSeparatorInset:UIEdgeInsetsZero];

[[UITableViewCell appearance] setSeparatorInset:UIEdgeInsetsZero];

// iOS 8:
if ([UITableView instancesRespondToSelector:@selector(setLayoutMargins:)]) {

    [[UITableView appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setPreservesSuperviewLayoutMargins:NO];

}

Bằng cách này, bạn giữ mã của UIViewControll của bạn sạch sẽ và luôn có thể ghi đè mã nếu bạn muốn.


41

iOS giới thiệu thuộc tính layoutMargins trên các ô VÀ chế độ xem bảng.

Thuộc tính này không có sẵn trong iOS 7.0, vì vậy bạn cần đảm bảo kiểm tra trước khi gán nó!

Tuy nhiên, Apple đã thêm một thuộc tính có tên làesesSuperviewLayoutMargins vào ô của bạn, điều này sẽ ngăn không cho nó kế thừa các cài đặt lề của Chế độ xem bảng của bạn. Bằng cách này, các ô của bạn có thể định cấu hình lề riêng của chúng độc lập với chế độ xem bảng. Hãy nghĩ về nó như một ghi đè.

Thuộc tính này được gọi là bảo vệSuperviewLayoutMargins và đặt nó thành NO có thể cho phép bạn ghi đè cài đặt layoutMargin của Chế độ xem bảng bằng cài đặt layoutMargin của ô của chính bạn. Cả hai đều tiết kiệm thời gian ( bạn không phải sửa đổi cài đặt của Chế độ xem bảng ) và ngắn gọn hơn. Vui lòng tham khảo câu trả lời của Mike Abdullah để được giải thích chi tiết.

LƯU Ý: đây là cách thực hiện đúng, ít lộn xộn, như được thể hiện trong câu trả lời của Mike Abdullah; thiết lập mức bảo tồn của tế bàoSuperviewLayoutMargins = NO sẽ đảm bảo rằng Chế độ xem bảng của bạn không ghi đè cài đặt ô.

Bước đầu tiên - Thiết lập lề di động của bạn:

/*
    Tells the delegate that the table view is about to draw a cell for a particular row.
*/
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,
    forRowAtIndexPath indexPath: NSIndexPath)
{
    // Remove separator inset
    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset = UIEdgeInsetsZero
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if cell.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
        cell.preservesSuperviewLayoutMargins = false
    }

    // Explictly set your cell's layout margins
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins = UIEdgeInsetsZero
    }
}

Đặt thuộc tính bảo tồnSuperviewLayoutMargins trên ô của bạn thành KHÔNG sẽ ngăn chế độ xem bảng của bạn ghi đè lên lề của ô. Trong một số trường hợp, nó dường như không hoạt động đúng.

Bước thứ hai - Chỉ khi tất cả đều thất bại, bạn có thể mạnh mẽ thay thế lề Chế độ xem bảng của mình:

/*
    Called to notify the view controller that its view has just laid out its subviews.
*/
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Force your tableview margins (this may be a bad idea)
    if self.tableView.respondsToSelector("setSeparatorInset:") {
        self.tableView.separatorInset = UIEdgeInsetsZero
    }

    if self.tableView.respondsToSelector("setLayoutMargins:") {
        self.tableView.layoutMargins = UIEdgeInsetsZero
    }
}

...Và ở đó bạn đi! Điều này sẽ hoạt động trên iOS 8 cũng như iOS 7.

Lưu ý: đã thử nghiệm bằng iOS 8.1 và 7.1, trong trường hợp của tôi, tôi chỉ cần sử dụng bước đầu tiên của giải thích này.

Bước thứ hai chỉ được yêu cầu nếu bạn có ô không được điền bên dưới các ô được hiển thị, nghĩa là. nếu bảng lớn hơn số lượng hàng trong mô hình bảng. Không thực hiện bước thứ hai sẽ dẫn đến các độ lệch khác nhau.


1
Bạn không cần kiểm tra các công cụ chọn trong willDisplayCellphương thức vì bản thân phương thức đã là iOS 8+ và sẽ không bao giờ được gọi từ các phiên bản cũ hơn.
Rivera

38

Trong Swift, điều đó hơi khó chịu hơn vì layoutMarginslà một thuộc tính, vì vậy bạn phải ghi đè getter setter.

override var layoutMargins: UIEdgeInsets {
  get { return UIEdgeInsetsZero }
  set(newVal) {}
}

Điều này sẽ có hiệu quả làm cho layoutMarginschỉ đọc, mà trong trường hợp của tôi là tốt.


Chỉ có giải pháp này đã làm việc cho tôi. Và tôi không cần thêm mã dòng trong các phương thức. Tôi đã sử dụng các tế bào tùy chỉnh.
Ramis

2
Đối với ô tĩnh, ngoại trừ việc ghi đè layoutMargins, bạn vẫn cần thay đổi kiểu dấu tách của ô thành "Phần tử tùy chỉnh" và đặt giá trị bên trái thành "0" trong bảng phân cảnh.
hufeng03

22

Đối với iOS 9, bạn cần thêm:

if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
    myTableView.cellLayoutMarginsFollowReadableWidth = NO;
} 

Để biết thêm chi tiết xin vui lòng tham khảo câu hỏi .


12
thật buồn cười khi thêm một số mã cho mỗi phiên bản để diện mạo ban đầu giữ nguyên ...
Christian

20

Tiện ích mở rộng Swift 2.0

Tôi chỉ muốn chia sẻ một phần mở rộng mà tôi đã thực hiện để loại bỏ lề khỏi các dấu tách ô của ô xem.

extension UITableViewCell {
    func removeMargins() {

        if self.respondsToSelector("setSeparatorInset:") {
            self.separatorInset = UIEdgeInsetsZero
        }

        if self.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
            self.preservesSuperviewLayoutMargins = false
        }

        if self.respondsToSelector("setLayoutMargins:") {
            self.layoutMargins = UIEdgeInsetsZero
        }
    }
}

Được sử dụng trong ngữ cảnh:

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell

    cell.removeMargins()
    return cell

15

Nhanh:

override func viewDidLoad() {
    super.viewDidLoad()

    if self.tableView.respondsToSelector("setSeparatorInset:") {
        self.tableView.separatorInset = UIEdgeInsetsZero
    }
    if self.tableView.respondsToSelector("setLayoutMargins:") {
        self.tableView.layoutMargins = UIEdgeInsetsZero
    }

    self.tableView.layoutIfNeeded()            // <--- this do the magic
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
     ...

    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset = UIEdgeInsetsZero
    }
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins = UIEdgeInsetsZero
    }

    return cell
}

11

Tôi đã làm cho nó hoạt động bằng cách làm điều này:

tableView.separatorInset = UIEdgeInsetsZero;
tableView.layoutMargins = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;

9

Theo như những gì cdstamper đã đề xuất thay vì chế độ xem bảng, việc thêm các dòng bên dưới trong layout của phương thứcSubview hoạt động với tôi.

- (void)layoutSubviews 
{
    [super layoutSubviews];

    if ([self respondsToSelector:@selector(setSeparatorInset:)])
                [self setSeparatorInset:UIEdgeInsetsZero];

        if ([self respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)])
        {
            [self setPreservesSuperviewLayoutMargins:NO];;
        }

        if ([self respondsToSelector:@selector(setLayoutMargins:)]) 
        {
            [self setLayoutMargins:UIEdgeInsetsZero];
        }
}

9

Ví dụ Swift 3.0:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // removing seperator inset
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // prevent the cell from inheriting the tableView's margin settings
    if cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // explicitly setting cell's layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}

9

Sau nhiều điều tra ...

Đây là cách duy nhất để kiểm soát hoàn toàn công cụ này (mà tôi có thể tìm thấy)

Để kiểm soát hoàn toàn cả phần chèn tách và lề bố trí trên mỗi ô. Làm điều này trong willDisplayCellphương pháp trên của bạn UITableviewDelegate.

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.layoutMargins = UIEdgeInsetsZero
    cell.contentView.layoutMargins = UIEdgeInsetsMake(0, 10, 0, 10)
    cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
}

Đối tượng ô điều khiển dải phân cách và contentViewđiều khiển mọi thứ khác. Nếu dấu cách dấu phân cách của bạn hiển thị màu không mong muốn, điều này sẽ giải quyết nó:

cell.backgroundColor = cell.contentView.backgroundColor

8

Giải pháp đơn giản trong Swift cho iOS 8 với một tùy chỉnhUITableViewCell

override func awakeFromNib() {
    super.awakeFromNib()

    self.layoutMargins = UIEdgeInsetsZero
    self.separatorInset = UIEdgeInsetsZero
}

Theo cách này, bạn đang thiết lập layoutMarginseparatorInsetchỉ một lần thay vì thực hiện cho từng câu willDisplayCellnhư hầu hết các câu trả lời ở trên gợi ý.

Nếu bạn đang sử dụng một tùy chỉnh UITableViewCellthì đây là nơi chính xác để làm điều đó. Nếu không bạn nên làm điều đó trong tableView:cellForRowAtIndexPath.

Chỉ cần một gợi ý khác: bạn không cần phải đặt preservesSuperviewLayoutMargins = falsevì giá trị mặc định đã có NO!


8

Đối với tôi, dòng đơn giản đã làm công việc

cell.layoutMargins = UIEdgeInsetsZero

được gọi là phương thức này trong phương thức ủy nhiệm của cellForRowAtIndexPath. Câu trả lời hay :)
Saintjab 29/05/2016

7

Chỉ cần thêm mã dưới đây có thể giải quyết chương trình này.

Chúc bạn may mắn!

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

       if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
           [cell setSeparatorInset:UIEdgeInsetsZero];
       }

       if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
           [cell setLayoutMargins:UIEdgeInsetsZero];
       }

}

5

Câu trả lời của Lukasz trong Swift:

    // iOS 7:
    UITableView.appearance().separatorStyle = .SingleLine
    UITableView.appearance().separatorInset = UIEdgeInsetsZero
    UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

    // iOS 8:
    if UITableView.instancesRespondToSelector("setLayoutMargins:") {
        UITableView.appearance().layoutMargins = UIEdgeInsetsZero
        UITableViewCell.appearance().layoutMargins = UIEdgeInsetsZero
        UITableViewCell.appearance().preservesSuperviewLayoutMargins = false
    }

5

Đây là mã hoạt động với tôi, trong Swift:

override func viewDidLoad() 
{
    super.viewDidLoad()
    ...
    if tableView.respondsToSelector("setSeparatorInset:") {
        tableView.separatorInset = UIEdgeInsetsZero
    }
}

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath)
{
    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset.left = CGFloat(0.0)
    }
    if tableView.respondsToSelector("setLayoutMargins:") {
        tableView.layoutMargins = UIEdgeInsetsZero
    }
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins.left = CGFloat(0.0)
    }
}

Điều này có vẻ sạch nhất đối với tôi (hiện tại), vì tất cả các điều chỉnh cạnh / lề của ô / bảng Xem được thực hiện trong tableView:willDisplayCell:forRowAtIndexPath:phương thức, mà không nhồi nhét mã không cần thiết vào tableView:cellForRowAtIndexPath:.

Btw, tôi chỉ thiết lập dấu phân cách bên trái của ôInset / layoutMargins, vì trong trường hợp này tôi không muốn làm hỏng các ràng buộc mà tôi đã thiết lập trong ô của mình.

Mã được cập nhật lên Swift 2.2:

 override func viewDidLoad() {
   super.viewDidLoad()       

    if tableView.respondsToSelector(Selector("setSeparatorInset:")) {
      tableView.separatorInset = UIEdgeInsetsZero
        }
    }

 override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
        if cell.respondsToSelector(Selector("setSeparatorInset:")) {
            cell.separatorInset.left = CGFloat(0.0)
        }
        if tableView.respondsToSelector(Selector("setLayoutMargins:")) {
            tableView.layoutMargins = UIEdgeInsetsZero
        }
        if cell.respondsToSelector(Selector("setLayoutMargins:")) {
            cell.layoutMargins.left = CGFloat(0.0)
        }
    }

Chính xác thì điều gì không hiệu quả với bạn? Chỉ cần thử nghiệm mã này trên trình giả lập iPhone 5, với SDK iOS 8.1 được cài đặt và mọi thứ vẫn như ban đầu khi tôi đăng câu trả lời này. Mã được biên dịch và chạy với Xcode 6.1.1.
Ivan

4

Hầu hết các câu trả lời được hiển thị insets tách và lợi nhuận bố trí không được đặt quá nhiều phương pháp (ví dụ viewDidLayoutSubviews, willDisplayCell, vv) cho các tế bào và tableviews, nhưng tôi đã phát hiện ra rằng chỉ cần đặt chúng trong cellForRowAtIndexPathcác công trình lớn. Có vẻ như cách sạch nhất.

// kill insets for iOS 8
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8) {
    cell.preservesSuperviewLayoutMargins = NO;
    [cell setLayoutMargins:UIEdgeInsetsZero];
}
// iOS 7 and later
if ([cell respondsToSelector:@selector(setSeparatorInset:)])
    [cell setSeparatorInset:UIEdgeInsetsZero];

4

Sử dụng đoạn mã dưới đây để tránh sự cố đệm không mong muốn cho UITableView trong iOS 8 & 7.

-(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 ([cell respondsToSelector:@selector(setLayoutMargins:)])
    {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

4

Thay vì cập nhật preservesSuperviewLayoutMarginslayoutMarginsmỗi khi ô di chuyển vào (sử dụng willDisplayCell), tôi khuyên bạn nên thực hiện một lần trong cellForRowAtIndexPath::

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)

    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero

    return cell

}

4

Đây là một cách dễ dàng để loại bỏ toàn cầu.

Trong UITableViewCell+Extensions.swift:

import UIKit

extension UITableViewCell {

  override public var layoutMargins: UIEdgeInsets {
    get { return UIEdgeInsetsZero }
    set { }
  }

}

Trong AppDelegate application:didFinishLaunchingWithOptions::

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

Thay vào đó, bạn có thể nghĩ rằng a) cũng chỉ ghi đè separatorInsettrong tiện ích mở rộng hoặc b) đặt proxy ngoại hình cho layoutMargins. Không phải sẽ làm việc. Mặc dù separatorInsetđược chỉ định là một thuộc tính, cố gắng ghi đè lên nó như một thuộc tính (hoặc phương thức) tạo ra các lỗi biên dịch. Và thiết lập proxy xuất hiện cho UITableViewCell's layoutMargins(hoặc, cho rằng vấn đề, cũng thiết lập proxy xuất hiện cho UITableView' s layoutMarginsseparatorInset) không có tác dụng.


3

Trong iOS8:

Thêm phần này vào Lớp con UITableViewCell của tôi:

- (UIEdgeInsets)layoutMargins {
    return UIEdgeInsetsZero;
}

và điều này thành "tableView: cellForRowAtIndexPath" hoặc "tableView: willDisplayCell":

[editCell setSeparatorInset:UIEdgeInsetsZero];

Đã làm cho tôi.


2
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        // ... Get the cell
        cell.separatorInset = UIEdgeInsetsMake(0.f, 20.f, 0.f, [UIScreen mainScreen].bounds.size.width - 20);
        // others
        return cell;
}

Đối với bất kỳ ô cụ thể nào bạn muốn ẩn dấu phân cách.


2

Sau khi thấy câu trả lời ở tầng 3, tôi đã cố gắng tìm hiểu mối quan hệ của việc thiết lập dấu phân cách giữa TableView & TableViewCell và đã thực hiện một số thử nghiệm. Dưới đây là kết luận của tôi:

  1. chúng ta có thể xem xét rằng việc đặt dấu phân cách của ô thành 0 phải di chuyển dấu phân cách theo hai bước: bước đầu tiên là đặt dấu phân cách của ô về 0. Bước thứ hai là thiết lập lề của ô thành không.

  2. đặt dải phân cách của TableView và lề ngoài có thể ảnh hưởng đến dải phân cách của ô . Tuy nhiên, từ thử nghiệm, tôi thấy rằng bộ phân tách của TableView dường như là vô dụng, lớp phủ lề của TableView thực sự có thể ảnh hưởng đến lớp phủ ngoài của ô .

  3. đặt PreservesSuperviewLayoutMargins = false, có thể cắt hiệu ứng lề của TableView trên các ô.

  4. một trong những giải pháp:

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell = UITableViewCell()
    
        cell.preservesSuperviewLayoutMargins = false
        cell.separatorInset = UIEdgeInsetsZero
        cell.layoutMargins = UIEdgeInsetsZero
    
        return cell
    }

2

Đây là giải pháp của tôi. Điều này áp dụng cho lớp con ô tùy chỉnh, chỉ cần thêm cả hai vào lớp con.

  1. - (UIEdgeInsets)layoutMargins {    
        return UIEdgeInsetsMake(0, 10, 0, 10);
    }

2.

self.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10);

Và thật thuận tiện khi bạn có thể tùy chỉnh vị trí của dải phân cách mà không yêu cầu nhà thiết kế của bạn vẽ một cái cho bạn ..........


1

Theo cách gọn nhẹ hơn câu trả lời được bình chọn nhiều nhất ...

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

    if ([cell respondsToSelector:@selector(setSeparatorInset:)] && [cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)] && [cell respondsToSelector:@selector(setLayoutMargins:)]) {
         [cell setSeparatorInset:UIEdgeInsetsZero];
         [cell setPreservesSuperviewLayoutMargins:NO];
         [cell setLayoutMargins:UIEdgeInsetsZero];
    }

}


1

Thêm đoạn mã này, thanh lịch đơn giản trong Swift hoạt động với tôi trong iOS8 :)

    // tableview single line
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero
}

1

Điều này hoạt động hoàn hảo cho tôi trong iOS 8 và iOS 9.

Đối với OBJ-C

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  { 
        if ([tableView respondsToSelector:@selector(setSeparatorInset:)])
        {
            [tableView setSeparatorInset:UIEdgeInsetsZero];
        }

        if ([tableView respondsToSelector:@selector(setLayoutMargins:)])
        {
            [tableView setLayoutMargins:UIEdgeInsetsZero];
        }

        if ([cell respondsToSelector:@selector(setLayoutMargins:)])
        {
            [cell setLayoutMargins:UIEdgeInsetsZero];
        }
         return cell;
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.