如何将阴影应用于 SwiftUI 中的内部视图?
How to apply shadow to interior views in SwiftUI?
我在 VStack
周围添加了一个阴影,它包含我的两个文本字段和一个提交按钮。但是,阴影也应用于 VStack
内的两个文本字段。
是不是我遗漏了什么导致了这种情况的发生?我尝试在文本字段上添加 shadow(radius: 0)
,但它没有任何改变。如果我从文本字段中删除填充和背景,那么阴影就会消失。
var body: some View {
VStack() {
Spacer()
VStack() {
TextField($email, placeholder: Text("email"))
.padding()
.background(Color(red: 242 / 255, green: 242 / 255, blue: 242 / 255))
SecureField($password, placeholder: Text("password"))
.padding()
.background(Color(red: 242 / 255, green: 242 / 255, blue: 242 / 255))
Button(action: { self.login() }, label: { Text("Login").foregroundColor(Color.white) })
.padding()
.background(Color(red: 0, green: 116 / 255, blue: 217 / 255))
}
.padding()
.background(Color.white)
.shadow(radius: 10)
Spacer()
}
.padding()
.background(Color(red: 0, green: 116 / 255, blue: 217 / 255))
.edgesIgnoringSafeArea(.all)
}
您可以在此处使用 clipped()
来解决此问题
VStack() {
Text("Text")
.background(Color.red)
.padding()
.padding()
Text("Text")
.background(Color.purple)
.padding()
}
.padding()
.background(Color.white)
.clipped()
.shadow(color: Color.red, radius: 10, x: 0, y: 0)
输出:
希望对您有所帮助:)
您可以通过使用 ZStack
在 VStack
后面放置 Rectangle
、Capsule
、Circle
或其他形状来解决此问题。然后将修改器应用于形状而不是 VStack 本身。
ZStack() {
Capsule()
.frame(width: 50, height: 50)
.background(Color.white)
.shadow(radius: 10)
VStack() {
//...
}
}
对我来说这似乎是一个非常烦人的功能,很多时候您想要在容器上添加阴影而不是将其应用于所有元素。
如果谁知道更好的方法请分享,谢谢!
对我来说,它也可以将阴影应用于背景而不是堆栈,例如:
VStack {
// ...
}.background(Rectangle().fill(Color.white).shadow(radius: 8))
对于正在为 RoundedRectangle
努力工作的用户,请使用:
HStack {
// Your nested views
}
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.black.opacity(0.2), lineWidth: 1)
)
.background(
RoundedRectangle(
cornerRadius: 10
)
.foregroundColor(Color.white)
.shadow(
color: Color.black,
radius: 5,
x: 0,
y: 0
)
)
阴影应用于 .background
、RoundedRectagle
元素 shadow
。
虽然很冗长,但很容易阅读,同样的原则可以应用于任何其他形状。
为此有一个专用修饰符 - compositingGroup
。
来自文档:
/// Wraps this view in a compositing group.
///
/// A compositing group makes compositing effects in this view's ancestor
/// views, such as opacity and the blend mode, take effect before this view
/// is rendered.
/// [...]
/// This limits the scope of [...] change to the outermost view.
VStack {
Text("Text")
.background(Color.red)
.padding()
.padding()
Text("Text")
.background(Color.purple)
.padding()
}
.padding()
.background(Color.white)
.compositingGroup()
.shadow(color: Color.red, radius: 10, x: 0, y: 0)
你好,我目前只使用这个,但它达到了它的目的 - 让我有内阴影。
稍加修改即可得到你想要的。
private struct InnerShadow: ViewModifier {
func body(content: Content) -> some View {
HStack(spacing: .zero) {
verticalLine().offset(x: -1)
VStack(spacing: .zero) {
horizontalLine().offset(y: -1)
content
horizontalLine().offset(y: 1)
}
verticalLine().offset(x: 1)
}
}
private func verticalLine() -> some View {
Rectangle()
.foregroundColor(.white)
.frame(maxWidth: 1, maxHeight: .infinity)
.shadow(radius: 4)
}
private func horizontalLine() -> some View {
Rectangle()
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: 1)
.shadow(radius: 4)
}
}
在某些情况下,使用 .clipped()
(如其他一些答案所建议的那样)可能会导致一些不受欢迎的 side-effects。使用 .background()
绘制额外的视图并给出阴影是低效的(在计算方面)且乏味。
最好的方法是在您的 VStack 上调用 .compositingGroup()
。看起来像这样:
VStack {
// Some inner views
}
.compositingGroup()
来自 Apple 开发者文档的 this page:
A compositing group makes compositing effects in this view’s ancestor views, such as opacity and the blend mode, take effect before this view is rendered.
因为视图及其子视图合成为一个 View
,任何应用于它的阴影都不会传播到子视图。
我在 VStack
周围添加了一个阴影,它包含我的两个文本字段和一个提交按钮。但是,阴影也应用于 VStack
内的两个文本字段。
是不是我遗漏了什么导致了这种情况的发生?我尝试在文本字段上添加 shadow(radius: 0)
,但它没有任何改变。如果我从文本字段中删除填充和背景,那么阴影就会消失。
var body: some View {
VStack() {
Spacer()
VStack() {
TextField($email, placeholder: Text("email"))
.padding()
.background(Color(red: 242 / 255, green: 242 / 255, blue: 242 / 255))
SecureField($password, placeholder: Text("password"))
.padding()
.background(Color(red: 242 / 255, green: 242 / 255, blue: 242 / 255))
Button(action: { self.login() }, label: { Text("Login").foregroundColor(Color.white) })
.padding()
.background(Color(red: 0, green: 116 / 255, blue: 217 / 255))
}
.padding()
.background(Color.white)
.shadow(radius: 10)
Spacer()
}
.padding()
.background(Color(red: 0, green: 116 / 255, blue: 217 / 255))
.edgesIgnoringSafeArea(.all)
}
您可以在此处使用 clipped()
来解决此问题
VStack() {
Text("Text")
.background(Color.red)
.padding()
.padding()
Text("Text")
.background(Color.purple)
.padding()
}
.padding()
.background(Color.white)
.clipped()
.shadow(color: Color.red, radius: 10, x: 0, y: 0)
输出:
希望对您有所帮助:)
您可以通过使用 ZStack
在 VStack
后面放置 Rectangle
、Capsule
、Circle
或其他形状来解决此问题。然后将修改器应用于形状而不是 VStack 本身。
ZStack() {
Capsule()
.frame(width: 50, height: 50)
.background(Color.white)
.shadow(radius: 10)
VStack() {
//...
}
}
对我来说这似乎是一个非常烦人的功能,很多时候您想要在容器上添加阴影而不是将其应用于所有元素。
如果谁知道更好的方法请分享,谢谢!
对我来说,它也可以将阴影应用于背景而不是堆栈,例如:
VStack {
// ...
}.background(Rectangle().fill(Color.white).shadow(radius: 8))
对于正在为 RoundedRectangle
努力工作的用户,请使用:
HStack {
// Your nested views
}
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.black.opacity(0.2), lineWidth: 1)
)
.background(
RoundedRectangle(
cornerRadius: 10
)
.foregroundColor(Color.white)
.shadow(
color: Color.black,
radius: 5,
x: 0,
y: 0
)
)
阴影应用于 .background
、RoundedRectagle
元素 shadow
。
虽然很冗长,但很容易阅读,同样的原则可以应用于任何其他形状。
为此有一个专用修饰符 - compositingGroup
。
来自文档:
/// Wraps this view in a compositing group.
///
/// A compositing group makes compositing effects in this view's ancestor
/// views, such as opacity and the blend mode, take effect before this view
/// is rendered.
/// [...]
/// This limits the scope of [...] change to the outermost view.
VStack {
Text("Text")
.background(Color.red)
.padding()
.padding()
Text("Text")
.background(Color.purple)
.padding()
}
.padding()
.background(Color.white)
.compositingGroup()
.shadow(color: Color.red, radius: 10, x: 0, y: 0)
你好,我目前只使用这个,但它达到了它的目的 - 让我有内阴影。
稍加修改即可得到你想要的。
private struct InnerShadow: ViewModifier {
func body(content: Content) -> some View {
HStack(spacing: .zero) {
verticalLine().offset(x: -1)
VStack(spacing: .zero) {
horizontalLine().offset(y: -1)
content
horizontalLine().offset(y: 1)
}
verticalLine().offset(x: 1)
}
}
private func verticalLine() -> some View {
Rectangle()
.foregroundColor(.white)
.frame(maxWidth: 1, maxHeight: .infinity)
.shadow(radius: 4)
}
private func horizontalLine() -> some View {
Rectangle()
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: 1)
.shadow(radius: 4)
}
}
在某些情况下,使用 .clipped()
(如其他一些答案所建议的那样)可能会导致一些不受欢迎的 side-effects。使用 .background()
绘制额外的视图并给出阴影是低效的(在计算方面)且乏味。
最好的方法是在您的 VStack 上调用 .compositingGroup()
。看起来像这样:
VStack {
// Some inner views
}
.compositingGroup()
来自 Apple 开发者文档的 this page:
A compositing group makes compositing effects in this view’s ancestor views, such as opacity and the blend mode, take effect before this view is rendered.
因为视图及其子视图合成为一个 View
,任何应用于它的阴影都不会传播到子视图。