<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nicola De Filippo</title>
    <description>The latest articles on Forem by Nicola De Filippo (@niqt).</description>
    <link>https://forem.com/niqt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F47459%2Fd354efe9-457f-4887-ad90-40a93a7040ca.jpeg</url>
      <title>Forem: Nicola De Filippo</title>
      <link>https://forem.com/niqt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/niqt"/>
    <language>en</language>
    <item>
      <title>Mastering Customization: Configuring the Look and Feel of Lists in SwiftUI</title>
      <dc:creator>Nicola De Filippo</dc:creator>
      <pubDate>Tue, 19 Dec 2023 21:55:23 +0000</pubDate>
      <link>https://forem.com/niqt/mastering-customization-configuring-the-look-and-feel-of-lists-in-swiftui-5de</link>
      <guid>https://forem.com/niqt/mastering-customization-configuring-the-look-and-feel-of-lists-in-swiftui-5de</guid>
      <description>&lt;h1&gt;
  
  
  Mastering Customization: Configuring the Look and Feel of Lists in SwiftUI
&lt;/h1&gt;

&lt;p&gt;In this post, we’ll learn how to configure the look and feel of a list. The image we’re using is from unsplash,; rename it ‘zoe’ and copy it into the assets.&lt;/p&gt;

&lt;p&gt;Let’s start from the end and begin by envisioning what we want to create:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lnMZmXXp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdzg45e49zao0pmx9zp9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lnMZmXXp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdzg45e49zao0pmx9zp9.png" alt="Image description" width="506" height="996"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, install the San Francisco symbols (if you haven’t already), then create the data structure that we want to display in the list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct Decoration: Identifiable {
    let id = UUID()
    var name: String
    var color: Color
    var image: String
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The struct implement the Identifiable protocol, because we need add an unique identifier.&lt;/p&gt;

