为什么角半径仅应用于自定义视图的左上角和右上角?

阿德里安

我有我的自定义视图,我将它用作加载栏。它有一个不透明度为 0.1 的底层和一个不透明度为 1 的顶层。

这是它的设置方式:

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

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

    func configure() {
        animation.delegate = self
        bottomProgressBar.strokeColor = UIColor.white.cgColor
        bottomProgressBar.opacity = 0.1
        bottomProgressBar.lineWidth = self.frame.height
        bottomProgressBar.strokeStart = 0
        bottomProgressBar.strokeEnd = 1
        self.layer.addSublayer(bottomProgressBar)

        topProgressBar.strokeColor = UIColor.white.cgColor
        topProgressBar.lineWidth = self.frame.height
        topProgressBar.strokeStart = 0
        topProgressBar.strokeEnd = 1
        self.layer.addSublayer(topProgressBar)
        animate(fromValue: 0, toValue: 0)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let path = UIBezierPath()
        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x: self.frame.width, y: 0))

        bottomProgressBar.lineWidth = self.frame.height // Update lineWidth
        topProgressBar.lineWidth = self.frame.height    // Update lineWidth

        bottomProgressBar.path = path.cgPath
        topProgressBar.path = path.cgPath

        self.clipsToBounds = true
        self.layer.cornerRadius = 4
    }

现在我也想应用一个圆角半径,所以我在底部添加了代码layoutSubviews

self.clipsToBounds = true
self.layer.cornerRadius = 4

这仅将角半径应用于左上角和右上角部分,仅此而已。我不明白为什么。

我也尝试在configure方法bottomProgressBartopProgressBar层中设置它,但根本不起作用。

有人可以指出这里的问题是什么吗?

编辑:

这是完整的类代码:

class ProgressBar: UIView {

    var bottomProgressBar = CAShapeLayer()
    var topProgressBar = CAShapeLayer()

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

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

    func configure() {
        bottomProgressBar.strokeColor = UIColor.white.cgColor
        bottomProgressBar.opacity = 0.1
        bottomProgressBar.lineWidth = self.frame.height
        bottomProgressBar.strokeStart = 0
        bottomProgressBar.strokeEnd = 1
        self.layer.addSublayer(bottomProgressBar)

        topProgressBar.strokeColor = UIColor.white.cgColor
        topProgressBar.lineWidth = self.frame.height
        topProgressBar.strokeStart = 0
        topProgressBar.strokeEnd = 1
        self.layer.addSublayer(topProgressBar)

        animate(toValue: 1)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let path = UIBezierPath()
        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x: self.frame.width, y: 0))

        bottomProgressBar.lineWidth = self.frame.height // Update lineWidth
        topProgressBar.lineWidth = self.frame.height    // Update lineWidth

        bottomProgressBar.path = path.cgPath
        topProgressBar.path = path.cgPath
    }

    func animate(toValue: Double) {
        let animation = CABasicAnimation(keyPath: "strokeEnd")

        animation.duration = 1.0
        animation.fromValue = 0
        animation.toValue = toValue

        topProgressBar.strokeEnd = CGFloat(toValue)
        topProgressBar.animation(forKey: "animate")
    }
}

编辑2:

添加了更多关于正在发生的事情的截图:

这是没有应用拐角半径 - 简单的矩形

在此处输入图片说明

这就是我应用圆角半径时发生的情况 - 下半部分被切掉(矩形显然是半切)

在此处输入图片说明

这就是我想要的 - 带有所有 4 个角的角半径的简单矩形:

在此处输入图片说明

唐麦格

编辑:澄清最终目标后,这里有一个更简单的方法。您可以直接在操场页面中运行它...

import UIKit
import PlaygroundSupport

class ProgressBar: UIView {

    var progressView: UIView = {
        let v = UIView()
        v.backgroundColor = .white
        return v
    }()

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

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

    func configure() {
        backgroundColor = UIColor(white: 1.0, alpha: 0.1)
        layer.cornerRadius = 8.0
        clipsToBounds = true

        progressView.frame = bounds
        progressView.frame.size.width = 0.0
        addSubview(progressView)
    }

    func animate(_ pct: CGFloat) -> Void {
        UIView.animate(withDuration: 1.0, animations: {
            self.progressView.frame.size.width = self.bounds.size.width * pct
        })
    }

}

class MyViewController : UIViewController {

    var theButton: UIButton = {
        let b = UIButton()
        b.setTitle("Tap Me", for: .normal)
        b.translatesAutoresizingMaskIntoConstraints = false
        b.backgroundColor = .red
        return b
    }()

    var myProgressBar = ProgressBar(frame: CGRect(x: 40, y: 300, width: 300, height: 30))

    // on button tap, set the progress bar to 80%
    @objc func didTap(_ sender: Any?) -> Void {
        myProgressBar.animate(0.8)
    }

