I have Views embedded in a list, one View
per List
item but for some reason, the View
only takes up a small leading part of the list's row, rather than filling the full line. The embedded View
is fully expanded in the preview of the View
so I'm unsure why this is happening.
List View
import SwiftUI
struct AnnouncementsView: View{
@Binding var announcements: [Announcement]
@State var displayedMessage: String = ""
@State var isDisplayingMessage: Bool = false
static let sectionDateFormat: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/YYYY"
return formatter
}()
var body: some View{
//NavigationView{
VStack{
List($announcements){$announcement in
AnnouncementView(announcement: $announcement)
}
Spacer()
}
}
}
List Item View
struct AnnouncementView: View{
@Binding var announcement: Announcement
@State private var sheetIsShowing: Bool = false
static let sectionDateFormat: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/YYYY"
return formatter
}()
var body: some View{
HStack{
Button(action: {
sheetIsShowing = true
}){
if (!announcement.read){
Image(systemName: "exclamationmark.circle.fill")
.foregroundColor(.red)
}
Text(announcement.message)
.lineLimit(1)
.truncationMode(.tail)
.foregroundColor(.black)
Spacer()
Text("\(announcement.timestamp, formatter: Self.sectionDateFormat)")
.disabled(true)
}
}
.padding()
.sheet(isPresented:$sheetIsShowing){
NavigationView{
DetailedAnnouncementView(announcement: $announcement)
.navigationTitle(Text("\(announcement.timestamp, formatter: Self.sectionDateFormat)"))
.toolbar{
ToolbarItem(placement: .navigationBarLeading){
Button(action: {
announcement.read = true
sheetIsShowing = false
}){
Text("Mark as Read")
}
}
ToolbarItem(placement: .navigationBarTrailing){
Button(action: {
sheetIsShowing = false
announcement.read = false
}){
Text("Mark as Unread")
}
}
}
}
}
}
}
I'm probably missing something really basic but any help is much appreciated.
Thanks.
CodePudding user response:
So it seems that SwiftUI renders Button
's content as if it was inside an HStack
by default, in case no Stack was provided.
However, when using the Button
inside a List
, this default behaviour changes to defaulting as if it was a VStack
. (Note that it only happens when used inside a List
. When used inside LazyVStack
, ScrollView
, ForEach
... the default HStack
is maintained).
So, in order to make sure the Button
's content is always rendered horizontally, specify it by explicitly nesting its content inside an HStack
instead of relying on Button
's "default" behaviour (as it does not seem to be consistent right now)
So, change:
Button(action: ...) {
//content
}
To:
Button(action: ...) {
HStack {
//content
}
}