Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Swift:按钮的圆角打破了禁忌_Ios_Swift_Autolayout_Rounded Corners - Fatal编程技术网

Ios Swift:按钮的圆角打破了禁忌

Ios Swift:按钮的圆角打破了禁忌,ios,swift,autolayout,rounded-corners,Ios,Swift,Autolayout,Rounded Corners,我有一个通过xib加载自定义单元格的tableview,在该单元格中我有一个状态按钮,右下角应该是圆角。该按钮具有尾随/前导/底部空间到superview=0和高度=30的约束 如果不四舍五入,它就可以完美地工作,例如,只要我转过一个角(右下角),约束就会中断 self.btnStatus.roundCorners(corners: [.bottomRight], radius: 7.0, borderWidth: nil, borderColor: nil) 这里有些人建议调用layou

我有一个通过xib加载自定义单元格的tableview,在该单元格中我有一个状态按钮,右下角应该是圆角。该按钮具有尾随/前导/底部空间到superview=0和高度=30的约束

如果不四舍五入,它就可以完美地工作,例如,只要我转过一个角(右下角),约束就会中断

self.btnStatus.roundCorners(corners: [.bottomRight], radius: 7.0, borderWidth: nil, borderColor: nil)

这里有些人建议调用layoutSubviews(),但这对我没有帮助

更具体地说,我创建了一个简单的项目,您可以在其中查看整个项目

正确链接


您的按钮可能重叠,因为它没有上限约束?尝试添加明亮的边框,看看是否可以看到顶部,如果看不到,请尝试向顶部添加约束。另外,与其给它一个静态高度,不如试着使它与上面的物体成比例的高度(可能是设备的屏幕大小导致它重叠)

可能你的按钮重叠了,因为它没有上限约束?尝试添加明亮的边框,看看是否可以看到顶部,如果看不到,请尝试向顶部添加约束。另外,与其给它一个静态高度,不如试着使它与上面的物体成比例的高度(可能是设备的屏幕大小导致它重叠)

我看了你的代码。问题是,
roundCorners
函数取决于视图的边界来设置图层的属性,并且您正在
awakeFromNib
中调用
roundCorners
,此时您的单元格与NIB文件中的边界相同,因为尚未计算自动布局。您需要将
roundCorners
调用移动到中,以便在自动布局完成边界计算后调用它

import UIKit

class CustomTableViewCell: UITableViewCell {

    @IBOutlet weak var btnStatus: UIButton!    
    override func layoutSubviews() {
        super.layoutSubviews()
                self.btnStatus.roundCorners(corners: [.bottomRight], radius: 7.0, borderWidth: nil, borderColor: nil)
    }
}

编辑并将cell.setNeedsLayout()添加到cellforRowAt,以强制在第一次绘制单元格之前调用布局子视图。

我查看了您的代码。问题是,
roundCorners
函数取决于视图的边界来设置图层的属性,并且您正在
awakeFromNib
中调用
roundCorners
,此时您的单元格与NIB文件中的边界相同,因为尚未计算自动布局。您需要将
roundCorners
调用移动到中,以便在自动布局完成边界计算后调用它

import UIKit

class CustomTableViewCell: UITableViewCell {

    @IBOutlet weak var btnStatus: UIButton!    
    override func layoutSubviews() {
        super.layoutSubviews()
                self.btnStatus.roundCorners(corners: [.bottomRight], radius: 7.0, borderWidth: nil, borderColor: nil)
    }
}

编辑并将cell.setNeedsLayout()添加到cellforRowAt,以强制在第一次绘制单元格之前调用LayoutSubview。

通过对按钮进行子类化,并通过覆盖其
LayoutSubview()
函数放置“舍入”代码,可以获得更可靠的结果

首先,如果你想添加一个边框,你不想添加多个“边框子层”。。。因此,将您的
ui视图
扩展名更改为:

extension UIView {
    func roundCorners(corners: UIRectCorner, radius: CGFloat, borderWidth: CGFloat?, borderColor: UIColor?) {
        let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let maskLayer = CAShapeLayer()
        maskLayer.frame = self.bounds
        maskLayer.path = maskPath.cgPath

        self.layer.mask = maskLayer
        self.layer.masksToBounds = true

        if (borderWidth != nil && borderColor != nil) {

            // remove previously added border layer
            for layer in layer.sublayers! {
                if layer.name == "borderLayer" {
                    layer.removeFromSuperlayer()
                }
            }

            let borderLayer = CAShapeLayer()

            borderLayer.frame = self.bounds;
            borderLayer.path  = maskPath.cgPath;
            borderLayer.lineWidth = borderWidth ?? 0;
            borderLayer.strokeColor = borderColor?.cgColor;
            borderLayer.fillColor   = UIColor.clear.cgColor;
            borderLayer.name = "borderLayer"

            self.layer.addSublayer(borderLayer);

        }

    }
}
接下来,添加一个
UIButton
子类:

class RoundedButton: UIButton {

    var corners: UIRectCorner?
    var radius = CGFloat(0.0)
    var borderWidth = CGFloat(0.0)
    var borderColor: UIColor?