    override func loadView() {
        let view = UIView()
        self.view = view
        view.backgroundColor = UIColor.purple

        view.addSubview(theButton)
        // constrain button to Top: 32 and centerX
        NSLayoutConstraint.activate([
            theButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 32.0),
            theButton.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0.0),
            ])

        // add an action for the button tap
        theButton.addTarget(self, action: #selector(didTap(_:)), for: .touchUpInside)

        view.addSubview(myProgressBar)

    }

}

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

点击按钮将使“进度条”从零到 80% 动画

结果:

在此处输入图片说明


原答案:

首先:您要添加一条从...开始的“线”,并且您将 lineWidth0,0设为width,0视图的高度。

这给你这个结果:

在此处输入图片说明

黄色矩形是您的视图,白色矩形是您的“线”。正如你看到的,中心的线沿运行的视图,使该行的上半部分居然是外面的视图的框架。因此,当您圆化视图的角时,看起来好像只有顶角被圆化了。如果您为视图设置背景颜色,您将看到底角也被圆角,但那里没有“线”。

如果这是您真正想要的(顶部栏为白色,底部栏为绿色):

在此处输入图片说明

您想将线宽设置为视图高度的 1/2,并将线中心设置为 1/4 和 3/4:

class ProgressBar: UIView {

    var bottomProgressBar = CAShapeLayer()
    var topProgressBar = CAShapeLayer()

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

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

    func configure() {
        bottomProgressBar.strokeColor = UIColor.green.cgColor
        bottomProgressBar.opacity = 1
        bottomProgressBar.lineWidth = self.frame.height
        bottomProgressBar.strokeStart = 0
        bottomProgressBar.strokeEnd = 1
        self.layer.addSublayer(bottomProgressBar)

        topProgressBar.strokeColor = UIColor.white.cgColor
        topProgressBar.lineWidth = self.frame.height
        topProgressBar.strokeStart = 0
        topProgressBar.strokeEnd = 1
        self.layer.addSublayer(topProgressBar)

        //      animate(toValue: 1)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        var path = UIBezierPath()
        path.move(to: CGPoint(x: 0, y: self.frame.height * 0.25))
        path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height * 0.25))

        topProgressBar.path = path.cgPath

        path = UIBezierPath()
        path.move(to: CGPoint(x: 0, y: self.frame.height * 0.75))
        path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height * 0.75))

        bottomProgressBar.path = path.cgPath

        bottomProgressBar.lineWidth = self.frame.height / 2.0 // Update lineWidth
        topProgressBar.lineWidth = self.frame.height / 2.0    // Update lineWidth

        self.clipsToBounds = true
        self.layer.cornerRadius = 8

    }

    func animate(toValue: Double) {
        let animation = CABasicAnimation(keyPath: "strokeEnd")

        animation.duration = 3.0
        animation.fromValue = 0
        animation.toValue = toValue

        topProgressBar.strokeEnd = CGFloat(toValue)
        topProgressBar.animation(forKey: "animate")
    }
}

当然,如果你想要的只是一个带圆角的矩形,那么你不需要任何一个子层......只需创建一个白色背景的视图,并设置其层的角半径......

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

角半径仅适用于视图的左上角和左下角

自定义视图仅显示在左上角

如何只为UIView的左上角和右上角设置cornerRadius?

如何在右上角显示时间和日期,同时在左上角显示温度?

动画 UIBezierPath 从所有圆角到左上角和右上角圆角的路径

Sylius:如何自定义右上角的用户菜单?

在Android中使用Path和RectF在左上角,右上角,左下角,右下角绘制圆角

如何获得具有左上角和右下角坐标的右上角框?

为什么我的画布仅加载左上角的图像?

下拉菜单显示在右上角,单击时显示在左上角

如何从右上角而不是左上角启动CustomClipper(ClipPath)

如何将打开的活动概览从左上角移动到右上角?

如何在Android的左上角和右下角创建角半径?

左上角的ConstraintLayout视图

如何创建仅具有左上角和左下角半径的圆形UIButton

当背景色与边框背景色不同时,为WPF TextBlock设置左上角和右上角圆角不起作用

为什么我的视图的右上角有一个“加号”图标?

检查自定义工具提示的左上角是否在范围内

使用Tkinter移动自定义标题栏窗口,而无需从左上角移动

为什么Java 2D起源在左上角?

为什么NavigationView中的动画从左上角开始?

为什么图像的左上角有水印?

为什么说在函数pygame中未定义左上角?

在页面左上角快速打印视图

如何将SVG clipPath应用于不在Webkit浏览器中文档左上角的HTML元素

当我单击自定义页面右上角的“完成”按钮或关闭按钮时,页面未使用 NSIS 关闭

圆形左上/右上角CardView Android不起作用

如何修复图像在顶部的边框右上角半径

Firefox忽略了表格单元的边框左上角半径