6

我正在尝试在 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")
                }
        }
    
    }
}

有谁知道如何做到这一点?我会很感激你的帮助:)

4

2 回答 2

7

简短的回答

我找到了解决方案。您可以创建自己的阴影图像并将其添加到 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

设置 shadowImage

我想以编程方式生成阴影图像。为此,我创建了 UIImage 的扩展。(代码取自这里

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

结果

在此处输入图像描述

于 2021-03-28T08:58:30.753 回答
2

为了实现您所希望的,您最好的选择是创建一个自定义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()
            
        }
    }
    
}

请记住,当您执行此操作时,您的所有选项卡都被指定为 内的 case 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()

当我在中调用TabViewfrom时,我添加了阴影ContentView,但您甚至可以在自身.shadow(radius: 10)之后添加。HStackTabView

这将是最终输出

                 在此处输入图像描述

于 2021-03-26T20:28:12.827 回答