ios入门实例(三): 首屏轮播图

12,976 阅读4分钟

前言:

本章节通过TabView,Gradient,Color set,.infinity等,多个SwiftUI page 实现app首页轮播效果,首屏轮播交互为大部分App都会有的场景,看完本章帮助同学们上手开发属于自己的Carousel

首屏轮播最终效果

file3.gif

创建WelcomePage页

首先创建项目:OnboardingFlow(点击查看如何创建ios应用) 创建项目成功后,在导航栏点击项目右键创建New File

image.png image.png image.png
// WelcomePage

import SwiftUI

struct WelcomePage: View {
    var body: some View {
        Text("Hello, World!")
    }
}

#Preview {
    WelcomePage()
}

写入欢迎文案

// WelcomePage
 var body: some View {
+ VStack {
-  Text("Hello, World!")
+  Text("Welcome to MyApp")
+     .font(.title) //字体大小
+      .fontWeight(.semibold) // 加粗
+  Text("Description text").font(.title2)
+ }
}
image.png

添加.border属性我们能更好调试UI样式

// WelcomePage
 VStack {
  Text("Welcome to MyApp")
    .font(.title) //字体大小
     .fontWeight(.semibold) // 加粗
+    .border(.black, width: 1.5)
  Text("Description text").font(.title2)
+    .border(.black, width: 1.5) 
 }
+ .border(.orange, width: 1.5)
+ .padding() 
+ .border(.purple, width: 1.5)
image.png

为了显示欢迎的icon图,这里添加个圆角frame RoundedRectangle

// WelcomePage
 VStack {
+  RoundedRectangle(cornerRadius: 30) // 圆角30
+  .frame(width: 150, height: 150)  // 宽高 150
+  .foregroundStyle(.tint)  // 背景蓝色
   ....
image.png

Padding设置标题边距

现在看效果标题位置有点拥挤,可以给标题添加边距 .padding(.top)

// WelcomePage
 VStack {
  Text("Welcome to MyApp")
    .font(.title) //字体大小
     .fontWeight(.semibold) // 加粗
+     .padding(.top) // 添加边距
    .border(.black, width: 1.5)
image.png

这样看效果是不是更好了呢?也可以单独添加不同方向的边距,我们可以在XCode查看Padding文档

image.png

点击EdgeInsets查看具体参数:

image.png

有兴趣的同学可以试着使用

ZStack 嵌入字体图标

现在需要再蓝色背景添加个icon,需要使用到ZStack它可以使 views叠加在另一个上

// WelcomePage
 VStack {
+   ZStack { 
     RoundedRectangle(cornerRadius: 30)
       .frame(width: 150, height: 150)
       .foregroundStyle(.tint) 
+       Image(systemName: "figure.2.and.child.holdinghands") // 添加个icon 图片
+      .font(.system(size: 70)) // icon size 70
+       .foregroundStyle(.white)  // icon 背景白色
+ }

最后把之前用来调试的边框.border去掉

image.png

大致完成了欢迎页的第一张图

创建FeaturesPage

创建功能介绍主页

// FeaturesPage

import SwiftUI 
struct FeaturesPage: View { 
   var body: some View { 
       VStack { 
           Text("Features")
             .font(.title)
             .fontWeight(.semibold) 
       } 
             .padding()
   }
} 

#Preview { 
  FeaturesPage() 
}
image.png

创建FeatureCard

创建功能介绍卡片,自定义传参iconName,description

// FeatureCard

import SwiftUI 
struct FeatureCard: View {
    let iconName: String 
    let description: String 
    
    var body: some View { 
      HStack { // 水平方向
        Image(systemName: iconName).font(.largeTitle) 
        Text(description)
      }
      .padding()
      .background(.tint, in: RoundedRectangle(cornerRadius: 12)) // card背景颜色
      .foregroundStyle(.white) // card 字体颜色
    } 
} 

#Preview {
   // 调用FeatureCard传入参数
   FeatureCard(
   iconName: "person.2.crop.square.stack.fill",
   description: "A multiline description about a feature paired with the image on the left.") 
   }
image.png

这里使用到了struct自定义传参,在ios入门实例(二)中有提到

FeaturesPage 中调用FeatureCard

在FeaturesPage页面中自定义传参调用FeatureCard

// FeaturesPage

import SwiftUI 
struct FeaturesPage: View { 
   var body: some View { 
       VStack { 
           Text("Features")
             .font(.title)
             .fontWeight(.semibold) 
+            .padding(.bottom) // 添加个边距
+             FeatureCard(
+             iconName: "person.2.crop.square.stack.fill",
+             description: "A multiline description about a feature paired with the +image on the left.")
       } 
             .padding()
   }
} 

#Preview { 
  FeaturesPage() 
}
image.png

