DEV Community

Vir
Vir

Posted on

Making a Cell View in SwiftUI

Let's make a View in SwiftUI which looks like a TableView / CollectionView Cell. All the code has been tested in Xcode Playgrounds, feel free to use it https://gist.github.com/Viranchee/87bfe6b39ae86bcc9b5b6f5d4b34d691

We will develop with Swift Playgrounds with Live View so as to easily test and debug. Open Xcode -> New Playgrounds -> Blank Playgrounds -> (Indicate where to save the file). Now run your file using Cmd+Shift+Enter and you can see the output on right side of the screen. Since we will be rendering UI, we will make use of PlaygroundSupport. So go ahead, write these lines

import SwiftUI
import PlaygroundSupport

To run any SwiftUI View inside Playground, we will use the setLiveView method.

PlaygroundPage.current.setLiveView(Cell1())

Let us try to make a Cell with Image, Title and Subtitle
To view the live view, press Cmd+Option+Enter

struct Cell1: View {
  var body: some View {
    HStack {
      Image(systemName: "music.house")
      VStack {
        Text("Title")
        Text("Subtitle")
      }
    }
  }
}
PlaygroundPage.current.setLiveView(Cell1())

Now let us give a shadow to the view. We use the background, stroke, shadow and foregroundColor modifiers on the View.

Note: ... means extra code which is same as the implementation in above snippet.

HStack {
      ...
    }
    .background(
      RoundedRectangle(cornerRadius: 5)
        .stroke(Color.yellow)
        .shadow(color: .gray, radius: 2.5, x: 0.6, y: 0)
        .foregroundColor(.white)
    )

Interesting!

Now let us widen the view by increasing the text. Also let's fix our Image

Let's use the resizable, aspectRatio, frame and padding modifiers on the Image and increase the length of our subtitle string

HStack(spacing: 0) {
      Image(systemName: "music.house")
        .resizable()
        .aspectRatio(1, contentMode: .fit)
        .frame(height: 50)
        .padding()

      ...
    }
    .background(...)

Great!

Let's fix the Title Text and make it have a green background

I will use the bold italic lineLimit maximumScaleFactor padding background foregroundColor modifiers here

VStack(alignment: .leading) {
        Text("Title")
          .bold()
          .italic()
          .lineLimit(1)
          .minimumScaleFactor(0.8)
          .padding(.horizontal, 10)
          .padding(.vertical, 2)
          .background(
            Capsule()
              .foregroundColor(.green)
        )
          .padding(.bottom, 5)
        ...

So far so good. Now let's modify the Subtitle Text

I will use these View Modifiers: lineLimit multilineTextAlignment truncationMode and a fixedSize modifier here.

Text("A long subtitle which extends more than a line")
          .lineLimit(2)
          .multilineTextAlignment(.leading)
          .truncationMode(.tail)
          .fixedSize(horizontal: false, vertical: true)

This completes much of our Cell View. Now, let us check how the View behaves under different circumstances, viz. different lengths of Title and Subtitle. To simulate the different sizes live, we will use the Slider which looks like such

struct SliderView: View {
  @State private var titleLength: CGFloat = 1  

  var body: some View {
        Text(String.init(repeating: "T", count: Int(self.titleLength)))
        Text("Title length")
        Slider(value: $titleLength, in: 1...100) {
// This Text is for Accessibility
          Text("Title")
}

Integrating the slider to control the Text length looks like such in code and output:

struct Cell6: View {
  @State private var titleLength: CGFloat = 1
  @State private var subtitleLength: CGFloat = 1


  var body: some View {
    VStack {


      HStack(spacing: 0) {
        Image(systemName: "music.house")
          .resizable()
          .aspectRatio(1, contentMode: .fit)
          .frame(height: 50)
          .padding()

        VStack(alignment: .leading) {
          Text(String.init(repeating: "T", count: Int(self.titleLength)))
            .bold()
            .italic()
            .lineLimit(1)
            .minimumScaleFactor(0.8)
            .padding(.horizontal, 10)
            .padding(.vertical, 2)
            .background(
              Capsule()
                .foregroundColor(.green)
          )
            .padding(.bottom, 5)
          Text(String.init(repeating: "S", count: Int(self.subtitleLength)))
            .lineLimit(2)
            .multilineTextAlignment(.leading)
            .truncationMode(.tail)
            .fixedSize(horizontal: false, vertical: true)
            .minimumScaleFactor(0.7)
        }
      }
      .background(
        RoundedRectangle(cornerRadius: 5)
          .stroke(Color.yellow)
          .shadow(color: .gray, radius: 2.5, x: 0.6, y: 0)
          .foregroundColor(.white)
      )

      HStack {
        Text("Title length")
        Slider(value: $titleLength, in: 1...40) {
          Text("Title")
        }
      }

      HStack {
        Text("Subtitle length")
        Slider(value: $subtitleLength, in: 1...100) {
          Text("Subtitle")
        }
      }
    }
  }
}

PlaygroundPage.current.setLiveView(Cell6())

Finally, we have crafted a SwiftUI View of our requirements and tested it with variety of input string size.

Credits: 

Top comments (0)