UISlider 的自定义形状并在 Swift 5 中更新进度

     2023-03-13     306

关键词:

【中文标题】UISlider 的自定义形状并在 Swift 5 中更新进度【英文标题】:Custom shape to UISlider and update progress in Swift 5 【发布时间】:2021-02-13 15:27:10 【问题描述】:

我已经检查了一些关于自定义 UIView 滑块的 *** 答案,但使用它们我无法制作这样的滑块。这会形成一个圆圈或半个圆圈。我想出了一些使用 UIView 制作圆形滑块的库,但它对我没有帮助,所以任何人都可以帮助我。如何制作 UIImage 下面的滑块?谢谢!

【问题讨论】:

【参考方案1】:

您可能会自己动手。 (您显然可以搜索第三方实现,但这超出了 *** 的范围。)有很多方法可以解决这个问题,但这里的基本元素是:

    整个路径的粉红色弧线。就个人而言,我会为此使用CAShapeLayer。 从开始到当前进度的白色弧线(从 0 到 1 测量)。同样,CAShapeLayer 是合乎逻辑的。 当前进度处的白点。下面我创建了一个带有白色背景的CALayer,然后将CAGradientLayer 作为一个蒙版应用到它上面。您也可以为此创建一个UIImage。 关于如何设置进度,你可以将粉色和白色弧线的路径设置为相同的路径,但只需更新白色弧线的strokeEnd。您还可以相应地调整白点图层的位置。 这里唯一复杂的事情是找出弧的中心。在下面的示例中,我使用基于视图边界的一些三角函数来计算它,以便弧从左下角到顶部,然后从右下角返回。或者,您也可以将圆弧的中心作为参数传递。

无论如何,它可能看起来像:

@IBDesignable
class ArcView: UIView 
    @IBInspectable
    var lineWidth: CGFloat = 7  didSet  updatePaths()  

    @IBInspectable
    var progress: CGFloat = 0  didSet  updatePaths()  

    override func prepareForInterfaceBuilder() 
        super.prepareForInterfaceBuilder()

        progress = 0.35
    

    lazy var currentPositionDotLayer: CALayer = 
        let layer = CALayer()
        layer.backgroundColor = UIColor.white.cgColor
        let rect = CGRect(x: 0, y: 0, width: lineWidth * 3, height: lineWidth * 3)
        layer.frame = rect

        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [UIColor.white.cgColor, UIColor.clear.cgColor]
        gradientLayer.type = .radial
        gradientLayer.frame = rect
        gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5)
        gradientLayer.endPoint = CGPoint(x: 1, y: 1)
        gradientLayer.locations = [0.5, 1]

        layer.mask = gradientLayer

        return layer
    ()

    lazy var progressShapeLayer: CAShapeLayer = 
        let shapeLayer = CAShapeLayer()
        shapeLayer.lineCap = .round
        shapeLayer.lineWidth = lineWidth
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
        return shapeLayer
    ()

    lazy var totalShapeLayer: CAShapeLayer = 
        let shapeLayer = CAShapeLayer()
        shapeLayer.lineCap = .round
        shapeLayer.lineWidth = lineWidth
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = #colorLiteral(red: 0.9439327121, green: 0.5454334617, blue: 0.6426400542, alpha: 1)
        return shapeLayer
    ()

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

    required init?(coder: NSCoder) 
        super.init(coder: coder)
        configure()
    

    override func layoutSubviews() 
        super.layoutSubviews()
        updatePaths()
    


// MARK: - Private utility methods

private extension ArcView 

    func configure() 
        layer.addSublayer(totalShapeLayer)
        layer.addSublayer(progressShapeLayer)
        layer.addSublayer(currentPositionDotLayer)
    

    func updatePaths() 
        let rect = bounds.insetBy(dx: lineWidth / 2, dy: lineWidth / 2)
        let halfWidth = rect.width / 2
        let height = rect.height
        let theta = atan(halfWidth / height)
        let radius = sqrt(halfWidth * halfWidth + height * height) / 2 / cos(theta)
        let center = CGPoint(x: rect.midX, y: rect.minY + radius)
        let delta = (.pi / 2 - theta) * 2
        let startAngle = .pi * 3 / 2 - delta
        let endAngle = .pi * 3 / 2 + delta

        let path = UIBezierPath(arcCenter: center,
                                radius: radius,
                                startAngle: startAngle,
                                endAngle: endAngle,
                                clockwise: true)

        progressShapeLayer.path = path.cgPath // white arc
        totalShapeLayer.path = path.cgPath    // pink arc
        progressShapeLayer.strokeEnd = progress

        let currentAngle = (endAngle - startAngle) * progress + startAngle
        let dotCenter = CGPoint(x: center.x + radius * cos(currentAngle),
                                y: center.y + radius * sin(currentAngle))
        currentPositionDotLayer.position = dotCenter
    