再新增个FeatureCard

// FeaturesPage

   FeatureCard(
     iconName: "person.2.crop.square.stack.fill",
     description: "A multiline description about a feature paired with the image on the left.")

+ FeatureCard(iconName: "quote.bubble.fill", description: "Short summary")
image.png

由效果图可以看到第二个 FeatureCard width方法没有填充满,可以使用Spacer进行拉伸水平方向

// FeatureCard
   ...
      HStack { // 水平方向
        Image(systemName: iconName).font(.largeTitle) 
        Text(description)
+        Spacer()
   ...
image.png

虽然填充好了但icon图宽度不一致通过设置 .frame来解决

// FeatureCard
   ...
      HStack { // 水平方向
        Image(systemName: iconName).font(.largeTitle) 
+        .frame(width: 50)
+        .padding(.trailing, 10)
   ...
image.png

TabView 滑动切换Page

修改主入口ContentView.swift代码

// ContentView.swift

 import SwiftUI struct ContentView: View {
        var body: some View {
+           TabView { 
+             WelcomePage() 
+             FeaturesPage() 
+           } 
+           .tabViewStyle(.page)  // 左右切换
        } 
} 

#Preview { 
  ContentView() 
}
file.gif

TabView左右切换是有spot样式,由于与背景都为白色所以看不出来,接下来开始设置背景

配置主题颜色&&设置背景

通过配置主题用来设置Page背景颜色,丰富轮播图视觉

配置主题GradientTop颜色步骤:

image.png image.png image.png

创建成功后点击Any Appearance白色背景块开始配置,色值:Red 0.852, Green 0.646, Blue 0.847

image.png image.png

同样步骤配置GradientBottom,色值:Red 0.954, Green 0.529, Blue 0.385

image.png

主题颜色配置好后,我们可以开始配置ContentView.swift 背景颜色了,全局声明主题颜色

// ContentView.swift

+ // 全局声明主题颜色
+ let gradientColors: [Color] =  
+  [ 
+    .gradientTop,
+    .gradientBottom 
+  ]
   ....
           TabView { 
             WelcomePage() 
             FeaturesPage() 
          } 
+           .background(Gradient(colors: gradientColors))


file2.gif

FeaturesPage 样式微调

切换到FeaturesPage代码,Preview预览中添加全局主题颜色

// FeaturesPage

#Preview { 
  FeaturesPage()
+  .background(Gradient(colors: gradientColors))
+  .foregroundStyle(.white)
}
image.png

从样式中看主体内容没有撑满全屏,需要设置 maxHeight 为 .infinity

// FeaturesPage

#Preview { 
  FeaturesPage()
+  .frame(maxHeight: .infinity)
  .background(Gradient(colors: gradientColors))
  .foregroundStyle(.white)
}
image.png

接下来padding,VStack,Spacer微调

// FeaturesPage

import SwiftUI 
struct FeaturesPage: View { 
   var body: some View { 
-       VStack { 
+       VStack(spacing: 30) { 
           Text("Features")
             .font(.title)
             .fontWeight(.semibold) 
            .padding(.bottom) 
+           .padding(.top, 100)// 顶部边距 100
             FeatureCard(
             iconName: "person.2.crop.square.stack.fill",
            description: "A multiline description about a feature paired with the image on the left.")
+            Spacer() // 填充空白使内容往顶部靠拢
       } 
             .padding()
   }
} 

#Preview { 
  FeaturesPage() 
}
image.png

FeaturesCard 样式微调

主要使用opacity,brightness增加透明效果

// FeatureCard

    var body: some View { 
      ...
     .background(
-       .tint, in: RoundedRectangle(cornerRadius: 12)
+        RoundedRectangle(cornerRadius: 12) // 圆角
+           .foregroundStyle(.tint) // 背景
+           .opacity(0.25) // 透明度
+           .brightness(-0.4)   // 亮度调整
       ) 

      .foregroundStyle(.white) // card 字体颜色
    }

brightness 属性,它允许你获取或设置屏幕的亮度。这个值的范围是 0.0(最暗)到 1.0(最亮)。

最终效果:

image.png