简体   繁体   English

如何实现自定义视图修饰符

[英]How to implement a custom view modifier

To be clear, i'm not asking how to use the ViewModifier protocol to create a struct with the body function that can then be used to modify a view.需要明确的是,我不是在问如何使用 ViewModifier 协议来创建一个带有主体 function 的结构,然后可以使用它来修改视图。 This question is a little bit different.这个问题有点不同。

I'm trying to create a reusable alternative to the NavigationView struct, which has been mostly successful using @Viewbuilder to enable trailing closure syntax which enables me to use the view i've named 'NavBarView' like this:我正在尝试创建 NavigationView 结构的可重用替代方案,该结构使用@Viewbuilder 启用尾随闭包语法大部分成功,这使我能够使用我命名为“NavBarView”的视图,如下所示:

NavBarView(foregroundColor: .gray) {
        Text("Child view")
    }

Which uses the following initializer:它使用以下初始化程序:

init(foregroundColor: Color, @ViewBuilder content: () -> Content) {
    self.foregroundColor = foregroundColor
    self.content = content()
}

I can post all the code here for the NavBarView struct if you'd like to see it, but I haven't for brevity.如果您想查看 NavBarView 结构,我可以在此处发布所有代码,但为了简洁起见,我没有。

This code compiles fine and creates the desired effect which looks like this:这段代码编译得很好,并创建了如下所示的预期效果:

在此处输入图像描述

However, I'd like to be able to implement the optional ability to add items to the 'navigation bar', similar to how you can call.navigationBarItems(trailing: ) on views inside a navigation view.但是,我希望能够实现将项目添加到“导航栏”的可选功能,类似于在导航视图内的视图上调用 .navigationBarItems(trailing: ) 的方式。 I'm not sure I could go about implementing this though.我不确定我是否可以 go 来实现这个。

What i've tried so far is creating an optional state property in the NavBarView struct called item, where it's type Item conforms to View as follows:到目前为止,我尝试的是在名为 item 的 NavBarView 结构中创建一个可选的 state 属性,其中它的类型 Item 符合 View 如下:

@State var item: Item?

This item is then placed into an HStack so that when it isn't optional it should be showed next to the "Parent View" text.然后将该项目放入 HStack 中,以便当它不是可选的时,它应该显示在“父视图”文本旁边。

I've then written the following function within the NavBarView struct:然后我在 NavBarView 结构中编写了以下 function :

func trailingItem(@ViewBuilder _ item: () -> Item) -> some View {
    self.item = item()
    return self
}

I've then attempted to call the function like this:然后我尝试像这样调用 function:

NavBarView(foregroundColor: .gray) {
        Text("Child view")
    }.trailingItem{Text("test test")}

However, I'm not getting any text appearing, and the debug button which i've hooked up to print out what is in the item property prints out nil, so for some reason that function isn't setting the item property as Text("test test").但是,我没有出现任何文本,并且我连接以打印出项目属性中的内容的调试按钮打印出 nil,因此由于某种原因 function 没有将项目属性设置为文本( “测试一下”)。

Am I going about this completely the wrong way?我会以完全错误的方式解决这个问题吗? Could someone shed any light on how I might go about achieving the desired behavior?有人可以阐明我如何 go 来实现所需的行为吗?

This is possible approach, the only small correction to your modifier这是可能的方法,对修改器的唯一小修正

extension NavBarView {
    func trailingItem(@ViewBuilder _ item: @escaping () -> Item) -> some View {
        var view = self    // make modifiable
        view.item = item()
        return view
    }
}

and so you don't need to have it as @State , just declare it as所以你不需要将它作为@State ,只需将其声明为

fileprivate var item: Item?

Tested with Xcode 11.4用 Xcode 11.4 测试

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM