gpt4 book ai didi

Change color of SwiftUI give Form section header(更改SwiftUI给予表单节标题的颜色)

转载 作者:bug小助手 更新时间:2023-10-25 23:38:38 25 4
gpt4 key购买 nike



I am trying to add a unique style to my app in the most declarative way possible. Coming from the CSS world I am very used to being able to specifically go in and say that <p>'s should have specific styling or even <p>'s that are within a div. I am trying to get similar semantics here.

我正试图以一种最具声明性的方式为我的应用程序添加一种独特的风格。作为css世界的一员,我非常习惯于能够明确地走进去,说

‘S应该有特定的样式,甚至

’S应该在一个div中。我正试图在这里得到类似的语义。


Ideally I would write my whole interface like this:

理想情况下,我应该这样编写整个界面:


Form {
Section {
LabeledContent {
TextField("I am a field:", text: .constant("Blah"))
.keyboardType(.numberPad)
Picker(selection: .constant(false), label: Text("")) {
Text("option 1").tag(true)
Text("option 2").tag(false)
}
.pickerStyle(.menu)
} label: {
Text("Text Field Label")
}
} header: {
Text("Header")
}
}.navigationBarTitle("Navigation Bar Title")
.formStyle(.theDefault)
// Very declarative only one style modifier needed. Since every Header text,
// LabeledContent, picker etc etc is going to look the same I want to make it easy to apply the styling. Ideally automatically.

And have that .formStyle(.theDefault) on the Form be enough. I don't know if this is obtainable. Thus far I have ran into two roadblocks.

并且在表单上具有.formStyle(.theDefault)就足够了。我不知道这是不是可以得到。到目前为止,我遇到了两个路障。



  1. I needed to use .labeledContentStyle(.theDefault)to style my form sections background with listRowBackground that is a bummer because now every time I add a LabeledContent I need to specifically call out it should use the default styling.

  2. My section headers can't be really be automatically styled by their superviews at. all. Most of the ways I have seen to do this would require me to have duplicated code for every section header.


So I guess my question is. Is there any way for this to just "work". I would love for my code to somewhat look like the above but have my custom styling from top to bottom with as minimal duplicated modifiers as possible. But it seems I can't modify labeledContentStyle from my FormStyle and I can't go in and specifically change the style of headers.

所以我想我的问题是。有没有办法让这一切“奏效”。我喜欢我的代码看起来有点像上面,但有我的自定义样式从上到下与尽可能少的重复修饰符。但是似乎我不能从我的FormStyle中修改LabeledContent Style,我也不能进入并具体更改标题的样式。


I would be totally fine if I have to write AppHeaderLabel("Bla") instead of Label("Bla") as that is better than having to say .textLabelStyle every time I have a Text object within my view.

如果我必须编写AppHeaderLabel(“Bla”)而不是Label(“Bla”),我会完全没有问题,因为这比每次在我的视图中有一个文本对象时都必须说.extLabelStyle要好得多。


Is there even any way to pull off #2? I would very much like to be able to see my headers.
Here's what my code looks like now

有没有办法完成第二名?我非常希望能够看到我的标题。下面是我的代码现在的样子


UI Image State. You can barely see header.


Here is the code

这里是代码


enum ColorConsts {
static let background: Color = Color(UIColor.darkGray)
static let card: Color = Color(UIColor(hue: 0.6, saturation: 0.51, brightness: 0.18, alpha: 1.0))
static let textColor: Color = Color(UIColor(hue: 0.619, saturation: 0.23, brightness: 0.65, alpha: 1.0))
static let accentColor: Color = Color(UIColor(hue: 0.46, saturation: 0.95, brightness: 0.68, alpha: 1.0))
}

struct LabeledControlContentStyle: LabeledContentStyle {
func makeBody(configuration: Configuration) -> some View {
LabeledContent(configuration)
.listRowBackground(ColorConsts.card)
.foregroundColor(ColorConsts.textColor)
.tint(ColorConsts.accentColor)

}
}

extension LabeledContentStyle where Self == LabeledControlContentStyle {
static var theDefault: LabeledControlContentStyle { .init() }
}