    override func layoutSubviews() {

        super.layoutSubviews()

        // don't apply mask if corners is not set, or if radius is Zero
        guard let _corners = corners, radius > 0.0 else {
            return
        }

        roundCorners(corners: _corners, radius: radius, borderWidth: borderWidth, borderColor: borderColor)

    }

}
这给您带来了几个好处:1)当按钮框发生变化时(例如,旋转设备),它将更新其遮罩层框;2)您可以从自定义单元格类或cellForRowAt设置这些值

无论采用哪种方式,都可以在故事板和
@IBOutlet
连接中将
btnStatus
类从
UIButton
更改为
RoundedButton

然后将
CustomTableViewCell
更改为:

class CustomTableViewCell: UITableViewCell {

    @IBOutlet weak var btnStatus: RoundedButton!

    override func awakeFromNib() {
        super.awakeFromNib()

        // set up corner maskign
        btnStatus.corners = .bottomRight
        btnStatus.radius = 7.0

        // set if desired
//      btnStatus.borderWidth = 2.0
//      btnStatus.borderColor = .blue

    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        // Configure the view for the selected state
    }

}
最后,您的
cellForRowAt
函数变为:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomTableViewCell
    return cell
}

这应该可以做到…

通过对按钮进行子类化,并通过覆盖其
layoutSubviews()
函数放置“舍入”代码,可以获得更可靠的结果

首先,如果你想添加一个边框,你不想添加多个“边框子层”。。。因此,将您的
ui视图
扩展名更改为:

extension UIView {
    func roundCorners(corners: UIRectCorner, radius: CGFloat, borderWidth: CGFloat?, borderColor: UIColor?) {
        let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let maskLayer = CAShapeLayer()
        maskLayer.frame = self.bounds
        maskLayer.path = maskPath.cgPath

        self.layer.mask = maskLayer
        self.layer.masksToBounds = true

        if (borderWidth != nil && borderColor != nil) {

            // remove previously added border layer
            for layer in layer.sublayers! {
                if layer.name == "borderLayer" {
                    layer.removeFromSuperlayer()
                }
            }

            let borderLayer = CAShapeLayer()

            borderLayer.frame = self.bounds;
            borderLayer.path  = maskPath.cgPath;
            borderLayer.lineWidth = borderWidth ?? 0;
            borderLayer.strokeColor = borderColor?.cgColor;
            borderLayer.fillColor   = UIColor.clear.cgColor;
            borderLayer.name = "borderLayer"

            self.layer.addSublayer(borderLayer);

        }

    }
}
接下来,添加一个
UIButton
子类:

class RoundedButton: UIButton {

    var corners: UIRectCorner?
    var radius = CGFloat(0.0)
    var borderWidth = CGFloat(0.0)
    var borderColor: UIColor?

    override func layoutSubviews() {

        super.layoutSubviews()

        // don't apply mask if corners is not set, or if radius is Zero
        guard let _corners = corners, radius > 0.0 else {
            return
        }

        roundCorners(corners: _corners, radius: radius, borderWidth: borderWidth, borderColor: borderColor)

    }

}
这给您带来了几个好处:1)当按钮框发生变化时(例如,旋转设备),它将更新其遮罩层框;2)您可以从自定义单元格类或cellForRowAt设置这些值

无论采用哪种方式,都可以在故事板和
@IBOutlet
连接中将
btnStatus
类从
UIButton
更改为
RoundedButton

然后将
CustomTableViewCell
更改为:

class CustomTableViewCell: UITableViewCell {

    @IBOutlet weak var btnStatus: RoundedButton!

    override func awakeFromNib() {
        super.awakeFromNib()

        // set up corner maskign
        btnStatus.corners = .bottomRight
        btnStatus.radius = 7.0

        // set if desired
//      btnStatus.borderWidth = 2.0
//      btnStatus.borderColor = .blue

    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        // Configure the view for the selected state
    }

}
最后,您的
cellForRowAt
函数变为:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomTableViewCell
    return cell
}


应该这样做了…

关于打破约束给出了哪些错误?如果代码打破了约束,只需将其放在
UIView
中,并为该容器
UIView
提供约束即可。约束不会关心视图中有什么,圆角与否。@benjiiiii:完全没有错误,只是按钮没有对齐…@mihatel-您的“dropbox”链接错误。。。你必须选择“共享”,然后创建一个链接。@mihatel-看看我的答案。我想你会发现这是一种更可靠的方法。关于破坏约束给出了哪些错误?如果代码破坏了约束,只需将其放在
UIView
中,并给容器
UIView
约束即可。约束不会关心视图中有什么,圆角与否。@benjiiiii:完全没有错误,只是按钮没有对齐…@mihatel-您的“dropbox”链接错误。。。你必须选择“共享”,然后创建一个链接。@mihatel-看看我的答案。我想你会发现这是一个更可靠的方法。它没有帮助它没有帮助同样的问题:(我正在运行它,它正在工作。你是否正确地移动了代码?是的,哪个模拟器,我正在检查iphone7,iOS11,如果你能上传zip,我会很好地运行它,并在iphone7 iOS11上比较它是否正确。查看整个文件的编辑答案。在真实设备上也是一样的,事实上,如果我滚动它解决了问题,但只有在cell rendere上同样的问题:(我在运行它,我