ios - 第一次操作按钮的错误行为

标签 ios swift uibutton

当四个按钮中的任何一个被点击时,指示器总是第一次移动到最左边按钮下方的位置。但我想看到的是指示器滑动到刚被点击的按钮正下方的位置。这四个按钮在 Storyboard中被标记为 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
    }
}

enter image description here

最佳答案

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

对于您的“指示器”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):

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)
    }
}

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

关于ios - 第一次操作按钮的错误行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51896875/

相关文章:

ios - Sqlite.swift 不适用于 Xcode 7.3

swift - 更改 SpriteKit 中的主 Sprite

ios - 从另一个 Controller 的 UIPickerView 更新 UIButton 的标题

ios - 文本不会 swift 出现在 UIButton 上

html - Bootstrap 导航栏不会在 iPhone 上折叠

ios - 如何使用 Realm 存储字符串枚举

ios - 从远程服务器调用返回并评估错误对象时崩溃

ios - 是否有可能根据操作系统的版本拥有特定版本的应用程序?

ios - Swift - 如何让文本字段在测验中识别多个正确答案?

objective-c - 将上下文添加到 UI 控件或 NSObject