//https://sarunw.com/posts/swiftui-form-styling/
struct FormContentStyle: FormStyle {
func makeBody(configuration: Configuration) -> some View {
Form(configuration)
.listRowBackground(ColorConsts.card)
.background(ColorConsts.background)
.scrollContentBackground(.hidden)
}
}

extension FormStyle where Self == FormContentStyle {
static var theDefault: FormContentStyle { .init() }
}

struct AppStyles_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
Form {
Section {
LabeledContent {
TextField("I am a field:", text: .constant("Blah"))
.keyboardType(.numberPad)
Picker(selection: .constant(false), label: Text("")) {
Text("option 1").tag(true)
Text("option 2").tag(false)
}
.pickerStyle(.menu)
} label: {
Text("Text Field Label").fontWeight(.bold).foregroundColor(ColorConsts.textColor)
}.labeledContentStyle(.theDefault)
} header: {
Text("Header")
}
}.navigationBarTitle("Navigation Bar Title")
.formStyle(.theDefault)
}
}
}

It's worth saying I do hope to write "good" SwiftUI code. So I would probably be good with answers like "repeated style modifiers are just how it's done" if that's truly how SwiftUI should be written. But I am also curious if there are ways to make this more declarative so I can approach writing my UI more in the style it's done above (minimal repeated styling code. Labels,Forms, etc just get the right style).

值得一提的是,我确实希望编写“好的”SwiftUI代码。因此,如果SwiftUI真的应该这样编写,我可能会很好地回答“重复的样式修饰符就是这样做的”这样的答案。但我也很好奇是否有办法让它更具声明性,这样我就可以用上面的风格(最少的重复样式代码)来编写我的UI。标签、表格等只是获得正确的样式)。


My suspicion is that I should stop using Forms and Sections since styling them is so important to me and I am already having to be somewhat hacky by using scrollContentBackground(.hidden). Is there a way in SwiftUI to then create my "own" Form/Section classes so that I can write the UI like above but everything just works? I could of course build it with stacks etc. But being able to semantically just use Form {Section {} Section {}} is quite nice.

我的怀疑是,我应该停止使用表单和部分,因为样式对我来说太重要了,而且我已经不得不通过使用scroll Content Backround(.den)变得有点老生常谈了。有没有办法在SwiftUI中创建我自己的Form/Sector类,这样我就可以像上面那样编写UI,但一切都正常?我当然可以使用堆栈等来构建它,但能够在语义上只使用形式{Sections{}Sections{}}是非常好的。


更多回答

