2016-06-05 29 views
12

Sto cambiando la larghezza di un UITableViewCell in modo che la cella sia più piccola, ma l'utente può ancora scorrere lungo i bordi della tableview.UITableViewCell: angoli arrotondati e ombreggiatura

override func layoutSubviews() {   
    // Set the width of the cell 
    self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width - 40, self.bounds.size.height) 
    super.layoutSubviews() 
} 

Poi ho arrotondare gli angoli:

cell.layer.cornerRadius = 8 
cell.layer.masksToBounds = true 

Tutto bene finora. Il problema si verifica con l'ombra. I limiti sono mascherati, quindi l'ombra ovviamente non verrà visualizzata. Ho cercato altre risposte ma non riesco a capire come arrotondare gli angoli lungo i limiti e mostrare l'ombra.

cell.layer.shadowOffset = CGSizeMake(0, 0) 
cell.layer.shadowColor = UIColor.blackColor().CGColor 
cell.layer.shadowOpacity = 0.23 
cell.layer.shadowRadius = 4 

Quindi la mia domanda - come faccio a ridurre la larghezza, arrotondare gli angoli, e aggiungi un'ombra ad un UITableViewCell allo stesso tempo?

Update: Cercando la risposta di R Moyer

Trying R Moyer's answer

+0

Avete bisogno di 'masksToBounds' abilitato? Potresti essere in grado di aggiustare i vincoli semplicemente non usando quello. Altrimenti, cosa succede se si rende chiaro lo sfondo della cella e si aggiunge un altro 'UIView' all'interno della cella che contiene tutte le viste della cella. Quindi puoi rendere la vista del contenitore più piccola con angoli arrotondati e un'ombra, senza doversi preoccupare che l'ombra venga ritagliata. – dylansturg

risposta

23

Questa domanda arriva in un buon momento! Ho letteralmente risolto SOLAMENTE questo stesso problema.

  1. Creare un UIView (diciamo riferiscono ad essa come mainBackground) all'interno di contenuti del tuo cellulare. Questo conterrà tutti i contenuti della tua cella. Posizionalo e applica i vincoli necessari nello Storyboard.
  2. Creare un altro UIView. Questo sarà quello con l'ombra (chiamiamolo come shadowLayer). Posizionalo esattamente come hai fatto mainBackground, ma dietro di esso e applica gli stessi vincoli.
  3. Ora si dovrebbe essere in grado di impostare gli angoli arrotondati e le ombre come segue:

    cell.mainBackground.layer.cornerRadius = 8 
    cell.mainBackground.layer.masksToBounds = true 
    
    cell.shadowLayer.layer.masksToBounds = false 
    cell.shadowLayer.layer.shadowOffset = CGSizeMake(0, 0) 
    cell.shadowLayer.layer.shadowColor = UIColor.blackColor().CGColor 
    cell.shadowLayer.layer.shadowOpacity = 0.23 
    cell.shadowLayer.layer.shadowRadius = 4 
    

Tuttavia, il problema qui è: calcolare l'ombra per ogni singola cellula è un compito lento. Noterai un certo ritardo quando scorrerai il tuo tavolo. Il modo migliore per risolvere questo problema è definire un UIBezierPath per l'ombra, quindi rasterizzarlo. Quindi potresti voler fare questo:

cell.shadowLayer.layer.shadowPath = UIBezierPath(roundedRect: cell.shadowLayer.bounds, byRoundingCorners: .AllCorners, cornerRadii: CGSize(width: 8, height: 8)).CGPath 
cell.shadowLayer.layer.shouldRasterize = true 
cell.shadowLayer.layer.rasterizationScale = UIScreen.mainScreen().scale 

Ma questo crea un nuovo problema! La forma di UIBezierPath dipende dai limiti di shadowLayer, ma i limiti non sono impostati correttamente dall'ora cellForRowAtIndexPath viene chiamato. Pertanto, è necessario regolare lo shadowPath in base ai limiti di shadowLayer. Il modo migliore per farlo è sottoclasse UIView e aggiungi un osservatore delle proprietà alla proprietà bounds. Quindi imposta tutte le proprietà dell'ombra in didSet. Ricorda di cambiare la classe del tuo shadowLayer nello storyboard in modo che corrisponda alla tua nuova sottoclasse.

class ShadowView: UIView { 
    override var bounds: CGRect { 
     didSet { 
      setupShadow() 
     } 
    } 

    private func setupShadow() { 
     self.layer.cornerRadius = 8 
     self.layer.shadowOffset = CGSize(width: 0, height: 3) 
     self.layer.shadowRadius = 3 
     self.layer.shadowOpacity = 0.3 
     self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: .AllCorners, cornerRadii: CGSize(width: 8, height: 8)).CGPath 
     self.layer.shouldRasterize = true 
     self.layer.rasterizationScale = UIScreen.mainScreen().scale 
    } 
} 
+0

Ho impostato le viste e applicato i vincoli, ma non ha funzionato. Gli angoli sono ancora quadrati e non viene applicata alcuna ombra. Pensato che potrebbe essere perché entrambi i punti di vista non hanno colori, hanno apportato le modifiche necessarie ma senza dadi. –

