2016-04-28 4 views
2

現在、私はIBDesignable Viewsを使いこなしています。誰でもこれを解決できるかどうか不思議です。私は、インターフェイスビルダーを介して自動的にカスタムレイアウトアルゴリズムを使用して私のサブビュー内で配列されたビューを追加したいと思います。このビューは、アプリケーションを実行するときに効果的ですが、インターフェースビルダーでは、ビューはリアルタイムで再配置されません。IBDesignable - インターフェースビルダーを介して追加されたサブビューを整理する

UIViewクラスをデバッグしようとしましたが、インタフェースビルダーが要素を初期化していると思われますが、サブビューがゼロであると考えられます。インタフェースビルダーは、事実の後にこれらのビューを整理する機会を与えてくれないようです。しかし、もし私が不足しているものがあるのではないかと思っています。 IBDesignableクラス内のインターフェースビルダーから追加されたサブビューを並べ替えることは可能ですか?また、ビューがインターフェースビルダーに再配置されて表示されますか?

答えて

0

カスタムビューでは、提供されている方法を使用していない場合は、IBDesignableを使用してみます。また、Xcodeでビューを更新するか、自動的にビューを更新する必要があるかもしれません。以下は、あなたが逃している可能性のある機能です。これはライブアプリでは決して呼び出されません。これはXcode IBでのみ呼び出されます。

override func prepareForInterfaceBuilder() { 
    super.prepareForInterfaceBuilder() 
    setUpView() 
} 

この場合、setUpViewはサブビューをレイアウトしています。
ここに私が作成した例があります。

import UIKit 

