SwiftUI 学习笔记(七):常见的 View 和 Modifier 解析(六)

background()

background 为背景修饰符,可以添加某个 View 的背景颜色(不是 View 本身的颜色)或者形状。

//添加背景色
struct ContentView: View {
    
    var body: some View {
        Text("背景色")
            .padding()
            .background(Color.red)
    }
}

//添加形状
struct ContentView: View {
    
    var body: some View {
        Text("形状背景").foregroundColor(.white).padding()
            .background(
                RoundedRectangle(cornerRadius: 10)
                    .foregroundColor(.red)
                    .frame(height:60)
        )
    }
}

cornerRadius()、border()

在 UIKit 中我们常常会设置某个 View 的圆角和边框,在 SwiftUI 中使用 cornerRadius 和 border 修饰符即可。

struct ContentView: View {
    
    var body: some View {
        Text("圆角和边框")
            .padding()
            .background(Color.blue)
            .cornerRadius(25) //圆角
            .border(Color.green, width: 4) //边框
    }
}

shadow()

shadow 用于给 View 设置阴影。

struct ContentView: View {
    
    var body: some View {
        Text("阴影")
            .shadow(color: .red, radius: 5, x: 0, y: 0)
    }
}

若我们给 VStack 或 HStack 设置,里面所有的内容都会有阴影。可以给它们的 background 设置颜色或阴影,此时阴影只对 background 起作用。

struct ContentView: View {
    
    var body: some View {
        VStack {
            Text("阴影")
            Text("阴影")
            Text("阴影")
        }
        .padding()
        .background(Color.white.shadow(color: .red, radius: 5))
    }
}

实际项目中经常会出现卡片样式的圆角阴影,这种需要设置一下偏移。

struct ContentView: View {
    
    var body: some View {
        VStack {
            Text("卡片样式阴影")
                .font(.system(size: 20))
        }
        .padding()
        .background(Color.white )
        .cornerRadius(10)
        .shadow(radius: 5, y: 2)
    }
}

gradient()

gradient 为渐变色,一般作为背景使用。主要有三种渐变色:LinderGradient(线性渐变)、RadialGradient(径向渐变)、AngularGradient(角度渐变)。

struct ContentView: View {
    
    let gradient = Gradient(colors: [.red, .green])
    
    var body: some View {
        VStack {
            // LinderGradient
            RoundedRectangle(cornerRadius: 10)
                .fill(LinearGradient(gradient: gradient, startPoint: .leading, endPoint: .trailing))
                .frame(height:60)
                .padding()
            // RadialGradient
            RoundedRectangle(cornerRadius: 10)
                .fill(RadialGradient(gradient: gradient, center: .center,
                                     startRadius: 20, endRadius: 200))
                .frame(height:60)
                .padding()
            // AngularGradient
            Circle()
                .fill(AngularGradient(gradient: Gradient(colors: [.red, .yellow, .green, .blue, .purple, .red]), center: .center))
                .frame(height:120)
                .padding()
        }
    }
}

下面的例子将渐变色作为了按钮的背景。

struct ContentView: View {
    
    var body: some View {
        Button(action: {
        }) {
            Text("删除")
                .font(.title)
                //与屏幕一样宽
                .frame(minWidth: 0, maxWidth: .infinity)
                .padding()
                .background(LinearGradient(
                    gradient: Gradient(colors: [.red, .green]),
                    startPoint: .leading, endPoint: .trailing))
                .cornerRadius(40)
        }
    }
}

stroke() 与 strokeBorder()

stroke 与 strokeBorder 两个修饰符都是用于在形状周围绘制边框,其中 stroke 绘制的边框在 View 内部,strokeBorder 绘制的边框一半在 View 的内部,一半在外部。

需要注意,这两个修饰符仅适用于 Shape 而不能与其他非 Shape 的 View 一起使用,否则应改用 border。

//实现Shape的边框
struct ContentView: View {
    
    let gradient = Gradient(colors: [.orange, .red])
    
    var body: some View {
        ZStack {
            //直接用border圆角不会出现
            RoundedRectangle(cornerRadius: 10)
                .stroke(Color.green, style: StrokeStyle(lineWidth: 4))
                .frame(height:60)
            
            RoundedRectangle(cornerRadius: 10)
                .fill(LinearGradient(gradient: gradient, startPoint: .leading, endPoint: .trailing))
                .frame(height:60)
        }.padding()
    }
}
//制作环形
struct ContentView: View {
    
    var body: some View {
        Circle()
            .strokeBorder(Color.blue, lineWidth: 50)
    }
}
//实现图片“边框”
struct ContentView: View {
    
    let gradient = Gradient(colors: [.purple, .blue])
    
