关于swift:在iOS11中旋转设备时UIToolbar的左右间距

UIToolbar left and right spacing when rotating device in IOS11

自iOS11起,我在UIToolbar的填充方面遇到了一个奇怪的问题。旋转设备时,工具栏的左右填充变大(下面的示例)。

旋转之前设备是否处于纵向或横向模式都没有关系。额外的间距仅在旋转后出现。我认为这是自动调整大小的问题。

旋转之前查看调试器(正确的间距):
https://www.dropbox.com/s/1wigv1et88t1mvn/Schermafdruk 2018-01-31 15.51.05.png?dl = 0

旋转后查看调试器(间距错误):
https://www.dropbox.com/s/9gnqi6hzv5czcnw/Schermafdruk 2018-01-31 20.59.48.png?dl = 0

示例:

https://www.dropbox.com/s/s7jbmbsuorump5e/spacing-toolbar.gif?dl=0

我正在使用工具栏类在工具栏内创建按钮。
在xcode界面中,选中了\\'Autoresize Subview \\'选项。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
class ToolbarClass: UIToolbar {

    //Set height of toolbar
    override func sizeThatFits(_ size: CGSize) -> CGSize {
        var size = super.sizeThatFits(size)
        size.height = 60
        return size
    }

    //Toolbar settings
    override func layoutSubviews() {
        super.layoutSubviews()

        //Default
        self.barStyle = UIBarStyle.default
        self.sizeToFit()

        //Buttons ios11+

        //Space
        let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let spaceBetween:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
        spaceBetween.width = 1.0

        let nameSpace:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
        nameSpace.width = 10

        //Logo
        let logoImage = UIImage(named:"MBS-Logo")
        let logoImageView = UIImageView(image: logoImage)
        logoImageView.frame = CGRect(x: -46, y: 0, width: 48, height: 54)
        logoImageView.contentMode = .scaleAspectFit
        let logoView = UIView(frame: CGRect(x: 0, y: 0, width: 48, height: 54))
        logoView.clipsToBounds = false
        logoView.layer.cornerRadius = logoView.frame.width / 2
        logoView.addSubview(logoImageView)
        let logoImg = UIBarButtonItem(customView: logoView)
        logoImg.customView = logoView

        //Profile
        let profileImage = UIImage(named:"No-Profile")
        let profileImageView = UIImageView(image: profileImage)
        profileImageView.frame = CGRect(x: 40, y: 0, width: 50, height: 50)
        profileImageView.contentMode = .scaleAspectFit
        profileImageView.clipsToBounds = true
        profileImageView.layer.cornerRadius = profileImageView.frame.width / 2
        let profileView = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
        profileView.clipsToBounds = false
        profileView.addSubview(profileImageView)
        let profileImg = UIBarButtonItem(customView: profileView)
        profileImg.customView = profileView

        //NameLabel
        let nameLbl = UILabel()
        nameLbl.frame = CGRect(x: 0, y: 0, width: 200, height: 60)
        nameLbl.text ="Hi"
        nameLbl.font = UIFont(name:"Roboto", size: 22)
        nameLbl.textColor = UIColor.white
        let nameLabel = UIBarButtonItem()
        nameLabel.customView = nameLbl

        //Settings
        let settingsBtn = UIButton()
        settingsBtn.frame = CGRect(x: 0, y: 0, width: 64, height: 60)
        settingsBtn.setImage(UIImage(named:"Settings-Bar")?.withRenderingMode(.alwaysOriginal), for: .normal)
        settingsBtn.addTarget(self, action: #selector(self.settingsPressed), for: .touchUpInside)
        let settingsButton = UIBarButtonItem()
        settingsButton.customView = settingsBtn

        //Classes
        let classesBtn = UIButton()
        classesBtn.frame = CGRect(x: 0, y: 0, width: 64, height: 60)
        classesBtn.setImage(UIImage(named:"Classes-Bar")?.withRenderingMode(.alwaysOriginal), for: .normal)
        classesBtn.addTarget(self, action: #selector(self.classesPressed), for: .touchUpInside)
        let classesButton = UIBarButtonItem()
        classesButton.customView = classesBtn

        //Set buttons
        self.setItems([profileImg, logoImg, nameSpace, nameLabel, spaceButton, classesButton, spaceBetween, settingsButton], animated: false)

    }

}

enter


首先layoutSubviews并不是添加所有项目的正确位置。例如,每次调用设备方向layoutSubviews时,将再次创建所有项目。使用init?(coder:)init(frame:)

将代码移动到init?(coder:)init(frame:)后,您将看到左右边距(当前仅在定向时出现)。这是UIToolBar的实际行为,它会自动在两侧增加边距。

要删除该边距,只需在工具栏项目的开始和结束处添加固定大小的负分隔符即可。

1
2
let negativeFizedSpace = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
negativeFizedSpace.width = -20 // Spacing 20 for iPad and 16 for iPhone
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
class ToolbarClass: UIToolbar {

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    private func commonInit() {

        //Space
        let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let spaceBetween:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
        spaceBetween.width = 1.0

        let nameSpace:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
        nameSpace.width = 10

        //Logo
        let logoImage = UIImage(named:"MBS-Logo")
        let logoImageView = UIImageView(image: logoImage)
        logoImageView.frame = CGRect(x: -46, y: 0, width: 48, height: 54)
        logoImageView.contentMode = .scaleAspectFit
        let logoView = UIView(frame: CGRect(x: 0, y: 0, width: 48, height: 54))
        logoView.clipsToBounds = false
        logoView.layer.cornerRadius = logoView.frame.width / 2
        logoView.addSubview(logoImageView)
        let logoImg = UIBarButtonItem(customView: logoView)
        logoImg.customView = logoView

        //Profile
        let profileImage = UIImage(named:"No-Profile")
        let profileImageView = UIImageView(image: profileImage)
        profileImageView.frame = CGRect(x: 40, y: 0, width: 50, height: 50)
        profileImageView.contentMode = .scaleAspectFit
        profileImageView.clipsToBounds = true
        profileImageView.layer.cornerRadius = profileImageView.frame.width / 2
        let profileView = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
        profileView.clipsToBounds = false
        profileView.addSubview(profileImageView)
        let profileImg = UIBarButtonItem(customView: profileView)
        profileImg.customView = profileView

        //NameLabel
        let nameLbl = UILabel()
        nameLbl.frame = CGRect(x: 0, y: 0, width: 200, height: 60)
        nameLbl.text ="Hi"
        nameLbl.font = UIFont(name:"Roboto", size: 22)
        nameLbl.textColor = UIColor.white
        let nameLabel = UIBarButtonItem()
        nameLabel.customView = nameLbl

        //Settings
        let settingsBtn = UIButton()
        settingsBtn.frame = CGRect(x: 0, y: 0, width: 64, height: 60)
        settingsBtn.setImage(UIImage(named:"Settings-Bar")?.withRenderingMode(.alwaysOriginal), for: .normal)
        settingsBtn.addTarget(self, action: #selector(self.settingsPressed), for: .touchUpInside)
        let settingsButton = UIBarButtonItem()
        settingsButton.customView = settingsBtn

        //Classes
        let classesBtn = UIButton()
        classesBtn.frame = CGRect(x: 0, y: 0, width: 64, height: 60)
        classesBtn.setImage(UIImage(named:"Classes-Bar")?.withRenderingMode(.alwaysOriginal), for: .normal)
        classesBtn.addTarget(self, action: #selector(self.classesPressed), for: .touchUpInside)
        let classesButton = UIBarButtonItem()
        classesButton.customView = classesBtn


        let negativeFizedSpace = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
        negativeFizedSpace.width = -20 // Spacing 20 for iPad and 16 for iPhone

        //Set buttons
        self.setItems([negativeFizedSpace, profileImg, logoImg, nameSpace, nameLabel, spaceButton, classesButton, spaceBetween, settingsButton, negativeFizedSpace], animated: false)
    }

    //Set height of toolbar
    override func sizeThatFits(_ size: CGSize) -> CGSize {
        var size = super.sizeThatFits(size)
        size.height = 60
        return size
    }        
}

更新

如果使用导航控制器工具栏。替代方法是创建一个UIViewController扩展名,以添加通用工具栏项,并在ViewController的viewDidLoad方法中调用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        addGeneralToolbarItems()
    }
}

class ToolbarClass: UIToolbar {
    //Set height of toolbar
    override func sizeThatFits(_ size: CGSize) -> CGSize {
        var size = super.sizeThatFits(size)
        size.height = 60
        return size
    }
}

extension UIViewController {
    func addGeneralToolbarItems()  {
        //Space
        let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let spaceBetween:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
        spaceBetween.width = 1.0

        let nameSpace:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
        nameSpace.width = 10

        //Logo
        let logoImage = UIImage(named:"MBS-Logo")
        let logoImageView = UIImageView(image: logoImage)
        logoImageView.frame = CGRect(x: -46, y: 0, width: 48, height: 54)
        logoImageView.contentMode = .scaleAspectFit
        let logoView = UIView(frame: CGRect(x: 0, y: 0, width: 48, height: 54))
        logoView.clipsToBounds = false
        logoView.layer.cornerRadius = logoView.frame.width / 2
        logoView.addSubview(logoImageView)
        let logoImg = UIBarButtonItem(customView: logoView)
        logoImg.customView = logoView

        //Profile
        let profileImage = UIImage(named:"No-Profile")
        let profileImageView = UIImageView(image: profileImage)
        profileImageView.frame = CGRect(x: 40, y: 0, width: 50, height: 50)
        profileImageView.contentMode = .scaleAspectFit
        profileImageView.clipsToBounds = true
        profileImageView.layer.cornerRadius = profileImageView.frame.width / 2
        let profileView = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
        profileView.clipsToBounds = false
        profileView.addSubview(profileImageView)
        let profileImg = UIBarButtonItem(customView: profileView)
        profileImg.customView = profileView

        //NameLabel
        let nameLbl = UILabel()
        nameLbl.frame = CGRect(x: 0, y: 0, width: 200, height: 60)
        nameLbl.text ="Hi"
        nameLbl.font = UIFont(name:"Roboto", size: 22)
        nameLbl.textColor = UIColor.white
        let nameLabel = UIBarButtonItem()
        nameLabel.customView = nameLbl

        //Settings
        let settingsBtn = UIButton()
        settingsBtn.frame = CGRect(x: 0, y: 0, width: 64, height: 60)
        settingsBtn.setImage(UIImage(named:"Settings-Bar")?.withRenderingMode(.alwaysOriginal), for: .normal)
        settingsBtn.addTarget(self, action: #selector(self.settingsPressed), for: .touchUpInside)
        let settingsButton = UIBarButtonItem()
        settingsButton.customView = settingsBtn

        //Classes
        let classesBtn = UIButton()
        classesBtn.frame = CGRect(x: 0, y: 0, width: 64, height: 60)
        classesBtn.setImage(UIImage(named:"Classes-Bar")?.withRenderingMode(.alwaysOriginal), for: .normal)
        classesBtn.addTarget(self, action: #selector(self.classesPressed), for: .touchUpInside)
        let classesButton = UIBarButtonItem()
        classesButton.customView = classesBtn


        let negativeFizedSpace = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
        negativeFizedSpace.width = -20 // Spacing 20 for iPad and 16 for iPhone

        //Set buttons
        self.setToolbarItems([negativeFizedSpace, profileImg, logoImg, nameSpace, nameLabel, spaceButton, classesButton, spaceBetween, settingsButton, negativeFizedSpace], animated: false)

    }

    @objc func settingsPressed() {

    }

    @objc func classesPressed() {

    }
}