Translation of www.hackingwithswift.com/books/ios-s…

For more content, please follow the public account “Swift Garden”.


Like articles? How about 🔺💛➕ company 3? Follow this column, follow me 🚀🚀🚀

Add custom star rating components

SwiftUI makes it easy to create custom UI components because they are basically views that expose some @binding to us.

To illustrate this, we’ll build a star rating view that lets the user select a score from 1 to 5 by clicking on an image. Although in our case a very simple implementation is required to work, we need to add some flexibility to the control in order for it to work elsewhere. This means we need to design several custom properties:

  • Rated label (default: empty string)
  • Maximum rating (default: 5)
  • Images of lit and unlit stars (default:nilAs an unlit image, a filled star as a lit image; So is if we find it unlitnil, then we can also apply to lit pictures.)
  • Lit and unlit colors (default: yellow for lit, gray for unlit)

We also need an additional attribute to store the @Binding integer so that we can report the star selected by the user.

Create a new SwiftUI view called “RatingView” and add the following properties:

@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.yellowCopy the code

Before we populate the body property, try compiling the code — you will find that the compilation fails because the RatingView_Previews structure did not pass in a Binding for the rating.

SwiftUI has a special simple solution for this called Constant Bindings. They’re bindings with fixed values, which means they can’t be changed in the UI, but also means they can be created very easily — great for preview scenarios.

Replace the previews attribute with the following:

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

Now let’s go back to the body property. There will be an HStack at the head that contains the tags to display, plus as many stars as you need — however, you can choose your own image, but it doesn’t have to be stars.

The logic for selecting images for the stars is simple, but splitting them into their own method reduces the complexity of the code. The logic is as follows:

  • If index is greater than current rating, return unlit image if unlit image exists, otherwise return lit image.
  • If the index is less than or equal to the current rating, return the lit image.

We can wrap this logic into a method and add the following code to the RatingView:

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

Now, implementing the body property is surprisingly simple. If the tag has text, create a text view for it, then use ForEach to traverse 1 to the maximum level, and then call image repeatedly (for:). Depending on the rating, we also apply a foreground color and add a click gesture to support the selected rating.

Replace the body attribute with the following:

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

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

Now that our rating view is complete, put it back into our AddBookView and replace the second paragraph with the following:

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

That’s all the code we need — our defaults are reasonable, so the visuals look good. You also don’t have to click into the selector view to select a star, these star rating views look more natural and more common.

The overall effect is as follows:

                                     




My official account here Swift and computer programming related articles, as well as excellent translation of foreign articles, welcome to pay attention to ~

                                                                 Â