上面,我设置了ArcView的背景颜色,这样你就可以看到它的bounds,但是你显然会把背景颜色设置为透明的。

现在您可能会添加大量附加功能(例如,添加用户交互以便您“擦洗”它等)。例如,请参阅https://github.com/robertmryan/ArcView。但设计这类东西的关键是把它分解成它的组成元素,一个在另一个之上。


您可以以编程方式设置arcViewprogress 以使其在值0 和1 之间更改当前值:

func startUpdating() 
    arcView.progress = 0

    var current = 0

    Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true)  [weak self] timer in
        current += 1

        guard let self = self, current <= 10 else 
            timer.invalidate()
            return
        

        self.arcView.progress = CGFloat(current) / 10
    

导致:

【讨论】:

您好@Rob,非常感谢您抽出宝贵时间。我将此代码添加到我的项目中,一切正常,但面临一个问题,进度 = 0.35,但它显示为 0。如果我在情节提要中更改此进度值,那么它不能以编程方式工作,它不起作用? 我检查了 prepareForInterfaceBuilder 这个方法没有调用。 你好@Rob,我在移动进度方面遇到了一些问题,你能帮我解决这个问题吗?我尝试使用 UIView Touch 操作,但总是得到 CALayer 并混淆是否需要添加位置或什么?并尝试 CATransaction 但不工作。如果你能帮我解决这个问题,我会更新这个问题。谢谢! 关于不更新的问题,我不知道为什么它不会为您更新。请参阅此示例,如上图所示:github.com/robertmryan/ArcView @YogeshPatel - 重新接触,我刚刚推送了提交,展示了该模式的示例。

使用 UIEdgedInset 的自定义 UISlider 渲染效果不佳

