【问题标题】:Incorrect beviour of button for action at the first time第一次操作按钮的错误行为
【发布时间】:2018-08-17 13:49:53
【问题描述】:

当点击四个按钮中的任何一个时,指示器总是第一次动画到最左边的按钮下方的位置。但我想看到的是,指示器会滑到刚刚被点击的按钮正下方的位置。这四个按钮在情节提要中被标记为 0、1、2、3。为什么?提前谢谢!

class MainViewController: UIViewController {

    @IBOutlet weak var weatherBtn: UIButton!
    @IBOutlet weak var tourismBtn: UIButton!
    @IBOutlet weak var tectonicsBtn: UIButton!
    @IBOutlet weak var foodBtn: UIButton!
    @IBOutlet weak var indicator: UIImageView!

    var btnsArray: [UIButton]!
    let tin = UIColor(red: 145/255, green: 145/255, blue: 145/255, alpha: 1)

    override func viewDidLoad() {
        super.viewDidLoad()
        btnsArray = [weatherBtn, tourismBtn, tectonicsBtn, foodBtn]

        indicator.image = UIImage().solidColor(.black, size: indicator.frame.size)
    }

    @IBAction func topicBtnTapped(_ sender: UIButton) {
        indicate(button: sender)
    }


    func indicate(button: UIButton) {
        UIView.animate(withDuration: 0.3) {
            self.indicator.center.x = (button.superview?.frame.minX)! + button.frame.width * 0.5 * (2 * CGFloat(button.tag) + 1)
        }

        for btn in btnsArray {
            btn.titleLabel?.textColor = tin
        }
        button.setTitleColor(.black, for: .normal)
    }
}

extension UIImage {
    func solidColor(_ color: UIColor, size: CGSize) -> UIImage {
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        color.setFill()
        UIRectFill(rect)
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }
}

【问题讨论】:

  • 如果你使用这个更好 -> cocoacontrols.com/controls/shviewpagerexample
  • @dahiya_boy 谢谢!但我正在尝试实现我现在拥有的代码。没有可可豆荚。 :)
  • 在情节提要中布局时是否使用了约束?如果是这样,您应该为约束创建IBOutlets 并更改.constant 值。将约束与显式帧值混合会产生问题。
  • @DonMag 确实如此。我现在已经解决了这个问题。谢谢!

标签: ios swift uibutton


【解决方案1】:

假设您正在使用自动布局约束...

对于您的“指示器”UIImageView,在“天气”按钮的底部设置宽度和高度限制以及垂直间距限制。

然后,将其水平居中限制在您的“天气”按钮上。

为 centerX 约束添加一个 IBOutlet:

@IBOutlet var indicatorCenterXConstraint: NSLayoutConstraint!

那么,当你想移动“指标”时:

    // deactivate indicator's current centerXAnchor
    self.indicatorCenterXConstraint.isActive = false

    // re-init to center aligned to selected button
    self.indicatorCenterXConstraint = self.indicator.centerXAnchor.constraint(equalTo: button.centerXAnchor)

    // set it active
    self.indicatorCenterXConstraint.isActive = true

    // animate it into place
    UIView.animate(withDuration: 0.3) {
        self.view.layoutIfNeeded()
    }

因此,每次点击“菜单”按钮时,都会停用当前的 centerXAnchor,将其重新初始化为所点击按钮的 centerXAnchor,重新激活它并为其设置动画。

这是完整的课程:

class MenuMainViewController: UIViewController {

    @IBOutlet weak var weatherBtn: UIButton!
    @IBOutlet weak var tourismBtn: UIButton!
    @IBOutlet weak var tectonicsBtn: UIButton!
    @IBOutlet weak var foodBtn: UIButton!
    @IBOutlet weak var indicator: UIImageView!

    // outlet to control the position of the indicator
    @IBOutlet var indicatorCenterXConstraint: NSLayoutConstraint!

    var btnsArray: [UIButton]!
    let tin = UIColor(red: 145/255, green: 145/255, blue: 145/255, alpha: 1)

    override func viewDidLoad() {
        super.viewDidLoad()
        btnsArray = [weatherBtn, tourismBtn, tectonicsBtn, foodBtn]

        indicator.image = UIImage().solidColor(.black, size: indicator.frame.size)

        // init button title colors
        for btn in btnsArray {
            btn.setTitleColor(tin, for: .normal)
        }
        // set first button to "active" color
        weatherBtn.setTitleColor(.black, for: .normal)

    }

    @IBAction func topicBtnTapped(_ sender: UIButton) {
        indicate(button: sender)
    }


    func indicate(button: UIButton) {
        // deactivate indicator's current centerXAnchor
        self.indicatorCenterXConstraint.isActive = false

        // re-init to center aligned to selected button
        self.indicatorCenterXConstraint = self.indicator.centerXAnchor.constraint(equalTo: button.centerXAnchor)

        // set it active
        self.indicatorCenterXConstraint.isActive = true

        // animate it into place
        UIView.animate(withDuration: 0.3) {
            self.view.layoutIfNeeded()
        }

        // update button title colors
        for btn in btnsArray {
            btn.setTitleColor(tin, for: .normal)
        }
        button.setTitleColor(.black, for: .normal)
    }
}

顺便说一句,您可以使用普通的UIView.backgroundColor = .black,而不是为您的“指标”imageView 创建纯色图像。

【讨论】:

  • 非常感谢!你为我说得非常清楚和详细!也感谢您的额外实施!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-30
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多