Swift 星星评价控件

1,161 阅读2分钟

空闲时间里,做了一个星星评价的控件,如下:

StartRateControl.gif
好了,废话不多说,先说思路吧~首先,要先建立层View,一层装未选中的星星,一层装选中的星星,如图:
我的思路就是,在两层View上,分别放上选中星星的图片和未选中星星的图片,然后再获取手势的位置设置选中星星图层的宽度,分为两个思路,一个是滑动,一个则是点击,下面是滑动评分的代码,根据滑动手势获取位置计算出评分

//滑动评分
    @objc func starPan(_ recognizer:UIPanGestureRecognizer) -> () {
        var OffX:CGFloat = 0
        if recognizer.state == .began{
            OffX = recognizer.location(in: self).x
        }else if recognizer.state == .changed{
            OffX += recognizer.location(in: self).x
        }else{
            return
        }
        // 最低一颗星星
        if OffX < 0 {
            OffX = 1
        }
        self.score = Float(OffX) / Float(self.bounds.width) * Float(self.count)
        showStarRate()
        backSorce()
    }

下面是点击评分的代码,根据点击手势获取位置计算出评分

//点击评分
    @objc func starTap(_ recognizer:UIPanGestureRecognizer) -> () {
        if !self.allowTap {
            return
        }
        let OffX = recognizer.location(in: self).x
        self.score = Float(OffX) / Float(self.bounds.width) * Float(self.count)
        showStarRate()
        backSorce()
    }

然后根据手势计算的评分来刷新UI界面,在显示评分这里,有两个思路,一个是支持非整星的评分,一个是只支持整星的评分

 //显示评分
    fileprivate func showStarRate(){
        let  duration = (usePanAnimation && !firstInit) ? 0.1 : 0.0
        UIView.animate(withDuration: duration, animations: {
            if self.allowUnderCompleteStar{//支持非整星评分
                self.starForegroundView.frame = CGRect(x: 0,y: 0,width: self.bounds.width / CGFloat(self.count) * CGFloat(self.score),height: self.bounds.height)
            }else{//只支持整星评分
                self.starForegroundView.frame = CGRect(x: 0,y: 0,width: self.bounds.width / CGFloat(self.count) * CGFloat(ceilf(self.score)),height: self.bounds.height)
            }
        })
    }

核心代码基本就在这三个方法里面,向外界传递评价分数我是用的 block 传的,根据个人喜好,也可以用代理的方式提供给外界,这里就不放代码了。 在外面调用星星评价控件也非常简单,下面上个调用的方法

// 评分星星
    fileprivate lazy var startStateView: THStartRateView = {
        let frame = CGRect(x: 20, y: 200, width: 160, height:27)
        let startView = THStartRateView.init(frame: frame, starCount: 5, score: 5, foreImageName: "bigbig", interval: 5)
        startView.score = 5
        startView.allowTap = true
        startView.allowUserPan = true
        startView.isUserInteractionEnabled = true
        return startView
    }()