2014-04-13 13 views
6

Ho costruito un UITextView crescente attaccato alla tastiera, simile a quello di App Stock Messaggi, caricando un .xib nella inputAccessoryView della tastiera in quanto tale:iOS Tastiera - ingresso Accessori Vedi XI ter con layout automatico non ricevere evento di tocco

self.keyboardAccessoryView = [[[NSBundle mainBundle] 
          loadNibNamed:@"KeyboardAccessoryView" 
          owner:self options:nil] 
          firstObject]; 

il .xib assomiglia a questo e sta usando vincoli di layout in modo che il textView cresce verticalmente quando l'utente inserisce più righe di testo:

enter image description here

Ciò è tanto grande lavoro, con rotazione e everythi ng, tranne un grosso bug - quando il testo è composto da più righe, solo la linea di fondo gestisce gli eventi di tocco. Ciò significa che un utente non può scorrere all'interno di UITextView perché i suoi eventi di tocco vengono passati alla vista (grigio scuro) sul retro e lo scorrimento invece. Inoltre non possono selezionare e modificare il loro testo sulle prime 3 righe.

enter image description here

credo che avrei potuto fare una soluzione catturando le coordinate di tutti gli eventi rubinetteria e controllando se la tastiera è aperta e l'altezza del UITextView è, quindi selezionando l'elemento corretto per ricevere l'evento di tocco. Ma questa è una soluzione fragile che è più complicata con la rotazione. C'è qualcosa che mi manca nel mio approccio di visualizzazione del testo auto-crescente o una soluzione più semplice?

+0

Ho problemi con i vincoli del layout automatico per far crescere verticalmente la vista accessoria. Sto giocando con il layout Qualche possibilità che tu possa condividere alcune intuizioni lì? Posso solo aumentare la visualizzazione del testo (modificando il suo vincolo di dimensione) mentre la sua vista accessoria del contenitore rimane la sua dimensione originale. – rainypixels

risposta

2

Ho capito che anche se l'ingresso dell'accessorio per tastiera cresce in verticale con il layout automatico, il suo frame no. Pertanto, è necessario regolare la cornice dell'accessorio della tastiera ogni volta che l'altezza di uitextview aumenta, si riduce e ruota. Questo introduce alcune complicazioni in quanto UITextView in iOS7 è notoriamente bacato - ho notato che il comportamento non era coerente su iPhone, iPad e il simulatore.

+2

Hai qualche codice per questo? – Magoo

5

Per rendere vista accessorio ingresso crescere verticalmente appena impostato il suo autoresizingMask = .flexibleHeight, calcolare la sua intrinsicContentSize e lasciare che il quadro faccia il resto.

Il codice:

class InputAccessoryView: UIView, UITextViewDelegate { 

    let textView = UITextView() 

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

     // This is required to make the view grow vertically 
     self.autoresizingMask = UIViewAutoresizing.flexibleHeight 

     // Setup textView as needed 
     self.addSubview(self.textView) 
     self.textView.translatesAutoresizingMaskIntoConstraints = false 
     self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[textView]|", options: [], metrics: nil, views: ["textView": self.textView])) 
    self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[textView]|", options: [], metrics: nil, views: ["textView": self.textView])) 

     self.textView.delegate = self 

     // Disabling textView scrolling prevents some undesired effects, 
     // like incorrect contentOffset when adding new line, 
     // and makes the textView behave similar to Apple's Messages app 
     self.textView.scrollEnabled = false 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    override var intrinsicContentSize: CGSize { 
     // Calculate intrinsicContentSize that will fit all the text 
     let textSize = self.textView.sizeThatFits(CGSize(width: self.textView.bounds.width, height: CGFloat.max)) 
     return CGSize(width: self.bounds.width, height: textSize.height) 
    } 

    // MARK: UITextViewDelegate 

    func textViewDidChange(_ textView: UITextView) { 
     // Re-calculate intrinsicContentSize when text changes 
     self.invalidateIntrinsicContentSize() 
    } 

} 

Questo approccio è molto semplice ed affidabile, in quanto non richiede l'hacking vincoli o ricreare la vista ogni volta che i suoi cambiamenti di dimensione.

+0

penso che questo passi ancora attraverso il touch alla vista dietro la vista accessoria anche se – Erich

+0

@Erich I ha ricontrollato e non ha avuto problemi con la propagazione degli eventi di tocco quando si utilizza questo approccio. Forse la configurazione della vista degli accessori di input è diversa in qualche modo? Il mio è basato su questo: https://robots.thoughtbot.com/input-accessorizing-uiviewcontroller – maxkonovalov

+0

Questo è semplicemente fantastico! Max, grazie mille per aver condiviso con noi. –