在 SwiftUI 的 TabView 上方添加阴影

Add shadow above SwiftUI's TabView

我正在尝试在 SwiftUI 中实现 TabView,它具有与屏幕背景相同的颜色,但在其上方也有一个 阴影,如下图所示:

到目前为止我已经能够正确显示颜色,但我不知道如何添加阴影。这是我的代码:

struct ContentView: View {
    
    init() {
        let appearance = UITabBarAppearance()
        appearance.configureWithTransparentBackground()

        UITabBar.appearance().standardAppearance = appearance
    }
    
    var body: some View {
        TabView {
            Text("First View")
                .tabItem {
                    Image(systemName: "square.and.arrow.down")
                    Text("First")
                }
            Text("Second View")
                .tabItem {
                    Image(systemName: "square.and.arrow.up")
                    Text("Second")
                }
        }
    
    }
}

有人知道怎么做吗?非常感谢您的帮助:)

为了完全实现您的愿望,您最好的选择是创建自定义 TabView

事实上,在 SwiftUI 中,您可以使用 UITabBarAppearance().shadowColor,但除了在 TabView 本身的顶部绘制一条 2px 的线外,这不会做太多事情。

相反,使用以下代码,您可以创建自定义 TabView 并实现所需的图形效果。

import SwiftUI


enum Tab {
    case borrow,ret,device,you
}

struct TabView: View {
    @Binding var tabIdx: Tab
    
    var body: some View {
        HStack {
            Group {
                Spacer()
                
                Button (action: {
                    self.tabIdx = .borrow
                }) {
                    VStack{
                        Image(systemName: "arrow.down.circle")
                        Text("Borrow")
                            .font(.system(size: 10))
                        
                    }
                }
                .foregroundColor(self.tabIdx == .borrow ? .purple : .secondary)
                
                Spacer()
                
                Button (action: {
                    self.tabIdx = .ret
                }) {
                    VStack{
                        Image(systemName: "arrow.up.circle")
                        Text("Return")
                            .font(.system(size: 10))
                        
                    }
                }
                .foregroundColor(self.tabIdx == .ret ? .purple : .secondary)
                
                Spacer()
                
                Button (action: {
                    self.tabIdx = .device
                }) {
                    VStack{
                        Image(systemName: "safari")
                        Text("Device")
                            .font(.system(size: 10))
                        
                    }
                }
                .foregroundColor(self.tabIdx == .device ? .purple : .secondary)
                
                Spacer()
                
                Button (action: {
                    self.tabIdx = .you
                }) {
                    VStack{
                        Image(systemName: "person.circle")
                        Text("You")
                            .font(.system(size: 10))
                        
                    }
                }
                .foregroundColor(self.tabIdx == .you ? .purple : .secondary)
                
                Spacer()
            }
        }
        .padding(.bottom, 30)
        .padding(.top, 10)
        .background(Color(red: 0.95, green: 0.95, blue: 0.95))
        .font(.system(size: 30))
        .frame(height: 80)
    }
}


struct ContentView: View {
    @State var tabIdx: Tab = .borrow
    
    var body: some View {
        NavigationView {
            VStack(spacing: 20) {
                Spacer()
                
                if tabIdx == .borrow {
                    Text("Borrow")
                } else if tabIdx == .ret {
                    Text("Return")
                } else if tabIdx == .device {
                    Text("Device")
                } else if tabIdx == .you {
                    Text("You")
                }
                Spacer(minLength: 0)
                TabView(tabIdx: self.$tabIdx)
                    .shadow(radius: 10)
            }
            .ignoresSafeArea()
            
        }
    }
    
}

请记住,当您执行此操作时,所有选项卡都指定为 enum Tab {} 内的大小写,并且 TabView() 包含一些 Button 元素,这将通过使用@State var tabIdx。所以你可以通过修改self.tabIdx = <yourtab>语句来调整你的动作。

活动颜色在每个按钮后使用此语句设置:

.foregroundColor(self.tabIdx == .borrow ? .purple : .secondary)

在这里你可以把.purple改成适合你的。

您可以看到在 ContentView 上,if-else if 块捕获了 SubView。我在这里放置了一些 Text() 元素,例如 Text("Borrow"),因此您可以通过调用 BorrowView() 或任何您拥有的东西来替换它们。

我在 ContentView 中调用 TabView 时添加了阴影,但您甚至可以在 HStack 之后添加 .shadow(radius: 10) 12=]本身。

这将是最终输出:

简答

我找到了解决办法。您可以创建自己的阴影图像并将其添加到 UITabBar 外观,如下所示:

// load your custom shadow image
let shadowImage: UIImage = ...

//you also need to set backgroundImage, without it shadowImage is ignored
UITabBar.appearance().backgroundImage = UIImage()
UITabBar.appearance().shadowImage = shadowImage

更详细的回答

设置背景图片

注意通过设置

UITabBar.appearance().backgroundImage = UIImage()

您将 TabView 设为透明,因此如果您的内容可以在其下方滚动则不太理想。为了克服这个问题,您可以设置 TabView 的颜色。

let appearance = UITabBarAppearance()
appearance.configureWithTransparentBackground()
appearance.backgroundColor = UIColor.systemGray6
UITabBar.appearance().standardAppearance = appearance

设置阴影图像

我想以编程方式生成阴影图像。为此,我创建了 UIImage 的扩展。 (code taken from here)

extension UIImage {
    static func gradientImageWithBounds(bounds: CGRect, colors: [CGColor]) -> UIImage {
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = bounds
        gradientLayer.colors = colors
        
        UIGraphicsBeginImageContext(gradientLayer.bounds.size)
        gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image!
    }
}

最后我将我的 TabView 设计成这样:

let image = UIImage.gradientImageWithBounds(
    bounds: CGRect( x: 0, y: 0, width: UIScreen.main.scale, height: 8),
    colors: [ 
        UIColor.clear.cgColor, 
        UIColor.black.withAlphaComponent(0.1).cgColor
    ]
)

let appearance = UITabBarAppearance()
appearance.configureWithTransparentBackground()
appearance.backgroundColor = UIColor.systemGray6
        
appearance.backgroundImage = UIImage()
appearance.shadowImage = image

UITabBar.appearance().standardAppearance = appearance

结果