【问题标题】:How to apply shadow to interior views in SwiftUI?如何在 SwiftUI 中将阴影应用于内部视图?
【发布时间】:2019-10-24 09:50:35
【问题描述】:

我在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)
}

【问题讨论】:

  • 一个视图的子视图继承父视图的影子对我来说似乎是一个错误
  • @ielyamani 不,这不是错误,有解决方案

标签: swift swiftui


【解决方案1】:

你好,我现在只使用这个,但它的目的是 - 让我有内在的阴影。

通过一些修改,你可以拥有你想要的。

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)
    }

}

【讨论】:

    【解决方案2】:

    为此有一个专用修饰符 - 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)
    

    【讨论】:

      【解决方案3】:

      对于为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
         )
      )
      

      阴影应用于.backgroundRoundedRectagle元素shadow

      虽然相当冗长,但易于阅读,并且可以将相同的原理应用于任何其他形状。

      【讨论】:

        【解决方案4】:

        您可以在此处使用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)
        

        输出:

        希望对你有帮助:)

        【讨论】:

        • 即使你没有解释它,这个 hack 仍然有效。然而,这并不是苹果给clipped() 的定义。阴影修饰符的继承对我来说似乎仍然是一个错误。
        • @ielyamani 这就是 VStack 和 HStack 的工作方式。如果您向 VStack 提供任何修饰符,它将自动应用于它的子项。如果 Text 没有它自己的 foregroundColor(),像 foregroundColor(Color.red) 这样会使 VStack 中的所有 Text 变为红色
        • 仍然没有解释为什么 VStack 有影子而它的子节点没有
        • 它对我不起作用。我仍然在孩子们周围留下阴影。
        • .clipped() 对我也没有帮助,它仍然将.shadow 应用于每个嵌套视图。
        【解决方案5】:

        对我来说,将阴影应用于背景而不是堆栈也很有效,例如:

        VStack {
          // ...
        }.background(Rectangle().fill(Color.white).shadow(radius: 8))
        

        【讨论】:

        • 您可以只使用简单的Color.white 而不是Rectangle().fill(Color.white) 来创建一个彩色矩形?
        • 这是正确答案。使用clipped() 对具有拐角半径的子视图造成了奇怪的影响
        • 使用 clipped() 在使用偏移量时也给我带来了问题
        【解决方案6】:

        您可以通过使用ZStackVStack 后面放置RectangleCapsuleCircle 或其他形状来解决此问题。然后将修改器应用于形状而不是 VStack 本身。

        ZStack() {
            Capsule()
                .frame(width: 50, height: 50)
                .background(Color.white)
                .shadow(radius: 10)
        
            VStack() {
                //...
            }
        }
        

        对我来说似乎是一个非常烦人的功能,很多时候您希望在容器上添加阴影而不将其应用于所有元素。

        如果有人知道更好的方法,请分享,谢谢!

        【讨论】:

        • 我从未见过将阴影应用到所有孩子的用例,因此您可以在阴影上添加阴影。但也许有。
        猜你喜欢
        • 2020-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-25
        • 2012-01-11
        • 1970-01-01
        • 2022-06-20
        • 1970-01-01
        相关资源
        最近更新 更多