】使用UIEdgedInset的自定义UISlider渲染效果不佳【英文标题】:CustomUISliderusingUIEdgedInsetdoesnotrenderwell【发布时间】:2017-03-3111:52:29【问题描述】:我正在尝试使用图像进行自定义uislider(没有可见旋钮,当用户无法编辑时将其隐藏... 查看详情

以编程方式创建形状视图并在集合视图单元格上使用

...图单元格中使用三角形自定义视图,它不起作用。这是我的自定义视图 查看详情

iPhone 的自定义 UISlider

】iPhone的自定义UISlider【英文标题】:customUISliderforiPhone【发布时间】:2012-11-0215:22:17【问题描述】:我正在为iPad开发一个应用程序,它需要在UISlider中选择特定的数据间隔。滑块应该有两个滑块按钮,控件也应该允许间隔移动... 查看详情

没有图像的自定义 UISlider

】没有图像的自定义UISlider【英文标题】:CustomUISliderwithoutimage【发布时间】:2014-04-0215:02:04【问题描述】:我正在尝试在iOS7中调整UISliderthumb的大小,但我做不到。我知道可以使用setThumbImage,但我不想使用任何图像。setThumbImage:... 查看详情

具有居中 UISlider 和两个图像的自定义 UITableViewCell

】具有居中UISlider和两个图像的自定义UITableViewCell【英文标题】:CustomUITableViewCellwithcenteredUISliderandtwoimages【发布时间】:2011-07-3104:25:52【问题描述】:我想以编程方式创建一个自定义UITableViewCell,其中一个UISlider在中心,两个图... 查看详情

Swift:如何在动态 UITableView 的自定义单元格中获取滑块的值?

...态单元格的UITableView。其中,我使用自定义UITableViewCell和UISlider。如何获取滑块的值? 查看详情

在 Swift 中自动移动 UISlider

】在Swift中自动移动UISlider【英文标题】:MoveUISliderautomaticallyinSwift【发布时间】:2016-12-2811:46:21【问题描述】:我想在你点击按钮时将UISlider从minValue循环移动到maxValue并在再次点击按钮时将其停止在当前位置,我想使用Swift。我... 查看详情

给 UISlider 进度条圆角 [Swift]

】给UISlider进度条圆角[Swift]【英文标题】:GiveUISliderprogressbarroundedcorners[Swift]【发布时间】:2020-07-0416:32:44【问题描述】:我想知道是否有人知道如何自定义UISlider以使进度条圆角(没有拇指图像),如下图所示:我想要什么:... 查看详情

斯威夫特:UISlider轨道的一侧不圆

】斯威夫特:UISlider轨道的一侧不圆【英文标题】:Swift:UISlideronesideoftracknotrounded【发布时间】:2020-01-2812:21:09【问题描述】:我有一个自定义UISlider,但是滑块的一侧不是圆角这是我的自定义视图:classPrimarySliderView:UISlideroverride... 查看详情

我可以使用 messageKIt 在 swift 5 ios 中创建像这样的自定义单元格吗?

】我可以使用messageKIt在swift5ios中创建像这样的自定义单元格吗?【英文标题】:CanIcreatecustomcellsliketheseinswift5iosusingmessageKIt?【发布时间】:2021-03-2213:45:10【问题描述】:我正在构建一个聊天应用程序并且我是ios新手,我想使用me... 查看详情

在 Swift 中的自定义单元格中存储/检索核心数据

】在Swift中的自定义单元格中存储/检索核心数据【英文标题】:Storing/RetrievingCoreDatainCustomCellinSwift【发布时间】:2015-02-2202:18:04【问题描述】:我正在编写的iOS应用程序将日期保存到CoreData,然后计算TimeBetweenToday和TableView中显示... 查看详情

带有标签和 UISlider 的自定义 UITableViewCell 在 ios 7 的 6 次崩溃中运行良好。 ?? UITableViewCellScrollView?

】带有标签和UISlider的自定义UITableViewCell在ios7的6次崩溃中运行良好。??UITableViewCellScrollView?【英文标题】:customUITableViewCellwithlabelandUISliderworkedfinein6crashesinios7.??UITableViewCellScrollView?【发布时间】:2013-10-0114:08:14【问题描述】:我... 查看详情

如何为自定义 UIControl 添加触摸事件并在 swift 5 中确定触摸的项目

】如何为自定义UIControl添加触摸事件并在swift5中确定触摸的项目【英文标题】:HowtoaddtoucheventforcustomUIControlanddeterminethetouchediteminswift5【发布时间】:2019-08-2119:15:18【问题描述】:我创建了一个自定义UIControl。UIControl包含多个项... 查看详情

如何将 UISlider 设置为只有一个轨道图像,而不是在 Swift 中使用最小轨道图像和最大轨道图像?

】如何将UISlider设置为只有一个轨道图像,而不是在Swift中使用最小轨道图像和最大轨道图像?【英文标题】:HowdoIsetUISlidertohaveonlyonetrackimageratherthanusingaminimumtrackimageandamaximumtrackimageinSwift?【发布时间】:2017-04-1122:20:56【问题描... 查看详情

具有自定义形状的自定义 ImageView

】具有自定义形状的自定义ImageView【英文标题】:CustomImageViewWithaCustomShape【发布时间】:2016-12-2710:23:40【问题描述】:我正在尝试创建一个自定义ImageView,它在自定义边框和形状而不是默认矩形内显示图像,并且边框的外侧是Tr... 查看详情

修改自定义 UISlider

】修改自定义UISlider【英文标题】:ModifyingacustomUISlider【发布时间】:2012-07-1915:16:42【问题描述】:所以我有一个使用以下代码制作的自定义UISlider:UIImage*minImage=[UIImageimageNamed:@"settings_slider_fill.png"];UIImage*maxImage=[UIImageimageNamed:@"s... 查看详情

视频预览的自定义形状:AVCaptureVideoPreviewLayer?

】视频预览的自定义形状:AVCaptureVideoPreviewLayer?【英文标题】:Customshapeforvideopreview:AVCaptureVideoPreviewLayer?【发布时间】:2019-11-1910:24:09【问题描述】:是否可以像剪辑图像一样剪辑视频预览层?image.clipShape(Circle()).overlay(Circle().... 查看详情

我想在 UIView 上绘制像苹果形状这样的自定义形状

】我想在UIView上绘制像苹果形状这样的自定义形状【英文标题】:IwanttodrawcustomshapelikeappleshapeonUIView【发布时间】:2015-04-1004:42:20【问题描述】:我正在尝试为progressHUD制作Apple的形状。我可以选择使用.png图像,但我不能,因为... 查看详情