2013-10-08 9 views
9

Sto usando iOS 7 e sto provando a spostare un'etichetta centrata sulla sinistra della mia vista. Attualmente sto cercando di farlo cambiando il modo in cui la mia UILabel è allineata e sto cercando di animarla nel processo. Attualmente sto chiamando il seguente:C'è un modo per animare cambiando il testo di un UILabel?

[UIView animateWithDuration:0.5 
       animations:^{ 
         self.monthLabel.textAlignment = NSTextAlignmentLeft; 
       } completion:nil]; 

Ma questo salta l'etichetta al nuovo allineamento. C'è un modo per animare questo, o un modo migliore per regolare l'etichetta per farlo accadere?

risposta

9

Impostare la dimensione del frame UILabel per contenere esattamente il testo e centrare l'UILabel nella visualizzazione.

self.monthLabel.text = @"February"; 
[self.monthLabel sizeToFit]; 
self.monthLabel.center = parentView.center; // You may need to adjust the y position 

quindi impostare l'allineamento che non dovrebbe di influenza sulla configurazione dal momento che non ci sarà spazio.

self.monthLabel.textAlignment = NSTextAlignmentLeft; 

Quindi, animare la dimensione del frame UILabel in modo che scorra dove lo vuoi.

[UIView animateWithDuration:0.5 
      animations:^{ 
        CGRect frame = self.monthLabel.frame; 
        frame.origin.x = 10; 
        self.monthLabel.frame = frame; 
      } completion:nil]; 
+0

Non riesco a impostare la cornice sulla dimensione esatta della mia etichetta, poiché il testo cambierà, in particolare con il nome di diversi mesi – lehn0058

+0

Aggiornare la cornice dell'etichetta nello stesso momento in cui si imposta il testo. Ho aggiornato la risposta per mostrare come farlo. – bbarnhart

+0

@bbarnhart cosa succede se nell'etichetta sono presenti 2 righe di testo? Di questo non funziona ... –

1

è possibile animare il FRAME, non il testoAlignment.

Fare un [UILabel sizeToFit] sull'etichetta se si vuole sbarazzarsi di qualsiasi "padding" sul telaio, quindi è possibile animare la cornice nel blocco di animazione per spostarla come volete

CGRect frameLabel = self.monthLabel.frame; 

[UIView animateWithDuration:0.5 
       animations:^{ 
         frameLabel.origin.x -= 100;   // e.g. move it left by 100 
         self.monthLabel.frame = frameLabel; 
       } completion:nil]; 
+0

Mi piace questo approccio! Ho bisogno di avere la mia etichetta centrata (in questo momento sta mostrando il nome di un mese sopra una vista della collezione del calendario) quindi giocherò con questa e inizialmente imposterò il centro dell'etichetta invece di provare ad usare textAlignment – lehn0058

+0

se vuoi impostare la variabile "frameLabel" nell'animazione del blocco è necessario impostare la variabile con il prefisso di accesso "__block CGRect frameLabel" ..., perché si modificherà la variabile valore frameLabel nel blocco. – horkavlna

0

hai solo bisogno di animare la cornice dell'etichetta. Poiché qui il blocco di completamento è presente, è necessario modificare nuovamente il frame. e fai andare il ciclo.

[UIView animateWithDuration:0.5 
       animations:^{ 
         // Change the frame 
       } completion:^{[UIView animateWithDuration:0.5 
       animations:^{ 
         // Change the frame 
       } completion:^{ 
        // repeat the proccess 
}] 

}]; 
+0

Lo farei, ma ho il riempimento su entrambi i lati dell'etichetta poiché il mio testo cambierà in base al mese selezionato dall'utente. – lehn0058

2

La tua etichetta è multilinea? Un'animazione come questa: http://img62.imageshack.us/img62/9693/t7hx.png?

Se è così, allora ci sono un paio di alternative.

etichetta multilinea

Opzione 1:

Invece di un'animazione UIView tradizionale, provare una transizione UIView. Il testo non scivolerà verso sinistra, ma invece si attenuerà piacevolmente alla nuova posizione.

[UIView transitionWithView:self.monthLabel 
         duration:0.5 
         options:UIViewAnimationOptionTransitionCrossDissolve 
        animations:^{ 
     self.monthLabel.textAlignment = NSTextAlignmentLeft; 
    } completion:NO]; 

Opzione 2:

È possibile lavorare manualmente dove appariranno le nuove linee, quindi creare un UILabel separato per ogni riga di testo poi animare i fotogrammi. Questo è ovviamente più lavoro, ma darà quell'animazione di diapositiva desiderata.

etichetta singola linea

Invece di animare la TextAlignment, rendere l'etichetta stessa dimensione della stringa che contiene con [self.monthLabel sizeToFit], quindi lavorare manualmente l'inquadratura e la centratura. Quindi è sufficiente animare il fotogramma, lo stesso dell'opzione 2 su un'etichetta multilinea.

0

Questo mi ha servito bene

import Foundation 
import UIKit 


class AnimatableMultilineLabel: UIView { 

    enum Alignment { 
     case left 
     case right 
    } 

    public var textAlignment: Alignment = .left { 
     didSet { 
      layout() 
     } 
    } 

    public var font: UIFont? = nil { 
     didSet { 
      setNeedsLayout() 
     } 
    } 

    public var textColor: UIColor? = nil { 
     didSet { 
      setNeedsLayout() 
     } 
    } 

    public var lines: [String] = [] { 
     didSet { 
      for label in labels { 
       label.removeFromSuperview() 
      } 
      labels = [] 
      setNeedsLayout() 
     } 
    } 

    private var labels: [UILabel] = [] 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     setup() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     setup() 
    } 

    private func setup() { 
     isUserInteractionEnabled = false 
    } 

    override func layoutSubviews() { 
     super.layoutSubviews() 

     layout() 
    } 

    private func layout() { 

     autocreateLabels() 

     var yPosition: CGFloat = 0.0 
     for label in labels { 
      let size = label.sizeThatFits(bounds.size) 
      let minX = textAlignment == .left ? 0.0 : bounds.width - size.width 
      let frame = CGRect(x: minX, y: yPosition, width: size.width, height: size.height) 
      label.frame = frame 
      yPosition = frame.maxY 
     } 
    } 

    private func autocreateLabels() { 
     if labels.count != lines.count { 
      for text in lines { 
       let label = UILabel() 
       label.font = font 
       label.textColor = textColor 
       label.text = text 
       addSubview(label) 
       labels.append(label) 
      } 
     } 
    } 

    override func sizeThatFits(_ size: CGSize) -> CGSize { 
     autocreateLabels() 

     var height: CGFloat = 0.0 
     for label in labels { 
      height = label.sizeThatFits(size).height 
     } 
     return CGSize(width: size.width, height: height) 
    } 
} 

allora si dovrebbe essere in grado di

UIView.animate(withDuration: 0.5, animations: { 
    multilineLabel.textAlignment = .right 
}) 
+0

Interessante. Come decidi quali linee separare? – agibson007

+0

Tutte le linee erano senza interruzioni quindi sapevo che avrei potuto dichiararlo in questo modo. Una soluzione più intelligente prenderebbe una stringa attribuita e animerebbe correttamente le interruzioni di riga automaticamente. – hfossli

Problemi correlati