&lt;p&gt;In the ContentView, we initialize the data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct ContentView: View {
    var decorations = [Decoration(name: "Star", color: .yellow, image:  "star.fill"), Decoration(name: "Light", color: .pink, image: "lightbulb.fill"), Decoration(name: "Snow", color: .white, image:"snowflake")]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We add only three Christmas decorations.&lt;/p&gt;

&lt;p&gt;In the body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var body: some View {
        NavigationStack {
            List(decorations) { decoration in
                NavigationLink(destination: EmptyView()) {
                    HStack {
                        Image(systemName: decoration.image)
                            .foregroundStyle(decoration.color)
                            .frame(width: 50, height: 50)
                        Text(decoration.name)
                            .foregroundColor(decoration.color)
                            .opacity(0.7)
                            .font(.title)
                            .fontWeight(.bold)
                    }
                }.listRowBackground(Color(red: 0.1, green: 0.1, blue: 0.1))
                .listRowSeparatorTint(.white)

            }
            .navigationTitle("Decorations")
            .background(Image("zoe").resizable().aspectRatio(contentMode: .fill)
                .edgesIgnoringSafeArea(.all)
            )
            .scrollContentBackground(.hidden)
            .opacity(0.8)

        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The content of each row is displayed using an HStack, which includes the name, color and the image of the decoration, utilizing the data from the decoration array.&lt;/p&gt;

&lt;p&gt;Now, let’s take a look at the individual customizations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.listRowBackground(Color(red: 0.1, green: 0.1, blue: 0.1))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, we set the background of the row to a custom gray, instead of the default white (in light mode) or black (in dark mode).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.listRowSeparatorTint(.white)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To enhance the visibility of the row separator, we use this code to change its default color.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.background(Image("zoe").resizable().aspectRatio(contentMode: .fill)
.edgesIgnoringSafeArea(.all))
.opacity(0.8)
.scrollContentBackground(.hidden)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Therefore, we set the image as the background with a certain opacity and use all the available screen space, ignoring the safe area on every edge. Note that this last property is applied to the image, not to the background. Finally, we hide the background of the content so that the image is fully visible.&lt;/p&gt;

&lt;p&gt;If you execute this code, you will see the title with the default black color (when using light mode). However, we want the title to always be in white. To achieve this, we add the init function to ContentView:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;init() {
      // Large Navigation Title
      UINavigationBar.appearance().largeTitleTextAttributes =  [.foregroundColor: UIColor.white]
      // Inline Navigation Title
      UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: UIColor.white]
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way, we set the text color for large and inline titles. Note the ‘UI’ prefix, which means that we are using functions from UIKit.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: English is not my native language, so I’m sorry for some errors. I appreciate if your correct me.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;[originally published](&lt;a href="https://nicoladefilippo.com/mastering-customization-configuring-the-look-and-feel-of-lists-in-swiftui/"&gt;https://nicoladefilippo.com/mastering-customization-configuring-the-look-and-feel-of-lists-in-swiftui/&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>swiftui</category>
      <category>swift</category>
      <category>iosdevelopment</category>
    </item>
    <item>
      <title>SwiftUI Sheets Demystified (Episode II )</title>
      <dc:creator>Nicola De Filippo</dc:creator>
      <pubDate>Sun, 17 Dec 2023 22:39:21 +0000</pubDate>
      <link>https://forem.com/niqt/swiftui-sheets-demystified-episode-iideg-4m26</link>
      <guid>https://forem.com/niqt/swiftui-sheets-demystified-episode-iideg-4m26</guid>
      <description>&lt;p&gt;In the previous episode &lt;a href="https://nicoladefilippo.com/swiftui-sheets-demystified-episode-i/"&gt;SwiftUI Sheets Demystified (Episode I°)&lt;/a&gt;, we learned how to open a sheet. In this episode, we will learn how to open the sheet by passing a selected value. Here’s a brief overview of what we’ll cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Selecting a color name from a list, passing the selected color to the sheet, and using it as the background color.&lt;/li&gt;
&lt;li&gt;How to tap a row in a list that has an empty zone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, let’s define the color struct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct IColor: Identifiable {
    let id = UUID()
    var name: String
    var value: Color
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This struct implements the &lt;em&gt;Identifiable&lt;/em&gt; protocol so we add the id identifier. The name contains the color name, instead the value the color.&lt;/p&gt;

&lt;p&gt;Now, let’s take a look at the ContentView:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct ContentView: View {
    var colors = [IColor(name: "red", value: .red), IColor(name: "blue", value: .blue), IColor(name: "green", value: .green)]
    @State var colorSelected: IColor?
    var body: some View {
        NavigationStack {
            List{
                ForEach(colors) { color in
                    HStack() {
                        Text(color.name)
                        Spacer()

                    }.contentShape(Rectangle())
                    .onTapGesture {
                        colorSelected = color
                    }
                }
            }.sheet(item: $colorSelected) { color in
                SheetUIView(color: $colorSelected)
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have a list of three colors. We define a state variable &lt;strong&gt;colorSelected&lt;/strong&gt; as an optional because initially, no color is selected.&lt;/p&gt;

&lt;p&gt;The list of colors is displayed using a horizontal stack comprising a &lt;strong&gt;Text&lt;/strong&gt; and a &lt;strong&gt;Spacer&lt;/strong&gt; (to fill the entire row of the list).&lt;/p&gt;

&lt;p&gt;We define the &lt;strong&gt;onTapGesture&lt;/strong&gt; to set &lt;strong&gt;colorSelected&lt;/strong&gt; to the chosen color. Then, the sheet is opened when the &lt;strong&gt;colorSelected&lt;/strong&gt; variable changes its value. In this case, it opens with the SheetUIView that receives the selected color.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;SheetUIView&lt;/em&gt; is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct SheetUIView: View {
    @Environment(\.dismiss) private var dismiss
    @Binding var color: IColor?
    var body: some View {
        ScrollView {
        }.overlay(
            HStack {
                Spacer()
                VStack {
                    Button(action: {
                        dismiss()
                    }, label: {
                        Image(systemName: "chevron.down.circle.fill")
                            .font(.largeTitle)
                            .foregroundColor(.white)
                    })
                        .padding(.trailing, 20)
                        .padding(.top, 10)
                    Spacer()
                }
            }
        ).edgesIgnoringSafeArea(.all)
            .background(
                color?.value ?? .white
            )
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The view is identical to that of the first episode, with only two differences: the image has been removed for brevity, and it’s added the&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.background(
     color?.value ?? .white
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the default color value is set to white. It’s essential to define a default value not only for when the sheet is opened, but also for when it’s closed. Without a default value, the selected color would be null when the sheet is closed, potentially causing the app to crash.&lt;/p&gt;

&lt;p&gt;One consideration to keep in mind, take a look in the ContentView at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.contentShape(Rectangle())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s necessary to make the entire row clickable. If we omit this, only the text area of the row will be clickable.&lt;/p&gt;

&lt;p&gt;To conclude, in the SheetUIView, use the following preview instruction to avoid errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Preview {
    @State var color: IColor? = IColor(name: "white", value: .white)
    return SheetUIView(color: $color)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Note: English is not my native language, so I’m sorry for some errors. I appreciate if your correct me.*
&lt;a href="https://nicoladefilippo.com/swiftui-sheets-demystified-episode-ii/"&gt;Originally posted&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swiftui</category>
      <category>swift</category>
      <category>iosdevelopment</category>
    </item>
    <item>
      <title>SwiftUI Sheets Demystified (Episode I )</title>
      <dc:creator>Nicola De Filippo</dc:creator>
      <pubDate>Mon, 11 Dec 2023 20:55:38 +0000</pubDate>
      <link>https://forem.com/niqt/swiftui-sheets-demystified-episode-ideg-2abp</link>
      <guid>https://forem.com/niqt/swiftui-sheets-demystified-episode-ideg-2abp</guid>
      <description>&lt;h1&gt;
  
  
  SwiftUI Sheets Demystified (Episode I°)
&lt;/h1&gt;

&lt;p&gt;In this post, we learn how to use sheets in SwiftUI. We will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open and close a not full-screen sheet&lt;/li&gt;
&lt;li&gt;Open and close a full-screen sheet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this example, i use this image &lt;a href="https://unsplash.com/it/foto/uno-sfondo-nero-con-una-lettera-fatta-di-liquido-29pM4D0phcc"&gt;unplash&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Non-Full-Screen Sheet
&lt;/h3&gt;

&lt;p&gt;Begin by creating the project and adding the image to the assets. I’ve renamed it susan.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct ContentView: View {
    @State var isPresented = false
    var body: some View {
        NavigationStack {
            Text("Sheet")
                .toolbar {
                    ToolbarItem(placement: .confirmationAction) {
                        Button("+") {
                            isPresented = true
                        }.font(.largeTitle)
                    }
                }
        }
        .sheet(isPresented: $isPresented, content: {
            SheetUIView()
        })
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we add a ‘plus’ button to the toolbar. When this button is tapped, the variable isPresented is set to true. Once isPresented becomes true, the sheet is presented, displaying the SheetUIView.&lt;/p&gt;

&lt;p&gt;Define the SheetUIView:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct SheetUIView: View {
    @Environment(\.dismiss) private var dismiss
    var body: some View {
        ScrollView {
            VStack {
                Image("susan")
                .resizable()
                .aspectRatio(contentMode: .fit)
                Text("The sheet")
            }
        }.overlay(
            HStack {
                Spacer()
                VStack {
                    Button(action: {
                        dismiss()
                    }, label: {
                        Image(systemName: "chevron.down.circle.fill")
                            .font(.largeTitle)
                            .foregroundColor(.white)
                    })
                        .padding(.trailing, 20)
                        .padding(.top, 10)
                    Spacer()
                }
            }
        )
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the Environment‘s dismiss, we call DismissAction on the current view. The body of the view contains an image at the top and some simple text. Although sheets are typically closed with a top-down swipe action, this might not always be intuitive. Therefore, we add a close button for clarity. Specifically, we place a button on the top-right corner with an action that calls dismiss(), thereby closing the sheet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XWAc6p_b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/di7cecwn8lth7u8zw77l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XWAc6p_b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/di7cecwn8lth7u8zw77l.png" alt="Image description" width="258" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Full-Screen Sheet:
&lt;/h3&gt;

&lt;p&gt;First, let’s start with a small modification in the ContentView.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct ContentView: View {
    @State var isPresented = false
    var body: some View {
        NavigationStack {
            Text("Sheet")
                .toolbar {
                    ToolbarItem(placement: .confirmationAction) {                     
                        Button("+") {
                            isPresented = true
                        }.font(.largeTitle)
                    }
                }
        }
        .fullScreenCover(isPresented: $isPresented){
            SheetUIView()
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We replace sheet with fullScreenCover for this implementation.&lt;/p&gt;

&lt;p&gt;In the SheetUIView, we ignore the safe area to achieve a visually appealing effect:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KBgdnAcs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7y7k48iwx65gwmsyt6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBgdnAcs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7y7k48iwx65gwmsyt6x.png" alt="Image description" width="266" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct SheetUIView: View {
    @Environment(\.dismiss) private var dismiss
    var body: some View {
        ScrollView {
            VStack {
                Image("susan")
                .resizable()
                .aspectRatio(contentMode: .fit)
                Text("The sheet")
            }
        }.overlay(
            HStack {
                Spacer()
                VStack {
                    Button(action: {
                        dismiss()
                    }, label: {
                        Image(systemName: "chevron.down.circle.fill")
                            .font(.largeTitle)
                            .foregroundColor(.white)
                    })
                        .padding(.trailing, 20)
                        .padding(.top, 10)
                    Spacer()
                }
            }
        ).edgesIgnoringSafeArea(.all)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A tip for both scenarios mentioned above: If you’re not using an image but rather a VStack within a ScrollView, it’s advisable to define the VStack with these dimensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ScrollView {
            VStack {
                Spacer(minLength: 100)
                Text("Hello")
            }.frame(maxWidth: .infinity, maxHeight: .infinity)
        }
        ......
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is necessary to prevent the close button, defined in the overlay, from following the text in the VStack and ensure it stays at the top right border.&lt;/p&gt;

&lt;p&gt;That’s all for this post. In the next one &lt;a href="https://nicoladefilippo.com/swiftui-sheets-demystified-episode-ii/"&gt;episode-ii&lt;/a&gt;, we will explore additional scenarios for using sheets.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: English is not my native language, so I’m sorry for some errors. I appreciate if your correct me.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nicoladefilippo.com/swiftui-sheets-demystified-episode-i/"&gt;Originally posted here&lt;/a&gt; &lt;/p&gt;

</description>
      <category>swiftui</category>
      <category>swift</category>
      <category>iosdevelopment</category>
    </item>
    <item>
      <title>Onboarding with a pager</title>
      <dc:creator>Nicola De Filippo</dc:creator>
      <pubDate>Wed, 06 Dec 2023 20:36:23 +0000</pubDate>
      <link>https://forem.com/niqt/onboarding-with-a-pager-4oia</link>
      <guid>https://forem.com/niqt/onboarding-with-a-pager-4oia</guid>
      <description>&lt;p&gt;To help you with creating an onboarding screen using a custom pager with a custom font, custom color, and button, I’ll guide you through the steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create the Pager Component:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The pager will typically be a component or a view that allows the user to swipe through different screens (each representing a step in the onboarding process).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Custom Font and Color:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To apply a custom font, first add the font files to your project. Then, set the font for the text elements in your pager screens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For custom colors, define the color values (like hex codes or RGB) in your project’s color resources or stylesheet. Apply these colors to the text, background, or other elements as needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding a Button:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a custom button&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, take a look how to create a pager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TabView {
      Text("First page")
      Text("Second page")
      Text("Third page")
}.tabViewStyle(.page)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now see how to add a font:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;download Fredoka from here &lt;a href="https://fonts.google.com/specimen/Fredoka" rel="noopener noreferrer"&gt;https://fonts.google.com/specimen/Fredoka&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;add it to the project select from the File menu “Add file to your project” and select the font file&lt;/li&gt;
&lt;li&gt;write the font file mane in the info section “Font provided by the application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl10tsl5ylaw7ozfc0wrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl10tsl5ylaw7ozfc0wrd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now add a custom color, in the project open assets and add color:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6nt3rboidf8fyevun5f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6nt3rboidf8fyevun5f.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set a name for the color and in the right panel set the color value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2b9raxotzqvkay5oeisy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2b9raxotzqvkay5oeisy.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now create three views, using the custom color and the custom font, and please download also the san Francisco symbols (&lt;a href="https://developer.apple.com/sf-symbols/" rel="noopener noreferrer"&gt;https://developer.apple.com/sf-symbols/&lt;/a&gt;) for the images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct ContentView: View {
    var body: some View {
        TabView {
            VStack {
                Image(systemName: "car")
                    .resizable()
                    .frame(width: 100, height: 100)
                Text("Welcome - first screen")
                    .font(Font.custom("Fredoka-Regular", size: 30, relativeTo: .largeTitle))
            }
            VStack {
                Image(systemName: "bolt.car")
                    .resizable()
                    .frame(width: 100, height: 100)
                Text("Welcome - second screen")
                    .font(Font.custom("Fredoka-Regular", size: 30, relativeTo: .largeTitle))
            }
        }.tabViewStyle(.page)
        .background(Color("onboardingColor"))
        .foregroundStyle(.white)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first screen is:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1kt1dubygzqm7v8yy6rp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1kt1dubygzqm7v8yy6rp.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
To add custom button with a white border:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VStack {
       Image(systemName: "bolt.car")
       .resizable()
       .frame(width: 100, height: 100)
       Text("Welcome - second screen")
       .font(Font.custom("Fredoka-Regular", size: 30, relativeTo: .largeTitle))

       Button("Start") {

       }
       .padding()
       .overlay(
           Capsule()
           .stroke(Color.white, lineWidth: 2)

        )
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add the border to the button we use an overlay with a capsule shape empty with only a white border.&lt;/p&gt;

&lt;p&gt;Enjoy creating your onboarding screen. Remember, a well-designed onboarding experience can significantly enhance user engagement and understanding of your app.&lt;/p&gt;

</description>
      <category>swiftui</category>
    </item>
  </channel>
</rss>
