【问题标题】:Make sliding view stay inside the borders of background view使滑动视图保持在背景视图的边界内
【发布时间】:2020-05-28 14:14:51
【问题描述】:

我需要制作滑块让用户左右滑动以确认他想买东西

我通过更新前导约束的偏移量来移动滑块。 问题是我不能让滑块停留在背景视图的边框中。 我尝试保存当前偏移量并在每次触摸后检查坐标差异,但它不起作用。

 var diff: CGFloat {
        return startCoordinate - endCoordinate
    }

private func updateConstraints(_ diff: CGFloat) {
        if diff + appearance.sliderLeadingOffset + currentOffset <= appearance.sliderMaxLeadingOffset {
            sliderView.snp.updateConstraints { make in
                make.leading.equalTo(backgroundView.snp.leading).offset(-diff)
            }
            startCoordinate = diff
            currentOffset = diff + appearance.sliderLeadingOffset
        }

    }

    @objc private func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
        switch gestureRecognizer.state {
        case .began:
            let touchLocation = gestureRecognizer.location(in: sliderView)
            touchOffset = sliderView.bounds.minX + touchLocation.x
            startCoordinate = touchLocation.x - touchOffset
        case .ended:
            endCoordinate = gestureRecognizer.location(in: sliderView).x
        case .changed:
            let location = gestureRecognizer.location(in: sliderView)
            if backgroundView.frame.contains(location) {
                endCoordinate = location.x - touchOffset
            }
            updateConstraints(diff)
        default: break
        }
    }

【问题讨论】:

    标签: ios swift autolayout


    【解决方案1】:

    以下是功能齐全的滑块按钮的完整代码。 创建一个新的 Swift 文件并将其命名为 SlidingButton.swift

    import Foundation
    import UIKit
    
    protocol SlideButtonDelegate{
        func buttonStatus(status:String, sender:SlidingButton)
    }
    
    @IBDesignable class SlidingButton: UIView{
    
    var delegate: SlideButtonDelegate?
    
    @IBInspectable var dragPointWidth: CGFloat = 100 {
        didSet{
            setStyle()
        }
    }
    
    @IBInspectable var dragPointColor: UIColor = UIColor.darkGray {
        didSet{
            setStyle()
        }
    }
    
    @IBInspectable var buttonColor: UIColor = UIColor.gray {
        didSet{
            setStyle()
        }
    }
    
    @IBInspectable var buttonText: String = "Slide Here" {
        didSet{
            setStyle()
        }
    }
    
    @IBInspectable var imageName: UIImage = UIImage() {
        didSet{
            setStyle()
        }
    }
    
    @IBInspectable var buttonTextColor: UIColor = UIColor.white {
        didSet{
            setStyle()
        }
    }
    
    @IBInspectable var dragPointTextColor: UIColor = UIColor.white {
        didSet{
            setStyle()
        }
    }
    
    @IBInspectable var buttonFinishedSliding: UIColor = UIColor.white {
        didSet{
            setStyle()
        }
    }
    
    @IBInspectable var buttonCornerRadius: CGFloat = 30 {
        didSet{
            setStyle()
        }
    }
    
    var buttonFont = UIFont.boldSystemFont(ofSize: 35)
    
    var dragPoint = UIView()
    var buttonLabel = UILabel()
    var dragPointButtonLabel = UILabel()
    var imageView = UIImageView()
    var layoutSet = false
    
    override init (frame : CGRect) {
        super.init(frame : frame)
    }
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
    
    }
    
    override func layoutSubviews() {
        if !layoutSet{
            self.setUpButton()
            self.layoutSet = true
        }
    }
    
    func setStyle(){
        self.buttonLabel.text = self.buttonText
        self.dragPointButtonLabel.text = self.buttonText
        self.dragPoint.frame.size.width = self.dragPointWidth
        self.dragPoint.backgroundColor = self.dragPointColor
        self.backgroundColor = self.buttonColor
        self.imageView.image = imageName
        self.buttonLabel.textColor = self.buttonTextColor
        self.dragPointButtonLabel.textColor = self.dragPointTextColor
    
        self.dragPoint.layer.cornerRadius = buttonCornerRadius
        self.layer.cornerRadius = buttonCornerRadius
    }
    
    func setUpButton(){
    
        self.backgroundColor = self.buttonColor
        self.dragPoint = UIView(frame: CGRect(x: dragPointWidth - self.frame.size.width, y: 0, width: self.frame.size.width, height: self.frame.size.height))
        self.dragPoint.backgroundColor = dragPointColor
        self.dragPoint.layer.cornerRadius = buttonCornerRadius
        self.addSubview(self.dragPoint)
    
        if !self.buttonText.isEmpty{
    
            self.buttonLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height))
            self.buttonLabel.textAlignment = .center
            self.buttonLabel.text = buttonText
            self.buttonLabel.textColor = UIColor.white
            self.buttonLabel.font = self.buttonFont
            self.buttonLabel.textColor = self.buttonTextColor
            self.addSubview(self.buttonLabel)
    
            self.dragPointButtonLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height))
            self.dragPointButtonLabel.textAlignment = .center
            self.dragPointButtonLabel.text = buttonText
            self.dragPointButtonLabel.textColor = UIColor.white
            self.dragPointButtonLabel.font = self.buttonFont
            self.dragPointButtonLabel.textColor = self.dragPointTextColor
            self.dragPoint.addSubview(self.dragPointButtonLabel)
        }
        self.bringSubviewToFront(self.dragPoint)
    
        if self.imageName != UIImage(){
            self.imageView = UIImageView(frame: CGRect(x: self.frame.size.width - dragPointWidth, y: 0, width: self.dragPointWidth, height: self.frame.size.height))
            self.imageView.contentMode = .center
            self.imageView.image = self.imageName
            self.dragPoint.addSubview(self.imageView)
        }
    
        self.layer.masksToBounds = true
    
        // start detecting pan gesture
        let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panDetected(sender:)))
        panGestureRecognizer.minimumNumberOfTouches = 1
        self.dragPoint.addGestureRecognizer(panGestureRecognizer)
    }
    
    @objc func panDetected(sender: UIPanGestureRecognizer){
        var translatedPoint = sender.translation(in: self)
        translatedPoint     = CGPoint(x: translatedPoint.x, y: self.frame.size.height / 2)
        sender.view?.frame.origin.x = (dragPointWidth - self.frame.size.width) + translatedPoint.x
        if sender.state == .ended{
    
            let velocityX = sender.velocity(in: self).x * 0.2
            var finalX = translatedPoint.x + velocityX
            if finalX < 0{
                finalX = 0
            }else if finalX + self.dragPointWidth  >  (self.frame.size.width - 60){
                // final point reached, do somethign here
            }
    
            let animationDuration:Double = abs(Double(velocityX) * 0.0002) + 0.2
            UIView.transition(with: self, duration: animationDuration, options: UIView.AnimationOptions.curveEaseOut, animations: {
                }, completion: { (Status) in
                    if Status{
                        self.animationFinished()
                    }
            })
        }
    }
    }
    

    用法:

    添加一个 UIVIEW 并使其符合上面的 SlidingButton 类

    然后您可以根据需要使用情节提要进行调整

    【讨论】:

    • 什么是self.unlock()self.animationFinished()unlocked = true..???
    • @SaifanNadaf 哎呀,这是我忘记删除的函数调用...
    • @SaifanNadaf 我删除并编辑了它。只需在该块中添加您自己的任务即可完成
    猜你喜欢
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多