    var body: some View {
        Image(systemName: "clock")
            .resizable()
            .aspectRatio(contentMode: .fill)
            .frame(width: 80, height: 80)
            .clipShape(Circle()) // 通常操作是clipShape后overlay里面stroke
            .overlay(Circle()
                .stroke(LinearGradient(gradient: Gradient(colors: [.purple, .blue]), startPoint: .top, endPoint: .bottom), lineWidth: 2.0)
        )
    }
}

offset()

offset 修饰符可以设置 x 与 y 两个方向的相对于原位置的偏移而不会影响其他的元素,常用于 View 位置的微调。

struct ContentView: View {
    
    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 20)
                .foregroundColor(Color.green)
                .frame(width: 300, height: 100)
                .offset(x: -20, y: -20)
            
            RoundedRectangle(cornerRadius: 20)
                .foregroundColor(Color.red)
                .frame(width: 300, height: 100)
            
            RoundedRectangle(cornerRadius: 20)
                .foregroundColor(Color.purple)
                .frame(width: 300, height: 100)
                .offset(x: 20, y: 20)
        }
    }
}

position()

SwiftUI 推荐使用弹性盒子布局,但也支持设置 position 进行绝对定位。坐标参考系为其所在的容器(和 UIKit 的 frame 类似)。

struct ContentView: View {
    
    var body: some View {
        // Text放置在(100, 100)的位置
        Text("SwiftUI")
            .border(Color.red)
            .position(x: 100, y: 100)
    }
}

overlay()

overlay 用于在某个 View 前面放置一个辅助 View。

与 background的区别:在 View前面添加用 overlay,在 View后面添加用 background。

这个辅助 View 默认是居中显示的,可以通过 alignment 参数设置显示在 View 的位置。

struct ContentView: View {
    
    var body: some View {
        VStack() {
            Spacer()
        }
        .frame(maxWidth: .infinity)
        .frame(height: 300)
        .background(Color.pink)
        .clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous)) //裁成圆角矩形
            .padding(.horizontal, 30) //左右两边有边距
            .overlay( //前面放一个圆形图片
                Image("img")
                    .resizable()
                    .frame(width: 60, height: 60)
                    .clipShape(Circle())
                    .offset(y: -150)
        )
    }
}

mask()

mask 为遮罩,常用于某个 View 遮罩另外一个 View 从而产生特殊的视觉效果。

//渐变文本
struct ContentView: View {
    
    let text = Text("SwiftUI")
        .font(.system(size: 50))
    
    var body: some View {
        text
            .overlay(LinearGradient(gradient: Gradient(colors: [.orange, .blue]), startPoint: .leading, endPoint: .trailing))
            .mask(text)
    }
}
//文字图片融合
struct ContentView: View {
    
    let text = Text("Steve Jobs")
        .font(.system(size: 40))
    
    var body: some View {
        text
            .overlay(Image("jobs"))
            .mask(text)
    }
}
//图片与图片融合
struct ContentView: View {
    
    var body: some View {
        Image(systemName: "hare")
            .resizable()
            .scaledToFit()
            .frame(width:100, height: 100)
            .overlayMask(Image("jobs"))
    }
}

extension View {
    //自定义一个函数利用overlay产生mask
    public func overlayMask<T: View>(_ overlay: T) -> some View {
        self
            .overlay(overlay)
            .mask(self)
    }
}

blur()

用于设置毛玻璃效果。

struct ContentView: View {
    
    var body: some View {
        VStack {
            Image("jobs")
                .resizable()
                .frame(width: 300, height: 300)
                .blur(radius: 20)
            Text("乔布斯")
                .blur(radius: 2)
        }
    }
}

accentColor()

accentColor 类似于 UIKit 中的 tintColor,可以设置按钮渲染的颜色。

struct ContentView: View {
    
    var body: some View {
        VStack {
            Text("Hello SwiftUI")
            
            Button("按钮") {
            }
        }.accentColor(.orange) //按钮被渲染为橘色
    }
}

edgesIgnoringSafeArea()

使用 edgesIgnoringSafeArea 可以忽略安全区域,常用于设置全屏 View。

struct ContentView: View {
    
    var body: some View {
        Image("bg")
            .resizable()
            .scaledToFill()
            .edgesIgnoringSafeArea(.all)
    }
}

状态栏显隐

在某些场景下,我们可能需要隐藏状态栏(例如视频播放、游戏界面等),可以通过设置 .statusBar(hidden: )解决。

//始终隐藏状态栏
struct ContentView: View {
    
    var body: some View {
        Text("Hello SwiftUI")
            .statusBar(hidden: true)
    }
}
//点击按钮切换状态栏隐藏、显示状态
struct ContentView: View {
    
    @State var hideStatusBar = false
    
    var body: some View {
        Button("状态栏切换") {
            self.hideStatusBar.toggle()
        }
        .statusBar(hidden: hideStatusBar)
    }
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注