Separatore di iOS 8 UITableView 0 non funzionante
objective-c swift (20)
Ho un'app in cui il separatore di UITableView
è impostato su valori personalizzati - Destra 0
, Sinistra 0
. Funziona perfettamente su iOS 7.x
, tuttavia in iOS 8.0
vedo che il separatore è impostato sul valore predefinito di 15
sulla destra. Anche se nei file xib è impostato su 0
, viene comunque visualizzato in modo errato.
Come rimuovere i margini del separatore di UITableViewCell
?
https://code.i-harness.com
Estensione Swift 2.0
Volevo solo condividere un'estensione che ho fatto per rimuovere i margini dai separatori di celle tableview.
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
}
}
}
Utilizzato nel contesto:
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell
cell.removeMargins()
return cell
Dopo molte indagini ...
Ecco l'unico modo per controllare completamente questa roba (che potrei trovare)
Per controllare completamente entrambi i separatori e i margini di layout su ogni cella. Fai questo nel metodo willDisplayCell
sul tuo 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)
}
L'oggetto cella controlla il separatore e contentView
controlla tutto il resto. Se i tuoi riquadri separatori sono mostrati in un colore inaspettato, questo dovrebbe risolverlo:
cell.backgroundColor = cell.contentView.backgroundColor
È possibile utilizzare UIAppearance una volta, all'avvio dell'applicazione (prima che venga caricata l'interfaccia utente), per impostarlo come impostazioni globali predefinite:
// 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];
}
In questo modo, manterrai pulito il codice di UIViewController e potrai sempre sostituirlo se lo desideri.
Arg !!! Dopo averlo giocato, esegui questa operazione nella sottoclasse Cell
:
- (UIEdgeInsets)layoutMargins
{
return UIEdgeInsetsZero;
}
o impostando il file cell.layoutMargins = UIEdgeInsetsZero;
risolto per me.
Credo che questa sia la stessa domanda che ho posto qui: Rimuovi SeparatorInset su iOS 8 UITableView per XCode 6 iPhone Simulator
In iOS 8 , c'è una nuova proprietà per tutti gli oggetti ereditati da UIView
. Pertanto, la soluzione per impostare SeparatorInset
in iOS 7.x non sarà in grado di rimuovere lo spazio bianco visualizzato su UITableView in iOS 8.
La nuova proprietà si chiama " 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
La soluzione:-
-(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];
}
}
Se imposti cell.layoutMargins = UIEdgeInsetsZero;
senza verificare se esiste il layoutMargins
, l'app si bloccherà su iOS 7.x. Quindi, il modo migliore sarebbe controllare se il layoutMargins
esiste prima di setLayoutMargins:UIEdgeInsetsZero
.
Dopo aver visto le risposte al terzo piano, ho cercato di capire quale fosse il rapporto tra l'impostazione del separatore tra TableView e TableViewCell e fatto qualche test. Ecco le mie conclusioni:
possiamo considerare che l'impostazione del separatore della cella a zero deve spostare il separatore in due passaggi: il primo passo è impostare il separatorinset della cella su zero. il secondo passo è quello di impostare il marginlayout della cella a zero.
imposta il separatorinset di TableView e marginlayout può influenzare il separatorinset della cella. Tuttavia, dal test, ho trovato che il separatorinset del TableView sembra essere inutile, marginlayout di TableView può effettivamente influenzare marginlayout della cella.
set Cell's PreservesSuperviewLayoutMargins = false, può tagliare l'effetto marginlayout di TableView su Cells.
una delle soluzioni:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell = UITableViewCell() cell.preservesSuperviewLayoutMargins = false cell.separatorInset = UIEdgeInsetsZero cell.layoutMargins = UIEdgeInsetsZero return cell }
In Swift è leggermente più fastidioso perché layoutMargins
è una proprietà, quindi devi scavalcare il getter e setter.
override var layoutMargins: UIEdgeInsets {
get { return UIEdgeInsetsZero }
set(newVal) {}
}
Questo renderà efficacemente layoutMargins
sola lettura, che nel mio caso va bene.
In iOS8:
Aggiungendo questo alla sottoclasse UITableViewCell:
- (UIEdgeInsets)layoutMargins {
return UIEdgeInsetsZero;
}
e questo a "tableView: cellForRowAtIndexPath" o "tableView: willDisplayCell":
[editCell setSeparatorInset:UIEdgeInsetsZero];
LAVORATO per me.
L'ho fatto funzionare in questo modo:
tableView.separatorInset = UIEdgeInsetsZero;
tableView.layoutMargins = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;
La maggior parte delle risposte mostra i separatori ei margini del layout impostati su una varietà di metodi (ad esempio, viewDidLayoutSubviews
, willDisplayCell
, ecc.) Per le celle e le visualizzazioni di tabelle, ma ho scoperto che il semplice inserimento di questi in cellForRowAtIndexPath
funziona alla grande. Sembra il modo più pulito.
// 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];
Per iOS 9 è necessario aggiungere:
if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
myTableView.cellLayoutMarginsFollowReadableWidth = NO;
}
Per maggiori dettagli si prega di fare riferimento alla question .
Per me la linea semplice ha fatto il lavoro
cell.layoutMargins = UIEdgeInsetsZero
Prendiamoci un momento per capire il problema prima di caricarci alla cieca per tentare di risolverlo.
Un rapido colpo nel debugger ti dirà che le linee di separazione sono sottoview di UITableViewCell
. Sembra che la cella stessa abbia una buona dose di responsabilità per il layout di queste linee.
iOS 8 introduce il concetto di margini di layout . Per impostazione predefinita, i margini di layout di una vista sono 8pt
su tutti i lati e sono ereditati dalle viste degli antenati.
Come meglio possiamo dire, quando si stende la sua linea di separazione, UITableViewCell
sceglie di rispettare il margine del layout di sinistra, usandolo per vincolare l'inserto sinistro.
Mettendo tutto ciò insieme, per ottenere l'insetto desiderato di veramente zero, abbiamo bisogno di:
- Imposta il margine sinistro del layout su
0
- Interrompere eventuali margini ereditati ignorando quello
Detto così, è un compito piuttosto semplice da raggiungere:
cell.layoutMargins = UIEdgeInsetsZero;
cell.preservesSuperviewLayoutMargins = NO;
Cose da notare:
- Questo codice deve essere eseguito solo una volta per cella (state solo configurando le proprietà della cella dopo tutto) e non c'è nulla di speciale quando si sceglie di eseguirlo. Fai quello che ti sembra più pulito.
- Purtroppo nessuna delle due proprietà è disponibile per la configurazione in Interface Builder, ma se lo si desidera è possibile specificare un attributo di runtime definito dall'utente per
preservesSuperviewLayoutMargins
. - Chiaramente, se la tua app si rivolge anche a versioni precedenti del sistema operativo, dovrai evitare di eseguire il codice sopra fino all'esecuzione su iOS 8 e versioni successive.
- Anziché impostare
preservesSuperviewLayoutMargins
, è possibile configurare le viste degli antenati (come la tabella) per avere anche0
margine sinistro, ma questo sembra intrinsecamente più soggetto a errori poiché non si controlla l'intera gerarchia. - Probabilmente sarebbe leggermente più pulito per impostare solo il margine sinistro su
0
e lasciare che siano gli altri. - Se vuoi inserire un valore 0 sui separatori "extra" che
UITableView
disegna nella parte inferiore delle tabelle in stile semplice, suppongo che sarà necessario specificare le stesse impostazioni anche a livello di tabella (non ho provato questo!)
Questa è la mia soluzione. Questo vale per la sottoclasse di celle personalizzate, basta aggiungerle entrambe alla sottoclasse.
- (UIEdgeInsets)layoutMargins { return UIEdgeInsetsMake(0, 10, 0, 10); }
2.
self.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10);
Ed è conveniente che tu possa personalizzare la posizione del separatore senza chiedere al tuo disegnatore di disegnarne uno per te ..........
Soluzione semplice in Swift per iOS 8 con UITableViewCell
personalizzato
override func awakeFromNib() {
super.awakeFromNib()
self.layoutMargins = UIEdgeInsetsZero
self.separatorInset = UIEdgeInsetsZero
}
In questo modo stai impostando layoutMargin
e separatorInset
solo una volta invece di farlo per ogni willDisplayCell
come willDisplayCell
maggior parte delle risposte precedenti.
Se stai usando un UITableViewCell
personalizzato, questo è il posto giusto per farlo. Altrimenti dovresti farlo in tableView:cellForRowAtIndexPath
.
Un altro suggerimento: non è necessario impostare preservesSuperviewLayoutMargins = false
perché il valore predefinito è già NO
!
Swift:
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
}
Esempio di 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
}
}
iOS 8.0 introduce la proprietà layoutMargins su celle E viste tabella.
Questa proprietà non è disponibile su iOS 7.0, quindi è necessario assicurarsi di controllare prima di assegnarlo!
Inoltre, Apple ha aggiunto una proprietà alla tua cella che gli impedirà di ereditare le impostazioni dei margini della tua Vista tabella. Quando questa proprietà è impostata, le tue celle possono configurare i propri margini indipendentemente dalla vista tabella. Pensalo come un override.
Questa proprietà si chiama preservesSuperviewLayoutMargins
e impostandola su NO
consentirà all'impostazione layoutMargin
della cella di sovrascrivere qualsiasi layoutMargin
sia impostato su TableView. Risparmia tempo ( non è necessario modificare le impostazioni della Vista tabella ) ed è più conciso. Si prega di fare riferimento alla risposta di Mike Abdullah per una spiegazione dettagliata.
NOTA: ciò che segue è un'implementazione pulita per un'impostazione del margine a livello di cella , come espressa nella risposta di Mike Abdullah. Impostazione delle conserve della cellaSuperviewLayoutMargins = NO garantisce che la vista tabella non sostituisca le impostazioni della cella. Se vuoi che l'intera vista tabella abbia margini coerenti, modifica il codice di conseguenza.
Imposta i margini della tua cella:
-(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
}
}
L'impostazione della proprietà preservesSuperviewLayoutMargins sulla tua cella su NO dovrebbe impedire alla vista tabella di ignorare i margini della cella. In alcuni casi, sembra non funzionare correttamente.
Se tutto fallisce, puoi forzare la forza bruta sui margini della vista tabella:
-(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
}
}
... e ci sei! Questo dovrebbe funzionare su iOS 7 e 8.
EDIT: Mohamed Saleh ha portato alla mia attenzione un possibile cambiamento in iOS 9. Potrebbe essere necessario impostare il valore di cellLayoutMarginsFollowReadableWidth
di Table View su NO
se si desidera personalizzare gli inserti oi margini. Il tuo chilometraggio può variare, questo non è documentato molto bene.
Questa proprietà esiste solo in iOS 9, quindi assicurati di controllare prima di impostare.
if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
myTableView.cellLayoutMarginsFollowReadableWidth = NO;
}
Swift 4:
if myTableView.responds(to: #selector(setter: self.cellLayoutMarginsFollowReadableWidth)) {
myTableView.cellLayoutMarginsFollowReadableWidth = false
}
(codice sopra da iOS 8 UITableView separator inset 0 non funziona )
EDIT: Ecco un approccio puro Interface Builder:
NOTA: iOS 11 cambia e semplifica gran parte di questo comportamento, un aggiornamento sarà imminente ...
In un modo più compatto rispetto alla risposta più votata ...
- (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];
}
}
Questo ha funzionato perfettamente per me su iOS 8 e iOS 9.
Per 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;
}