+0

Le tue opinioni si nascondono dietro la visualizzazione del contenuto della cella? Potresti pubblicare uno screenshot dello storyboard e/o del codice dal tuo UITableViewController? –

+0

No, sono in vantaggio rispetto alla visualizzazione del contenuto nello storyboard. Confermato anche eseguendo il debug della gerarchia della vista durante l'esecuzione dell'app. Ho collegato le prese alla sottoclasse della mia cella, e poi ho usato il tuo codice in 'cellForRowAtIndexPath'. Attualmente armeggiare con esso. –

3

Un approccio alternativo si può provare, prendere un UIView in UITableViewCell. Impostare il colore di sfondo di UITableViewCell per cancellare il colore. Ora puoi creare angoli arrotondati e aggiungere ombre su UIVIew. Questo apparirà come se la larghezza della cella fosse ridotta e l'utente potesse scorrere lungo i bordi della tabellaView.

+0

Attualmente prova questo. –

+0

Lo hai provato? –

6
cell.layer.cornerRadius = 10 
cell.layer.masksToBounds = true 
+0

All'interno di quale funzione dovrebbe andare questo codice? – jlstr

+0

in cellForItemAt indexPath – CMont

5

Per creare ombre e angolo per cellulare è necessario un solo backview. Vedi il mio esempio qui sotto.

enter image description here

si deve aggiungere backView e impostare leading, trailing, top, bottom vincoli pari a Content view. Mettere si accontenta di backView con vincoli del caso, ma essere sicuri il contenuto non oltre baia r backView.

Dopo che nel codice di inizializzazione delle cellule aggiungere queste righe:

override func awakeFromNib() { 
    super.awakeFromNib() 

    backgroundColor = Colors.colorClear 

    self.backView.layer.borderWidth = 1 
    self.backView.layer.cornerRadius = 3 
    self.backView.layer.borderColor = Colors.colorClear.cgColor 
    self.backView.layer.masksToBounds = true 

    self.layer.shadowOpacity = 0.18 
    self.layer.shadowOffset = CGSize(width: 0, height: 2) 
    self.layer.shadowRadius = 2 
    self.layer.shadowColor = Colors.colorBlack.cgColor 
    self.layer.masksToBounds = false 
} 

non dimenticate di creare IBOutlet per Back View.

Ed ecco il risultato:

enter image description here

+0

ha funzionato ma mostra ombra su tutti e 4 gli angoli di visualizzazione. Come aggiungere solo ombra esterna? – Chandni

1

ho raggiunto la stessa cosa usando seguente code.But voi hanno posto in layoutSubviews() metodo della sottoclasse TableViewCell.

self.contentView.backgroundColor = [UIColor whiteColor]; 
self.contentView.layer.cornerRadius = 5; 
self.contentView.layer.shadowOffset = CGSizeMake(1, 0); 
self.contentView.layer.shadowColor = [[UIColor blackColor] CGColor]; 
self.contentView.layer.shadowRadius = 5; 
self.contentView.layer.shadowOpacity = .25; 
CGRect shadowFrame = self.contentView.layer.bounds; 
CGPathRef shadowPath = [UIBezierPath bezierPathWithRect:shadowFrame].CGPath; 
self.contentView.layer.shadowPath = shadowPath; 
0

Prova questo, ha funzionato per me.

cell.contentView.layer.cornerRadius = 5.0 
    cell.contentView.layer.borderColor = UIColor.gray.withAlphaComponent(0.5).cgColor 
    cell.contentView.layer.borderWidth = 0.5 


    let border = CALayer() 
    let width = CGFloat(2.0) 
    border.borderColor = UIColor.darkGray.cgColor 
    border.frame = CGRect(x: 0, y: cell.contentView.frame.size.height - width, width: cell.contentView.frame.size.width, height: cell.contentView.frame.size.height) 

    border.borderWidth = width 
    cell.contentView.layer.addSublayer(border) 
    cell.contentView.layer.masksToBounds = true 
    cell.contentView.clipsToBounds = true 
+0

no non mostra ombra – Chandni

0

Funziona senza visualizzazioni aggiuntive!

override func awakeFromNib() { 
    super.awakeFromNib() 

    layer.masksToBounds = false 
    layer.cornerRadius = Constants.cornerRadius 
} 

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    ... 
    let layer = cell.layer 
    layer.shadowOffset = CGSize(width: 0, height: 1) 
    layer.shadowRadius = 2 
    layer.shadowColor = UIColor.lightGray.cgColor 
    layer.shadowOpacity = 0.2 
    layer.frame = cell.frame 
    cell.tagLabel.text = tagItems[indexPath.row].text 

    return cell 
} 
+0

Mi ha dato ombra ma il cerchio della mia cella cambia schermata di controllo pls https://www.dropbox.com/s/oy5ec9hee2krz0s/Screen%20Shot%202018-02-16%20at%202.15. 35% 20 AM.png? Dl = 0 – Chandni

+0

e voglio questo effetto https://stackoverflow.com/questions/48809557/how-to-do-shadow-effect-in-collection-view-and-table-view- cellulare? noredirect = 1 # comment84625789_48809557 – Chandni