I'm trying to recreate the messages app from Apple, I noticed that their chevron on the chat selection is at the top and not the center like how navigationLink gives by default.
Here is an image of Apple Messages:
Here is an image of my application:
import SwiftUI
struct ContentView: View {
private var imageSize: CGFloat = 50
var body: some View {
NavigationStack {
List(NavigationScreens.allCases, id: \.self) { screen in
NavigationLink(value: screen) {
Label(title: {
MessageChat(name: "SwiftUI")
.padding(.leading, 15)
//.border(.red)
}, icon: {
HStack {
Image(systemName: "circle.fill")
.resizable()
.frame(width: 10, height: 10)
Image("image_test")
.resizable()
.frame(width: imageSize, height: imageSize)
.clipShape(Circle())
}
.padding(10)
})
}
}
.navigationTitle("Messages")
.listStyle(.plain)
.scrollContentBackground(.hidden)
.navigationDestination(for: NavigationScreens.self) { screen in
switch screen {
case .Chat, .Profile, .Settings:
ChatSelection()
}
}
}
}
}
I'm not entirely sure if this is the correct way of doing it or if a custom NavigationLink would be needed.
Message Chat Code:
struct MessageChat: View {
@State var contact: Contact
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 4) {
HStack {
// MARK: Name
Text(contact.name)
.font(.headline)
.lineLimit(1)
.foregroundStyle(Color.primary)
Spacer()
// MARK: Message Date
Text("12/12/12")
.font(.subheadline)
.foregroundStyle(Color.gray)
}
.padding(.trailing, 20)
// MARK: Message Description
Text("Some random text long enough to have the multiple lines effect, just in case its not long enough")
.lineLimit(2)
.font(.subheadline)
.foregroundStyle(Color.secondary)
.frame(maxHeight: 40, alignment: .topLeading)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
If you move the NavigationLink
into the view MessageChat
then you can get the styling you are after:
struct MessageChat: View {
let name: String
let screen: NavigationScreens
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 4) {
NavigationLink(value: screen) {
HStack {
// ... name + message date, as before
}
.padding(.trailing, 20)
}
// ... description, as before
}
}
}
}
The List
then changes to something like:
List(NavigationScreens.allCases, id: \.self) { screen in
Label {
MessageChat(name: "SwiftUI", screen: screen)
.padding(.leading, 15)
} icon: {
HStack {
// ... images, as before
}
.padding(10)
}
}
Surprisingly, this turns the whole row into a link! This is why the dot on the left is in the active button color (blue), instead of the default foreground color.
Btw, you shouldn't be passing in a State
variable as a parameter. So inside MessageChat
, contact
should either be a let
or var
variable, or a Binding
, but not a State
variable.