@IBDesignable class AGIconButton: UIControl { 

private var iconImageView : UIImageView! 
private var iconLabel : UILabel! 
private var mainSpacer : UIView! 
private var highlightView:UIView! 
private var widthContraint : NSLayoutConstraint! 
var padding : CGFloat = 5 


override init(frame: CGRect) { 
    super.init(frame: frame) 
    setUpView() 
    addTarget(self, action: #selector(AGIconButton.userDidTouchDown), for: .touchDown) 
    addTarget(self, action: #selector(AGIconButton.userDidTouchUp), for: .touchUpInside) 
    addTarget(self, action: #selector(AGIconButton.userDidTouchUpOutside), for: .touchUpOutside) 

} 

required init?(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 
    setUpView() 
    addTarget(self, action: #selector(AGIconButton.userDidTouchDown), for: .touchDown) 
    addTarget(self, action: #selector(AGIconButton.userDidTouchUp), for: .touchUpInside) 
    addTarget(self, action: #selector(AGIconButton.userDidTouchUpOutside), for: .touchUpOutside) 


} 

//only called at design time 
override func prepareForInterfaceBuilder() { 
    super.prepareForInterfaceBuilder() 
    setUpView() 
    addTarget(self, action: #selector(AGIconButton.userDidTouchDown), for: .touchDown) 
    addTarget(self, action: #selector(AGIconButton.userDidTouchUp), for: .touchUpInside) 
    addTarget(self, action: #selector(AGIconButton.userDidTouchUpOutside), for: .touchUpOutside) 

} 




@IBInspectable var iconImage: UIImage = UIImage() { 
    didSet { 
     iconImageView.image = iconImage 
    } 
} 


@IBInspectable var imageSize: CGFloat = 40 { 
    didSet { 
     setUpView() 
    } 
} 


@IBInspectable var imagePadding: CGFloat = 10 { 
    didSet { 
      setUpView() 
    } 
} 

@IBInspectable var iconText: String = "Icon Button Time" { 
    didSet { 
      setUpView() 
    } 
} 

@IBInspectable var iconTextSize: CGFloat = 15 { 
    didSet { 
      setUpView() 
    } 
} 

@IBInspectable var iconTextColor: UIColor = UIColor.black { 
    didSet { 
     setUpView() 
    } 
} 

@IBInspectable var alignment: Int = 1 { 
    didSet { 
     setUpView() 
    } 
} 


override var intrinsicContentSize: CGSize { 
    let label = UILabel() 
    label.font = UIFont.systemFont(ofSize: iconTextSize) 
    label.text = iconText 
    label.sizeToFit() 
    return CGSize(width: imageSize + label.frame.width + imagePadding + (padding * 2), height: CGFloat(max(label.frame.height, imageSize) + padding * 2)) 
} 


@IBInspectable var highLightColor: UIColor = UIColor.lightGray { 
    didSet { 
     setUpView() 
    } 
} 

@IBInspectable var shouldBounce: Bool = true 

@IBInspectable var borderColor: UIColor = UIColor.clear { 
    didSet { 
     layer.borderColor = borderColor.cgColor 
    } 
} 

@IBInspectable var borderWidth: CGFloat = 0 { 
    didSet { 
     layer.borderWidth = borderWidth 
    } 
} 

@IBInspectable var cornerRadius: CGFloat = 0 { 
    didSet { 
     layer.cornerRadius = cornerRadius 
    } 
} 

private func setUpView(){ 

    if iconImageView == nil{ 
     iconImageView = UIImageView(image: iconImage) 
     iconImageView.contentMode = .scaleAspectFit 
     iconImageView.isUserInteractionEnabled = false 
     self.addSubview(iconImageView) 

    } 

    if mainSpacer == nil{ 
     mainSpacer = UIView(frame: CGRect(x: 0, y: 0, width: imagePadding, height: self.bounds.height)) 
     mainSpacer.isUserInteractionEnabled = false 
     self.addSubview(mainSpacer) 
    } 



    if iconLabel == nil{ 
     iconLabel = UILabel() 
     iconLabel.isUserInteractionEnabled = false 
     self.addSubview(iconLabel) 

    } 

    if highlightView == nil{ 
     highlightView = UIView(frame: self.bounds) 
     highlightView.autoresizingMask = [.flexibleWidth,.flexibleHeight] 
     highlightView.alpha = 0 
     highlightView.isUserInteractionEnabled = false 
     self.addSubview(highlightView) 
     self.bringSubview(toFront: highlightView) 
    } 
    highlightView.backgroundColor = highLightColor 

    iconLabel.font = UIFont.systemFont(ofSize: iconTextSize) 
    iconLabel.text = iconText 
    iconLabel.textColor = iconTextColor 
    iconLabel.sizeToFit() 


    var usedWidth : CGFloat = self.intrinsicContentSize.width 

    if bounds.width < usedWidth{ 
     usedWidth = bounds.width 
    } 

    let maxImageHeight = min(self.bounds.height - padding, imageSize) 

    //resize iconlabel if we have to 
    if maxImageHeight + imagePadding + iconLabel.bounds.width + padding * 2 > usedWidth{ 
     iconLabel.frame = CGRect(x: 0, y: 0, width: self.bounds.width - iconImageView.bounds.width - imagePadding - padding * 2, height: iconLabel.bounds.height) 
     iconLabel.fitFontForSize(minFontSize: 1, maxFontSize: iconTextSize, accuracy: 1.0) 

    } 

    let maxWidth = (self.bounds.width - iconLabel.bounds.width - maxImageHeight - imagePadding)/2 

    switch alignment { 
    case 0: 
     //intrinsic left 
     iconImageView.frame = CGRect(x:padding, y: self.bounds.midY - maxImageHeight/2,width:maxImageHeight, height: maxImageHeight) 
     mainSpacer.frame = CGRect(x: maxImageHeight + padding, y: 0, width: imagePadding, height: self.bounds.height) 
     iconLabel.frame = CGRect(x: maxImageHeight + imagePadding + padding, y: 0, width: iconLabel.frame.width, height: bounds.height) 

     break 
    case 1: 
     //intrinsic center 
     iconImageView.frame = CGRect(x: maxWidth, y: self.bounds.midY - maxImageHeight/2,width:maxImageHeight, height: maxImageHeight) 
     mainSpacer.frame = CGRect(x: maxWidth + maxImageHeight, y: 0, width: imagePadding, height: self.bounds.height) 
     iconLabel.frame = CGRect(x: maxWidth + maxImageHeight + imagePadding, y: 0, width: iconLabel.frame.width, height: self.bounds.height) 
     break 
    case 2: 
     //intrinsic icon right text aligned right 
     iconLabel.frame = CGRect(x: maxWidth, y: 0, width: iconLabel.frame.width, height: self.bounds.height) 
     iconLabel.textAlignment = .right 
     mainSpacer.frame = CGRect(x: iconLabel.frame.width + maxWidth, y: 0, width: imagePadding, height: self.bounds.height) 
     iconImageView.frame = CGRect(x: iconLabel.frame.width + imagePadding + maxWidth, y: self.bounds.midY - maxImageHeight/2,width:maxImageHeight, height: maxImageHeight) 
     break 
    case 3: 
     //intrinsic center invert icon 
     iconLabel.frame = CGRect(x:maxWidth, y: 0, width: iconLabel.frame.width, height: self.bounds.height) 
     mainSpacer.frame = CGRect(x: maxWidth + iconLabel.bounds.width, y: 0, width: imagePadding, height: self.bounds.height) 
     iconImageView.frame = CGRect(x: maxWidth + iconLabel.bounds.width + imagePadding, y: self.bounds.midY - maxImageHeight/2,width:maxImageHeight, height: maxImageHeight) 

     break 

    default: 
     //intrinsic center 
     iconImageView.frame = CGRect(x: maxWidth, y: self.bounds.midY - maxImageHeight/2,width:maxImageHeight, height: maxImageHeight) 
     mainSpacer.frame = CGRect(x: maxWidth + maxImageHeight, y: 0, width: imagePadding, height: self.bounds.height) 
     iconLabel.frame = CGRect(x: maxWidth + maxImageHeight + imagePadding, y: 0, width: iconLabel.frame.width, height: self.bounds.height) 
    } 


} 


//layout subviews 
override func layoutSubviews() { 
    super.layoutSubviews() 
    setUpView() 
} 


//MARK: Touch Events 
//TODO: run on timer to simulate a real press 
func userDidTouchDown(){ 
    if shouldBounce == true{ 
     animateBouncyDown() 
    }else{ 
     self.animateHighlightTo(alpha: 0.3) 
    } 

} 


func userDidTouchUp(){ 
    if shouldBounce == true{ 
     animateBouncyUp() 
    }else{ 
     self.animateHighlightTo(alpha: 0) 
    } 
} 

func userDidTouchUpOutside(){ 
    if shouldBounce == true{ 
     animateBouncyUp() 
    }else{ 
     self.animateHighlightTo(alpha: 0) 
    } 
} 

func animateHighlightTo(alpha:CGFloat){ 
    UIView.animate(withDuration: 0.2, animations: { [weak self] in 
     self?.highlightView.alpha = alpha 
    }) 

} 

func animateBouncyDown(){ 
    self.transform = CGAffineTransform.identity 
    UIView.animate(withDuration: 0.15, animations: { [weak self] in 
     self?.transform = CGAffineTransform(scaleX: 0.85, y: 0.85) 
    }) 
} 

func animateBouncyUp(){ 
    UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.8, options: .curveEaseInOut, animations: {[weak self] in 
     if self != nil{ 
      self?.transform = CGAffineTransform.identity 
     } 
    }, completion: nil) 
} 
} 

extension UILabel { 

func fitFontForSize(minFontSize : CGFloat = 1.0, maxFontSize : CGFloat = 300.0, accuracy : CGFloat = 1.0) { 
    var maxFontSize = maxFontSize 
    var minFontSize = minFontSize 
    assert(maxFontSize > minFontSize) 
    layoutIfNeeded() // Can be removed at your own discretion 
    let constrainedSize = bounds.size 
    while maxFontSize - minFontSize > accuracy { 
     let midFontSize : CGFloat = ((minFontSize + maxFontSize)/2) 
     font = font.withSize(midFontSize) 
     sizeToFit() 
     let checkSize : CGSize = bounds.size 
     if checkSize.height < constrainedSize.height && checkSize.width < constrainedSize.width { 
      minFontSize = midFontSize 
     } else { 
      maxFontSize = midFontSize 
     } 
    } 
    font = font.withSize(minFontSize) 
    sizeToFit() 
    layoutIfNeeded() 
} 
    } 
関連する問題