Hi there
Issue
I've implemented a custom DisclosureGroupStyle for a List, which shows hierarchical data. However, it seems that when applying this (or any other) custom DisclosureGroupStyle in macOS the context menu stops working, except on the lowest level. In iOS, on the other hand, the context menu keeps working on all levels.
Is this excepted behaviour?
Example
var body: some View {
List(categories, id: \.value, children: \.children) { tree in
Text(tree.value).font(.subheadline)
.contextMenu{
Button("Test") {}
}
}
.disclosureGroupStyle(SideBarDisclosureGroupStyle())
.padding(50)
}
}
struct SideBarDisclosureGroupStyle: DisclosureGroupStyle {
func makeBody(configuration: Configuration) -> some View {
HStack(alignment: .firstTextBaseline) {
configuration.label
Spacer()
Image(systemName:"chevron.\(configuration.isExpanded ? "down" : "right").circle")
.imageScale(.large)
.foregroundStyle(.secondary)
.onTapGesture() {
configuration.isExpanded.toggle()
}
}
.contentShape(Rectangle())
if configuration.isExpanded {
configuration.content
.disclosureGroupStyle(self)
}
}
}
// Example Data (Source: https://swiftwithmajid.com/2020/09/02/displaying-recursive-data-using-outlinegroup-in-swiftui/)
struct Tree<Value: Hashable>: Hashable {
let value: Value
var children: [Tree]? = nil
}
let categories: [Tree<String>] = [
.init(
value: "Clothing",
children: [
.init(value: "Hoodies"),
.init(value: "Jackets"),
.init(value: "Joggers"),
.init(value: "Jumpers"),
.init(
value: "Jeans",
children: [
.init(value: "Regular"),
.init(value: "Slim")
]
),
]
),
.init(
value: "Shoes",
children: [
.init(value: "Boots"),
.init(value: "Sliders"),
.init(value: "Sandals"),
.init(value: "Trainers"),
]
)
]
System info
macOS 13.0 Beta(22A5358e)
Xcode 14.0 beta 6 (14A5294g)
Many thanks
Sebastian
Post
Replies
Boosts
Views
Activity
Hello
I am trying to display items in a ScrollView which contains several autosized NSViewRepresentables. However, it seems the items overlap each other after scrolling or when the size of its parent ScrollView is changed (for an example see my post on SO) - https://stackoverflow.com/questions/66175613/autosized-nsviewrepresentables-in-scrollview-overlap-each-other-swiftui
If I've understood correctly, the ScrollView needs to know the height of its items to render it correctly. Therefore, I tried to pass the total height of the each item to its parent ScrollView, however, the items still overlap. I've made a simple example:
struct dataItem: Identifiable {
let id = UUID()
let question: String
let answer: String
}
let exampleData: [dataItem] = [dataItem(question: "Lorem Ipsum is simply....", answer: "Lorem Ips ange...ker including versions of Lorem Ipsum.") ,
dataItem(question:"The standard ..ranslation by H. Rackham.", answer:"The standard c.... Rackham."),
dataItem(question:"The standard ch...Rackham.", answer:"The stand...kham."),
dataItem(question:"The stand..Rackham.", answer:"The standa...kham."),
dataItem(question:"The stand...ackham.", answer:"The standard ...ham."),
dataItem(question:"The standa..H. Rackham.", answer:"The standard c...ackham."),
dataItem(question:"The st... H. Rackham.", answer:"The standard ch...m.")
]
struct ContentView: View {
@State var totalHeight: CGFloat = 80
var body: some View {
ScrollView{
ScrollViewReader{ scrollView in
LazyVStack {
ForEach(exampleData, id: \.id) { item in
RowView(item: item, totalHeight: $totalHeight)
// The following line makes the ScrollView jitter
// .frame(height: totalHeight)
}
}
}
}
.id(UUID().uuidString)
}
}
struct RowView: View {
let item: dataItem
@Binding var totalHeight: CGFloat
@State var optimalHeightQuestionValue: CGFloat = .zero
@State var optimalHeightAnswerValue: CGFloat = .zero
var body: some View{
let optimalHeightQuestion = BindingCGFloat(
get: {self.optimalHeightQuestionValue}, set: {
self.optimalHeightQuestionValue = $0
totalHeight = optimalHeightQuestionValue + optimalHeightAnswerValue
})
let optimalHeightAnswer = BindingCGFloat(
get: {self.optimalHeightAnswerValue}, set: {
self.optimalHeightAnswerValue = $0
totalHeight = optimalHeightQuestionValue + optimalHeightAnswerValue
})
VStack{
TextViewExt(attributedText: NSAttributedString(string: item.question), optimalHeight: optimalHeightQuestion)
.frame(height: optimalHeightQuestionValue)
TextViewExt(attributedText: NSAttributedString(string: item.answer), optimalHeight: optimalHeightAnswer)
.frame(height: optimalHeightAnswerValue)
}
}
}
struct TextViewExt: NSViewRepresentable {
typealias NSViewType = NSTextView
var attributedText: NSAttributedString
@Binding var optimalHeight: CGFloat
func makeNSView(context: Context) - NSTextView {
let textView = NSTextView()
textView.backgroundColor = .clear
return textView
}
func updateNSView(_ nsView: NSTextView, context: Context) {
DispatchQueue.main.async {
nsView.textStorage?.setAttributedString(attributedText)
nsView.translatesAutoresizingMaskIntoConstraints = true
nsView.sizeToFit()
self.optimalHeight = nsView.frame.height
}
}
}
Does anybody know why that's happening? Or is there something wrong with the auto-sizing of the NSTextView?
Thanks a lot for any advise!