SwiftUI自定义导航栏

1. 导航栏组件的尺寸

public struct HDSizeHook: PreferenceKey, ViewModifier {
    public static var defaultValue: CGSize = .zero
    public static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
        value = nextValue()
    }
    
    @Binding var value: CGSize
    @State var sValue: CGSize = .zero
    var onChanged: ((CGSize) -> Void)?
    
    public init(value: Binding<CGSize>) {
        self._value = value
    }
    
    public init(_ changed: @escaping (CGSize) -> Void) {
        self._value = .constant(.zero)
        self.onChanged = changed
    }
    
    public func body(content: Content) -> some View {
        content.background(
            GeometryReader { rp in
                Color.clear
                    .preference(key: HDSizeHook.self, value: rp.size)
                    .onPreferenceChange(HDSizeHook.self) { value in
                        self.value = value
                        onChanged?(value)
                    }
            }
        )
    }
}

2. 各组件的布局方法

public struct HDNavigationView<Content>: View where Content: View {
    @State var maxItemWidth: CGFloat = 0
    
    let content: () -> Content
    var title: String = ""
    
    var leftItems: () -> AnyView = {
        AnyView(
            Image(.back)
                .padding(.horizontal, 15)
                .padding(.vertical, 10)
                .background(Color(.kTheme239()))
                .onTapGesture {
                    Router.pop()
                }
        )
        
    }
    var rightItems: () -> AnyView = {
        AnyView(EmptyView())
    }
    
    public init(@ViewBuilder content: @escaping () -> Content) {
        self.content = content
    }
    
    public var body: some View {
        GeometryReader { proxy in
            VStack(spacing: 0) {
                HStack(spacing: 0) {
                    HStack {
                        leftItems()
                    }
                    .modifier(HDSizeHook{ value in
                        maxItemWidth = max(maxItemWidth, value.width)
                    })
                    .frame(minWidth: maxItemWidth, alignment: .leading)
                    Spacer()
                    Text(title)
                        .multilineTextAlignment(.center)
                    Spacer()
                    HStack {
                        rightItems()
                    }
                    .modifier(HDSizeHook{ value in
                        maxItemWidth = max(maxItemWidth, value.width)
                    })
                    .frame(minWidth: maxItemWidth, alignment: .trailing)
                }
                .frame(width: proxy.size.width, height: 44)
                .background(Color(.kTheme239()).edgesIgnoringSafeArea(.top))
                .foregroundColor(.white)
                .font(.system(size: 18))
                content()
            }
        }
    }
    
    public func navigationTitle(_ title: String) -> Self {
        var view = self
        view.title = title
        return view
    }
    
    public func navigationLeftItems<LeftContent>(@ViewBuilder items: @escaping () -> LeftContent) -> Self where LeftContent: View {
        var view = self
        view.leftItems = {
            AnyView(items())
        }
        return view
    }
    
    public func navigationRightItems<RightContent>(@ViewBuilder items: @escaping () -> RightContent) -> Self where RightContent: View {
        var view = self
        view.rightItems = {
            AnyView(items())
        }
        return view
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容