如何仅将 SwiftUI 不透明度应用于父视图?
How to apply SwiftUI opacity to the parent View only?
将不透明度应用于 SwiftUI 中的视图,将其向下传递到层次结构中,看起来它有点像环境值。当每个子视图独立地受到不透明度的影响时,它会导致行为。不管我们把黄色圆圈放在叠加层、背景还是ZStack里面。
我们如何才能使不透明度只影响父视图,就像它在 UIKit 中的行为一样,这样整个视图及其所有内容将变成半透明的单个实体对象?
struct OpacityTest: View {
var body: some View {
HStack(spacing: 30) {
buttonContent
.opacity(0.5)
Button(action: {}) {
buttonContent
}
}
}
var buttonContent: some View {
Image(systemName: "calendar.circle")
.resizable()
.frame(width: 65, height: 65)
.overlay(
Circle()
.fill(Color.yellow)
.frame(width: 40, height: 40)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
)
}
}
struct OpacityTest_Preview: PreviewProvider {
static var previews: some View {
OpacityTest()
}
}
更新:
正如 ChrisR 回答的那样,.drawingGroup() 完成了工作并部分解决了问题,但直到一切都在父视图范围内。一旦我们向叠加层内的视图添加偏移量,它就会被裁剪。有机会避免这种情况吗?
.overlay(
Circle()
.fill(Color.yellow)
.frame(width: 40, height: 40)
.offset(x: 10, y: -10) //This modifier brakes the drawingGroup
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
)
添加.drawingGroup()
。这会将所有进一步的修饰符应用于整个 object/view:
var buttonContent: some View {
Image(systemName: "calendar.circle")
.resizable()
.frame(width: 65, height: 65)
.overlay(
Circle()
.fill(Color.yellow)
.frame(width: 40, height: 40)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
)
.drawingGroup() // here
}
关于 OP 更新的编辑:
.offset
不会更改视图的 size/bounds,只会移动渲染,这会导致不必要的裁剪。您可以使用 geometryReader
,但在固定大小的示例中,手动放大父框架应该足以避免剪裁:
var buttonContent: some View {
ZStack(alignment: .topTrailing) {
Image(systemName: "calendar.circle")
.resizable()
.frame(width: 65, height: 65)
Circle()
.fill(Color.yellow)
.frame(width: 40, height: 40)
.offset(x: 10, y: -10)
}
.frame(width: 95, height: 95) // here
.drawingGroup()
}
如果我们对父视图应用任何修饰符,它也会对子视图产生影响。
从 buttonContent 中删除 .opacity(0.5)
并将其添加到 .overlay modifier
之前
添加 .compositingGroup() 就可以了。它使外部修饰符仅在顶层起作用,而不会通过层次结构传递。也不裁剪任何带偏移的子视图,并保留原始布局框架。
var buttonContent: some View {
Image(systemName: "calendar.circle")
.resizable()
.frame(width: 65, height: 65)
.overlay(
Circle()
.fill(Color.yellow)
.frame(width: 40, height: 40)
.offset(x: 10, y: -10)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
)
.compositingGroup() //here
}
将不透明度应用于 SwiftUI 中的视图,将其向下传递到层次结构中,看起来它有点像环境值。当每个子视图独立地受到不透明度的影响时,它会导致行为。不管我们把黄色圆圈放在叠加层、背景还是ZStack里面。
我们如何才能使不透明度只影响父视图,就像它在 UIKit 中的行为一样,这样整个视图及其所有内容将变成半透明的单个实体对象?
struct OpacityTest: View {
var body: some View {
HStack(spacing: 30) {
buttonContent
.opacity(0.5)
Button(action: {}) {
buttonContent
}
}
}
var buttonContent: some View {
Image(systemName: "calendar.circle")
.resizable()
.frame(width: 65, height: 65)
.overlay(
Circle()
.fill(Color.yellow)
.frame(width: 40, height: 40)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
)
}
}
struct OpacityTest_Preview: PreviewProvider {
static var previews: some View {
OpacityTest()
}
}
更新: 正如 ChrisR 回答的那样,.drawingGroup() 完成了工作并部分解决了问题,但直到一切都在父视图范围内。一旦我们向叠加层内的视图添加偏移量,它就会被裁剪。有机会避免这种情况吗?
.overlay(
Circle()
.fill(Color.yellow)
.frame(width: 40, height: 40)
.offset(x: 10, y: -10) //This modifier brakes the drawingGroup
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
)
添加.drawingGroup()
。这会将所有进一步的修饰符应用于整个 object/view:
var buttonContent: some View {
Image(systemName: "calendar.circle")
.resizable()
.frame(width: 65, height: 65)
.overlay(
Circle()
.fill(Color.yellow)
.frame(width: 40, height: 40)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
)
.drawingGroup() // here
}
关于 OP 更新的编辑:
.offset
不会更改视图的 size/bounds,只会移动渲染,这会导致不必要的裁剪。您可以使用 geometryReader
,但在固定大小的示例中,手动放大父框架应该足以避免剪裁:
var buttonContent: some View {
ZStack(alignment: .topTrailing) {
Image(systemName: "calendar.circle")
.resizable()
.frame(width: 65, height: 65)
Circle()
.fill(Color.yellow)
.frame(width: 40, height: 40)
.offset(x: 10, y: -10)
}
.frame(width: 95, height: 95) // here
.drawingGroup()
}
如果我们对父视图应用任何修饰符,它也会对子视图产生影响。
从 buttonContent 中删除 .opacity(0.5)
并将其添加到 .overlay modifier
添加 .compositingGroup() 就可以了。它使外部修饰符仅在顶层起作用,而不会通过层次结构传递。也不裁剪任何带偏移的子视图,并保留原始布局框架。
var buttonContent: some View {
Image(systemName: "calendar.circle")
.resizable()
.frame(width: 65, height: 65)
.overlay(
Circle()
.fill(Color.yellow)
.frame(width: 40, height: 40)
.offset(x: 10, y: -10)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
)
.compositingGroup() //here
}