Custom Review star images not showing properly in Swift

问题描述 投票:0回答:1

我在故事板和连接的网点中拍摄了 5 个图像视图

@IBOutlet var starRatingImageViews: [UIImageView]!

我正在从 json 中获取字符串值以获得 rating 像这样

rating = "4.2"

例如。

rating = "4.2" i need to show 4 full stars and one half star
但显示不正确

o/p:这里我有“4.2”评级,但它的星星在输出中显示错误。请指导我解决这个问题

代码: 这里

user.rating = "4.2"
但在 o/p 中显示错误的星星。
fillStars
方法我哪里错了。请指导。

 @IBOutlet var starRatingImageViews: [UIImageView]!

 if let rating = Float(user.rating ?? "0.0") {
     rating.fillStars(in: starRatingImageViews)
 }

 func fillStars(in imageViews: [UIImageView], withEmptyStar color: UIColor = .darkGray) {
    for i in (0 ..< imageViews.count) {
        imageViews[i].contentMode = .scaleAspectFit
        let review = Int(Float(self))
        if (i < review) {
            imageViews[i].image = UIImage(systemName: "star.fill")?.withRenderingMode(.alwaysOriginal).withTintColor(CommonColor.yellowColor)
        } else {
            if (self - Float(review)) > (0.5), i == review {
                imageViews[i].image = UIImage(systemName: "star.fill")?.withRenderingMode(.alwaysOriginal).withTintColor(CommonColor.yellowColor)
            } else if (self - Float(review)) <= (0.5), (self - Float(review)) > (0.0), i == review {
                imageViews[i].image = UIImage(systemName: "star.leadinghalf.fill")?.withRenderingMode(.alwaysOriginal).withTintColor(CommonColor.yellowColor)
            } else {
                imageViews[i].image = UIImage(systemName: "star")?.withRenderingMode(.alwaysOriginal).withTintColor(color)
            }
        }
    }
}
swift for-loop floating-point uiimageview
1个回答
0
投票

问题是您正在使用

self - Float(review)
来确定要绘制哪种星星,但是
self
独立于您的循环,并且您甚至不一致,因为您使用
i < review
作为第一次测试。你可以做到这一点,但它比需要的更难。如果情况比您需要的多,事情就会变得更加混乱:您需要画一颗实心星、半实心星或空心星。那是 3 个案例,但你的代码中有 4 个,因为你复制了完整的星号案例。

当我遇到这样的问题时,我更愿意考虑计算需要绘制的当前指标(星号,在你的情况下)的百分比,然后使用该结果来决定做什么,而不是混合一起计算和决策。所以我会修改你的代码是这样的:

func clamp<T: Comparable>(_ value: T, to range: ClosedRange<T>) -> T {
    return max(range.lowerBound, min(range.upperBound, value))
}

func fillStars(
    in imageViews: [UIImageView],
    withEmptyStar color: UIColor = .darkGray)
{
    let review = Float(self) // Is this needed now?

    for i in imageViews.indices
    {
        imageViews[i].contentMode = .scaleAspectFit
        let tintColor: UIColor
        let starName: String
        
        // Calculate the percentage of the current star to draw
        let percentOfThisStar = clamp(review - Float(i), to: 0...1)

        // Now use the percentage to pick the image/tinting
        if percentOfThisStar == 0
        { // Empty star
            tintColor = color
            starName  = "star"
        }
        else
        {
            tintColor = CommonColor.yellowColor
            starName  = percentOfThisStar < 0.5
                ? "star.leadinghalf.fill" // Partial star
                : "star.fill"             // Full star
        }
        
        imageViews[i].image = UIImage(systemName: starName)?
            .withRenderingMode(.alwaysOriginal)
            .withTintColor(tintColor)

    }
}

作为建议,我可能会将

fillStars
移动到代码库的另一部分。我不太确定
self
是什么(
Float
?是。我可能只是让它成为自由函数,或者可能是任何包含星星的视图中的方法,并将
Double
作为参数传递。我的推理只是填充星星与
Decimal
可能是的任何数字类型没有太大关系。这只是您应用程序的一种特殊情况用法,可能仅适用于您应用程序中的一个特定视图,那么为什么不将其放在该视图中呢?还是作为顶级应用程序特定功能?显然,这是一个判断电话。编译器不关心,所以这只是什么对您和您的团队最有意义的问题。
为了在不创建完整应用程序的情况下更轻松地测试它(并避免必须使用模拟器),我在命令行工具中这样写:
fillStars
我将

review

重命名为

self
,并将其作为参数传入。我打印 
enum StarType: String { case empty = "[ ]" case partial = "[* ]" case filled = "[**]" } func clamp<T: Comparable>(_ value: T, to range: ClosedRange<T>) -> T { return max(range.lowerBound, min(range.upperBound, value)) } func fillStars( in stars: inout [StarType], from rating: Float) { assert(Float(stars.count) >= rating) for i in stars.indices { // Calculate the percentage of the current star to draw let percentOfThisStar = clamp(rating - Float(i), to: 0...1) let starType: StarType // Now use the percentage to pick the image/tinting if percentOfThisStar == 0 { // Empty star starType = .empty } else { starType = percentOfThisStar < 0.5 ? .partial : .filled } stars[i] = starType } }

,而不是实心星,对于部分星,我打印

review
,对于空星,我打印
rating
.
我用这个代码驱动它:
[**]
这些是结果:

评分 = 4.2,星星 = [**][**][**][**][* ]

这似乎是正确的结果。

© www.soinside.com 2019 - 2024. All rights reserved.