2017-01-17 1 views
0

Comment créer un IBDesignable UITextView de sorte que je puisse ajuster les encarts du texte dans le constructeur d'interface? J'ai ajouté topInset, propriétés inspectables bottomInset, etc., mais maintenant, je vais avoir du mal à la figure de comment mettre à jour réellement EISN de la UITextView tels que les changements se reflètent dans IBUITextView IBDesignable Padding

import UIKit 

private let kPlaceholderTextViewInsetSpan: CGFloat = 8 

@IBDesignable class UIDesignableTextView: UITextView { 
    // variables 

    @IBInspectable var topInset: CGFloat = 0.0 
    @IBInspectable var leftInset: CGFloat = 0.0 
    @IBInspectable var bottomInset: CGFloat = 0.0 
    @IBInspectable var rightInset: CGFloat = 0.0 

    var insets: UIEdgeInsets { 
     get { 
      return UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset) 
     } 
     set { 
      topInset = newValue.top 
      leftInset = newValue.left 
      bottomInset = newValue.bottom 
      rightInset = newValue.right 
     } 
    } 

    @IBInspectable var placeholder: NSString? { didSet { setNeedsDisplay() } } 
    @IBInspectable var placeholderColor: UIColor = UIColor.lightGray 

    override var text: String! { didSet { setNeedsDisplay() } } 

    override var attributedText: NSAttributedString! { didSet { setNeedsDisplay() } } 

    override var contentInset: UIEdgeInsets { didSet { setNeedsDisplay() } } 

    override var font: UIFont? { didSet { setNeedsDisplay() } } 

    override var textAlignment: NSTextAlignment { didSet { setNeedsDisplay() } } 

    // MARK: - Lifecycle 

    /** Override coder init, for IB/XIB compatibility */ 
    #if !TARGET_INTERFACE_BUILDER 
    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     listenForTextChangedNotifications() 
    } 

    /** Override common init, for manual allocation */ 
    override init(frame: CGRect, textContainer: NSTextContainer?) { 
     super.init(frame: frame, textContainer: textContainer) 
     listenForTextChangedNotifications() 
    } 
    #endif 

    /** Initializes the placeholder text view, waiting for a notification of text changed */ 
    func listenForTextChangedNotifications() { 
     NotificationCenter.default.addObserver(self, selector: #selector(UIDesignableTextView.textChangedForPlaceholderTextView(_:)), name:NSNotification.Name.UITextViewTextDidChange , object: self) 
     NotificationCenter.default.addObserver(self, selector: #selector(UIDesignableTextView.textChangedForPlaceholderTextView(_:)), name:NSNotification.Name.UITextViewTextDidBeginEditing , object: self) 
    } 

    /** willMoveToWindow will get called with a nil argument when the window is about to dissapear */ 
    override func willMove(toWindow newWindow: UIWindow?) { 
     super.willMove(toWindow: newWindow) 
     if newWindow == nil { NotificationCenter.default.removeObserver(self) } 
     else { listenForTextChangedNotifications() } 
    } 

      func textChangedForPlaceholderTextView(_ notification: Notification) { 
     setNeedsDisplay() 
     setNeedsLayout() 
    } 

    override func draw(_ rect: CGRect) { 
     super.draw(rect) 

     if text.characters.count == 0 && self.placeholder != nil { 
      let baseRect = placeholderBoundsContainedIn(self.bounds) 
      let font = self.font ?? self.typingAttributes[NSFontAttributeName] as? UIFont ?? UIFont.systemFont(ofSize: UIFont.systemFontSize) 

      self.placeholderColor.set() 

      var customParagraphStyle: NSMutableParagraphStyle! 
      if let defaultParagraphStyle = typingAttributes[NSParagraphStyleAttributeName] as? NSParagraphStyle { 
       customParagraphStyle = defaultParagraphStyle.mutableCopy() as! NSMutableParagraphStyle 
      } else { customParagraphStyle = NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle } 
      // set attributes 
      customParagraphStyle.lineBreakMode = NSLineBreakMode.byTruncatingTail 
      customParagraphStyle.alignment = self.textAlignment 
      let attributes = [NSFontAttributeName: font, NSParagraphStyleAttributeName: customParagraphStyle.copy() as! NSParagraphStyle, NSForegroundColorAttributeName: self.placeholderColor] 
      // draw in rect. 
      self.placeholder?.draw(in: baseRect, withAttributes: attributes) 
     } 
    } 

    func placeholderBoundsContainedIn(_ containerBounds: CGRect) -> CGRect { 
     // get the base rect with content insets. 
     let baseRect = UIEdgeInsetsInsetRect(containerBounds, UIEdgeInsetsMake(kPlaceholderTextViewInsetSpan, kPlaceholderTextViewInsetSpan/2.0, 0, 0)) 

     // adjust typing and selection attributes 
     if let paragraphStyle = typingAttributes[NSParagraphStyleAttributeName] as? NSParagraphStyle { 
      baseRect.offsetBy(dx: paragraphStyle.headIndent, dy: paragraphStyle.firstLineHeadIndent) 
     } 

     return baseRect 
    } 

Répondre

1

C'est tout ce que vous avez besoin à faire:

import UIKit 

@IBDesignable class TextViewWithInsets: UITextView { 

    @IBInspectable var topInset: CGFloat = 0 { 
     didSet { 
      self.contentInset = UIEdgeInsetsMake(topInset, self.contentInset.left, self.contentInset.bottom, self.contentInset.right) 
     } 
    } 

    @IBInspectable var bottmInset: CGFloat = 0 { 
     didSet { 
      self.contentInset = UIEdgeInsetsMake(self.contentInset.top, self.contentInset.left, bottmInset, self.contentInset.right) 
     } 
    } 

    @IBInspectable var leftInset: CGFloat = 0 { 
     didSet { 
      self.contentInset = UIEdgeInsetsMake(self.contentInset.top, leftInset, self.contentInset.bottom, self.contentInset.right) 
     } 
    } 

    @IBInspectable var rightInset: CGFloat = 0 { 
     didSet { 
      self.contentInset = UIEdgeInsetsMake(self.contentInset.top, self.contentInset.left, self.contentInset.bottom, rightInset) 
     } 
    } 
} 

Comme vous pouvez le voir, ce sont des propriétés de la sous-classe de TextViewWithInsetsUITextView J'ai créé. Vous devez remplacer la partie didSet de la méthode de propriété. Ensuite, dans Interface Builder, ces quatre propriétés (Encart supérieur, Encart inférieur, Encadré à gauche et Encadré à droite) apparaîtront dans l'Inspecteur des attributs:

Assurez-vous que dans Identity Inspector, vous définissez l'objet TextView dans le storyboard être TextViewWithInsets ou quoi que vous choisissiez de le nommer comme ceci: Set class of Text View object in storyboard to custom class

+0

Est-ce que cette aide a répondu à votre question? Faites-moi savoir si vous essayez toujours de comprendre cela. – eschos24