I thought Section { LabeledContent { } header: { Text("Header") } was a section header? You just can only barely see it in my screenshot since the default color for it is so close to the background color. I am trying to create an interface that is dark.

我以为第{LabeledContent{}标题:{Text(“Header”)}是节标题?你只能在我的屏幕截图中勉强看到它,因为它的默认颜色与背景颜色如此接近。我正在尝试创建一个暗色的界面。

Anything light. Ideally I have my text color .foregroundColor(ColorConsts.textColor)

任何清淡的东西。理想情况下,我的文本颜色是.forecround颜色(ColorConsts.extColor)

Ah I see, so you are trying to avoid having to say that everywhere?

啊,我明白了,所以你是想避免到处都这么说吗?

Yeah. But for me even Text("Text Field Label").fontWeight(.bold).foregroundColor(ColorConsts.textColor) made no changes.

嗯。但对我来说,即使是文本(“Text field Label”).fontWeight(.bold).foregroundColor(ColorConsts.textColor)“)也没有做任何更改。

I guess my most urgent problem is the headers not showing because I can't style them. But eventually ideally I would like to write this interface with similar styling to what I have at the top (everything is simple and there is only one style statement) and am willing to explore even complicated options to make that possible. I am missing being able to specifically target sub-view within a view EX: Writing a FormStyle that would also apply a LabeledContentStyle to any labeled content within it.

我想我最迫切的问题是标题没有显示,因为我不能设计它们的样式。但最终,理想情况下,我希望用类似于我在顶部拥有的样式来编写这个界面(一切都很简单,只有一个样式声明),并愿意探索甚至复杂的选项来实现这一点。我错过了专门针对视图中的子视图的能力,例如:编写一个FormStyle,它也会将LabeledContent Style应用于其中的任何标签内容。

优秀答案推荐

Note that a lot of the built-in xxxStyle modifiers applies the style to the whole hierarchy that is below the applied view, unless there is a subview that already has the modifier. This includes labeledContentStyle. If you put labeledContentStyle on the Form, then all the LabeledContent gets the style.

请注意,许多内置的xxxStyle修改器将样式应用于应用视图下方的整个层次,除非有已有修改器的子视图。这包括LabeledContent Style。如果将LabeledContent Style放在表单上,则所有LabeledContent都将获得该样式。


So you can just add labeledContentStyle once to the Form. You don't need to add it once for every LabeledContent you have.

因此,您只需向表单中添加一次LabeledContent Style。您不必为您拥有的每个LabeledContent添加一次。


Form {
// ...
}
.labeledContentStyle(.theDefault)
.formStyle(.theDefault)

You can even put this in your FormStyle:

您甚至可以在您的FormStyle中添加以下内容:


struct FormContentStyle: FormStyle {
func makeBody(configuration: Configuration) -> some View {
Form(configuration)
.listRowBackground(ColorConsts.card)
.background(ColorConsts.background)
.scrollContentBackground(.hidden)
// This
.labeledContentStyle(.theDefault)
}
}

For your section headers, you can make your own AppHeaderLabel view like this, as you suggested:

对于您的节标题,您可以按照您的建议创建自己的AppHeaderLabel视图:


struct SectionHeader: View {
let text: LocalizedStringKey

init(_ text: LocalizedStringKey) {
self.text = text
}

var body: some View {
Text(text)
.foregroundColor(ColorConsts.textColor)
// plus whatever other styling you want
}
}

Of course, Text has many initialisers in addition to the one that takes in a LocalizedStringKey. It would be better if you just made your own section header modifier.

当然,除了接受LocalizedStringKey的初始值设定项之外,文本还有许多初始值设定项。如果你只做你自己的章节标题修饰符,那会更好。


extension View {
func sectionHeaderStyle() -> some View {
self
.foregroundColor(ColorConsts.textColor)
// plus whatever other styling you want
}
}

This approach can be used to "merge" however many view modifiers you want to use, into just one modifier. You can now just say:

这种方法可用于将您想要使用的任意多个视图修改器“合并”为一个修改器。现在,您只需说:


Text("Header").sectionHeaderStyle()
// instead of
Text("Header")
.foregroundColor(ColorConsts.textColor)
.somethingElse()
.yetAnotherModifier()
// ...

Note that if the styling needs state, you can use a ViewModifier instead. See also: Difference between creating ViewModifier and View extension in SwiftUI

请注意,如果样式设置需要状态,则可以改用视图修改器。另请参阅:在SwiftUI中创建视图修改器和视图扩展之间的区别


更多回答

This is SUPER useful. Many patterns here I didn't think of using. With the sectionHeaderStyle pattern is there any way to get it so that say something I put in in FormContentStyle or at the top level view was able to apply only to the Label views that are headers? Or even only on SectionHeader's?

这是超级有用的。这里有很多模式我都没想过要用。对于sectionHeaderStyle模式,有什么方法可以使我在FormContent Style中或在顶层视图中输入的内容只能应用于作为Header的标签视图?或者甚至只在SectionHeader上使用?

@CalebK I don't think "apply only to the Label views that are headers" is possible. But if you want it to apply to your custom view, you should be able to do that with a custom EnvironmentKey.

@CalebK我不认为“只应用于作为标题的标签视图”是可能的。但是,如果您希望它应用于您的自定义视图,您应该能够使用一个自定义的Environment Key来实现。

@CalebK Since .environment applies to all subviews, you can use that to do view modifiers that affect the whole view hierarchy. See here for how to make custom EnvironmentKeys. You would read these keys in SectionHeader and style it accordingly. You can't affect built-in views with this technique though, because they don't know about your custom environment key.

@CalebK由于.Environment适用于所有子视图,因此您可以使用它来进行影响整个视图层次结构的视图修饰符。查看此处了解如何制作自定义环境键。您将在SectionHeader中读取这些键并相应地设置其样式。但是,您不能使用此技术影响内置视图,因为它们不知道您的自定义环境密钥。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com