自定义导航栏项目放置不当

时间:2017-01-19 20:53:56

标签: ios swift cocoa-touch

我有一个自定义导航栏子类:

class ProfileNavigationBar: UINavigationBar {

  var titleLabel: UILabel
  var backButton: UIBarButtonItem
  var friendsButton: FriendsButton?

  required init?(coder: NSCoder) {
    titleLabel = UILabel(frame: CGRect(x: 0, y: 40, width: 320, height: 40))
    backButton = UIBarButtonItem.backButton(nil, action: nil)
    friendsButton = FriendsButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24))
    super.init(coder: coder)
  }

  override func awakeFromNib() {
    super.awakeFromNib()

    let item = UINavigationItem()
    item.titleView = titleLabel

    item.leftBarButtonItem = backButton
    item.hidesBackButton = true

    let friendsItem = UIBarButtonItem(customView: friendsButton!)
    item.rightBarButtonItems = [friendsItem]

    pushItem(item, animated: false)
  }

}

当FriendsButton的状态属性发生变化时,FriendsButton会自行调整大小。

问题是,当首次加载视图时,它看起来像这样,后退按钮和FriendsButton就在导航栏的边缘:( .loading state)

enter image description here

但是,当我将FriendsButton状态更改为.add时,通常会显示如下:

enter image description here

我该如何解决这个问题?

以下是FriendsButton的实现:

class FriendsButton: UIView {

  var state: FriendsButtonState {
    didSet {
      style(selected: state)
    }
  }

  var title: String = "" {
    didSet {
      set(title: title)
    }
  }

  var font = UIFont.boldSystemFont(ofSize: 11)

  private var imageView: UIImageView!
  private var button: UIButton!
  var loading: UIActivityIndicatorView!

  init(frame: CGRect, state: FriendsButtonState = .loading) {
    self.state = state
    super.init(frame: frame)
    backgroundColor = .yellow

    let plusSize = frame.size.height/2
    let plusYValue = (frame.size.height-plusSize)/2
    imageView = UIImageView(frame: CGRect(x: plusYValue*2, y: plusYValue, width: plusSize, height: plusSize))
    imageView.contentMode = .scaleAspectFit
    addSubview(imageView)

    let titleSize = (title as NSString).size(attributes: [NSFontAttributeName : font])
    button = UIButton(frame: CGRect(x: plusYValue*3.5 + plusSize, y: 0, width: titleSize.width, height: frame.size.height))
    addSubview(button)

    loading = UIActivityIndicatorView(activityIndicatorStyle: .gray)
    loading.center = center
    addSubview(loading)

    style(selected: state)

    updateSize()
  }

  func addTarget(object: Any, selector: Selector) {
    button.addTarget(object, action: selector, for: .touchUpInside)
  }

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

  private func style(selected: FriendsButtonState) {
    configureBorder(state: selected)
    loading.startAnimating()
    loading.isHidden = state != .loading
    isHidden = false

    switch state {
    case .friends:
      backgroundColor = .black
      button.setTitleColor(.white, for: .normal)
      imageView.image = #imageLiteral(resourceName: "friends-tick")
      title = "Friends"
    // ... + all other cases
    }
    self.updateSize()
  }

  private func configureBorder(state: FriendsButtonState) {
    layer.borderColor = UIColor.black.cgColor
    layer.borderWidth = state == .loading ? 0 : 1
    layer.cornerRadius = 5
  }

  private func set(title: String) {
    let plusSize = frame.size.height/2
    let plusYValue = (frame.size.height-plusSize)/2
    let titleSize = (title as NSString).size(attributes: [NSFontAttributeName : font])
    button.titleLabel?.font = font
    button.setTitle(title, for: .normal)
    button.frame = CGRect(x: plusYValue*3.5 + plusSize, y: 0, width: titleSize.width, height: frame.size.height)
    self.updateSize()
  }

  private func updateSize() {
    if state == .loading {
      frame.size.width = frame.size.width
      loading.center = CGPoint(x: frame.size.width/2, y: frame.size.height/2)
      loading.startAnimating()
      return
    }

    let plusSize = frame.size.height/2
    let plusYValue = (frame.size.height-plusSize)/2
    let titleSize = (title as NSString).size(attributes: [NSFontAttributeName : font])
    let totalWidth = plusYValue*5.5 + plusSize + titleSize.width
    frame.size.width = totalWidth
  }

编辑:我最初尝试将按钮设置为.add状态,但它仍会显示在导航栏的最右侧,直到它更改为其他状态。似乎按钮的第一个状态总是使导航栏将其所有子项移动到帧的边缘,直到它被更新。

编辑:我无法通过复制相关代码在其他项目上重现问题,但这是我遇到的具体问题(如下图所示)。首次导航到视图时,导航栏边缘和后退按钮之间的间隙不会保持(我设法在导航推送动画的中途获得屏幕截图)。我现在的问题是,是什么导致这种情况?

enter image description here

3 个答案:

答案 0 :(得分:3)

您必须停止活动指示器,否则它不会隐藏自己:

private func style(selected: FriendsButtonState) {
    configureBorder(state: selected)
    if (state == .loading) {
        loading.startAnimating()
    } else {
        loading.stopAnimating()
    }
    loading.isHidden = state != .loading

顺便说一句:如果您将loading.isHidden = state != .loading配置为在停止时自行隐藏,您也可以跳过UIActivityIndicatorView

init(frame: CGRect, state: FriendsButtonState = .loading) {
     // ...

    loading = UIActivityIndicatorView(activityIndicatorStyle: .gray)
    loading.center = center
    loading.hidesWhenStopped = true
    addSubview(loading)
    // ...
}

正确布置右侧导航栏按钮,您必须修改FriendsButton.updateSize:当处于州.loading时 - 至少是第一次 - 您还必须更新框架。

private func updateSize() {
    if state == .loading {
        frame.size.width = frame.size.width
        loading.center = CGPoint(x: frame.size.width/2, y: frame.size.height/2)
        loading.startAnimating()
        // do not return here
    }

    let plusSize = frame.size.height/2
    let plusYValue = (frame.size.height-plusSize)/2
    let titleSize = (title as NSString).size(attributes: [NSFontAttributeName : font])
    let totalWidth = plusYValue*5.5 + plusSize + titleSize.width
    frame.size.width = totalWidth
}

我假设左侧按钮相同,但不幸的是你的代码不能在这里编译(在调用backButton = UIBarButtonItem.backButton(nil, action: nil)时在init?方法中得到一个错误,因为{{1}上没有静态成员backButton }

现在,it works on my machine

在应用程序启动后: Just after start of the app

状态改为.friends后 After state change to .friends

State再次改回.loading State changed back again to .loading

一切都很好,没有变化等。 如果这不适合您的项目,那么您可能还有其他方面没有与您的代码一起发布。

答案 1 :(得分:3)

您应该更新x.execute(...) conn.commit() 中子视图的框架,因此您应该覆盖此方法。每当框架更改以及布局被标记为“脏”时,都会调用layoutSubviews()方法。 (通过调用layoutSubviews(),您可以实现此目的。)

答案 2 :(得分:1)

看起来你想在init中设置friendsButton的FriendsButtonState。变化:

response

friendsButton = FriendsButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24))