[SwiftUI 100天] Bookworm-part5 自定义评星组件

884 阅读3分钟

译自 www.hackingwithswift.com/books/ios-s…

更多内容,欢迎关注公众号 「Swift花园」
喜欢文章?不如来个 🔺💛➕三连?关注专栏,关注我 🚀🚀🚀

添加自定义评星组件

SwiftUI 使得创建自定义 UI 组件变得十分容易,因为它们基本上就是一些暴露了某些@Binding给我们的视图。

为了说明这一点,我们要构建一个星级评价视图,可以让用户通过点击图片选择 1 分 到 5 分。虽然在我们的案例中,只需要很简单的实现就能工作,不过为了让这个控件也能适用于别的地方,我们需要为它添加一些灵活性。这意味着我们需要设计几个自定义属性:

  • 评级的标签(默认:空字符串)
  • 最大等级评定(默认:5)
  • 点亮星星和未点亮星星的图片(默认:nil 作为未点亮的图片,一个填充的星星作为点亮的图片;如果我们发现未点亮用的也是 nil,那我们对其也适用点亮的图片)
  • 点亮和未点亮的颜色(默认:点亮用黄色,未点亮用灰色)

我们还需要一个额外的属性存储@Binding整数,以便我们报告用户选择的星级。

创建一个新的 SwiftUI 视图,取名 “RatingView”,添加下面这些属性:

@Binding var rating: Int

var label = ""

var maximumRating = 5

var offImage: Image?
var onImage = Image(systemName: "star.fill")

var offColor = Color.gray
var onColor = Color.yellow

在我们填充body属性之前,请先尝试编译代码 —— 你会发现编译失败,因为RatingView_Previews结构体没有为rating传入Binding

SwiftUI 对此有一个专门的简单解决方案,称为常量 bindings。它们是一些拥有固定值的 bindings ,一方面意味着它们不能在 UI 中改变,同时也意味着我们可以非常方便地创建它们 —— 对于预览的场景非常适用。

previews属性替换成下面这样:

static var previews: some View {
    RatingView(rating: .constant(4))
}

现在让我们回到body属性。这里头会有一个HStack,包含要显示的标签,加上足够多的星星 —— 不过,我们可以选择自己的图片,当然不一定必须是星星。

给星星选择图片的逻辑非常简单,但将它们拆分到自己的方法能够降低代码的复杂度。逻辑如下:

  • 如果索引大于当前评级,如果未点亮的图像存在,返回未点亮的图像,否则返回点亮的图像。
  • 如果传索引小于等于当前评级,返回点亮的图像。

我们可以把这个逻辑封装成一个方法,把下面的代码添加到RatingView

func image(for number: Int) -> Image {
    if number > rating {
        return offImage ?? onImage
    } else {
        return onImage
    }
}

现在,实现body属性变得令人惊讶的简单。如果标签有文本,则使用为其创建文本视图,然后使用ForEach遍历 1 到最大等级,然后调用重复调用image(for:)。取决于评级,我们还要应用一个前景色,并且增加点击手势,以支持选定等级。

body属性替换成下面这样:

HStack {
    if label.isEmpty == false {
        Text(label)
    }

    ForEach(1...maximumRating) { number in
        self.image(for: number)
            .foregroundColor(number > self.rating ? self.offColor : self.onColor)
            .onTapGesture {
                self.rating = number
            }
    }
}

这样一来我们的评级视图就完成了,把它放回我们的AddBookView,用下面的代码替换第二个段落原来的代码:

Section {
    RatingView(rating: $rating)
    TextField("Write a review", text: $review)
}

所需的代码就这些 —— 我们的默认值是合理的,所以视觉效果看起来很不错。你也不用再点击进入选择器视图中取选择星级,这些星星评级视图看起来更自然,也更常用。

整体效果如下:

                                     



我的公众号 这里有Swift及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~