SwifUI - Aligning items in a list - swiftui

I'm trying to align a row in a list but can't work out the order that I need to place items in to get the desired results.
My current code is
HStack {
Image(imageName ?? "")
.renderingMode(.original)
.resizable()
.scaledToFit()
.frame(height: 72.0)
Text("**1**")
VStack {
Text("2")
Text("3")
Text("4")
}
VStack {
Text("5")
Text("6")
}
}
Currently this is giving me the below layout
But I'm trying to make it look like this

This is what you need:
struct ContentView: View {
var body: some View {
List {
HStack(spacing: 20.0) {
Image(systemName: "swift")
.resizable()
.scaledToFit()
.frame(height: 72.0)
VStack(alignment: .leading) {
Text("Name")
.bold()
HStack(alignment: .top) {
VStack {
Text("2")
Text("3")
Text("4")
}
VStack {
Text("5")
Text("6")
}
}
}
}
}
}
}

You just need more stacks to wrap things, like
HStack {
Image("picture")
.renderingMode(.original)
.resizable()
.scaledToFit()
.frame(height: 72.0)
VStack(alignment: .leading) { // << here !!
Text("Name").bold()
HStack(alignment: .top) { // << here !!
VStack {
Text("2")
Text("3")
Text("4")
}
VStack {
Text("5")
Text("6")
}
}
}
}
Tested with Xcode 14 / iOS 16

Related

Color behind the time on iOS

This is my code:
struct Account: View {
var body: some View {
VStack {
ScrollView {
HStack {
Text("Account")
.font(.largeTitle)
.fontWeight(.bold)
Spacer(minLength: 0)
}
.padding()
.background(Color.indigo)
VStack {
Text("Doe, John Jack")
.font(.title)
Divider()
.foregroundColor(Color.indigo)
HStack {
Text("")
}
}
Spacer(minLength: 0)
VStack {
Button(action: {
}) {
Text("Log Out")
.foregroundColor(.red)
.fontWeight(.bold)
}
}
}
}
}
}
If you run the code above, you will see that the indigo doesn't go behind the time and battery precentage. How can I make it do that?
Try like this:
struct Account: View {
var body: some View {
VStack {
ScrollView {
HStack {
Text("Account")
.font(.largeTitle)
.fontWeight(.bold)
Spacer(minLength: 0)
}
.padding()
.background(Color.indigo)
VStack {
Text("Doe, John Jack")
.font(.title)
Divider()
.foregroundColor(Color.indigo)
HStack {
Text("")
}
}
Spacer(minLength: 0)
VStack {
Button(action: {
}) {
Text("Log Out")
.foregroundColor(.red)
.fontWeight(.bold)
}
}
}.padding(.top, 66)
}
.background(Color.indigo)
.edgesIgnoringSafeArea(.all)
}
}
You would also have to add some top padding to the ScrollView since ignoring safe area is going to push all your views to the margins
You should ignore the top safe area for this:
.ignoresSafeArea(.container, edges: .top)
Full working example
struct ContentView: View {
var body: some View {
Color
.indigo
.ignoresSafeArea(.container, edges: .top)
}
}

RoundedRectangle background leaves an uncolored gap

I wanted to make a RoundedRectangle that shows all the information and under it, there's a list of data.
The goal was, to make it look like a card, but when I change the background, it leaves a weird white gap, where it doesn't change the color. I already tried to change the background color, foreground color, accent color and everything I know for every single layer but I can't find the problem...
I made the RoundedRectangle .background green in this case, to make it more obvious.
Picture of the app, arrows are edited!
```var body: some View {
NavigationView {
VStack(alignment: .center) {
ZStack {
RoundedRectangle(cornerRadius: 25)
.padding()
.foregroundColor(.white)
.background(Color.green)
.frame(width: nil, height: 250)
VStack {
Text("Verfügbar")
.foregroundColor(.gray)
.italic()
.font(.title2)
Text("\(totalMoneyToday(), specifier: "%.2f")€")
.foregroundColor(.blue)
.bold()
.font(.largeTitle)
HStack {
Spacer()
VStack(alignment: .leading) {
Text("Einkommen")
.foregroundColor(.gray)
.italic()
HStack {
Label("", systemImage: "arrow.up.circle")
.foregroundColor(.green)
Text("\(posMoney(), specifier: "%.2f")€").bold()
}
}
Spacer()
VStack(alignment: .trailing) {
Text("Ausgaben")
.foregroundColor(.gray)
.italic()
HStack {
Label("", systemImage: "arrow.down.circle")
.foregroundColor(.red)
Text("\(negMoney(), specifier: "%.2f")€").bold()
}
}
Spacer()
}
.padding(5)
}
}.background(Color.red)
List {
ForEach(money) { money in
NavigationLink(destination: EditMoneyView(money: money)) {
HStack {
VStack(alignment: .leading, spacing: 6) {
Text(money.name!)
.bold()
Text("\(money.amount, specifier: "%.2f")") + Text("€")
}
Spacer()
Text("\(money.date!, style: .date)")
.foregroundColor(.gray)
.italic()
}
}
}
.onDelete(perform: deleteMoney)
}
}
.navigationBarTitle("Financist", displayMode: .inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
showingAddView.toggle()
} label: {
Label("Hinzufügen", systemImage: "plus.circle")
}
}
}
.sheet(isPresented: $showingAddView) {
AddMoneyView()
}
}
}```
Thank you so much guys!
I think it is just default spacing, make it zero
NavigationView {
VStack(alignment: .center, spacing: 0) { << here !!
It's your ZStack background.
var body: some View {
NavigationView {
VStack(alignment: .center) {
ZStack {
RoundedRectangle(cornerRadius: 25)
.padding()
.foregroundColor(.white)
.background(Color.green)
.frame(width: nil, height: 250)
VStack {
Text("Verfügbar")
.foregroundColor(.gray)
.italic()
.font(.title2)
Text("Money")
.foregroundColor(.blue)
.bold()
.font(.largeTitle)
HStack {
Spacer()
VStack(alignment: .leading) {
Text("Einkommen")
.foregroundColor(.gray)
.italic()
HStack {
Label("", systemImage: "arrow.up.circle")
.foregroundColor(.green)
Text("money").bold()
}
}
Spacer()
VStack(alignment: .trailing) {
Text("Ausgaben")
.foregroundColor(.gray)
.italic()
HStack {
Label("", systemImage: "arrow.down.circle")
.foregroundColor(.red)
Text("money").bold()
}
}
Spacer()
}
.padding(5)
}
}.background(Color.red)
List {
// ForEach(money) { money in
// NavigationLink(destination: EditMoneyView(money: money)) {
// HStack {
// VStack(alignment: .leading, spacing: 6) {
// Text(money.name!)
// .bold()
//
// Text("\(money.amount, specifier: "%.2f")") + Text("€")
// }
// Spacer()
// Text("\(money.date!, style: .date)")
// .foregroundColor(.gray)
// .italic()
// }
// }
// }
// .onDelete(perform: deleteMoney)
}
}
.navigationBarTitle("Financist", displayMode: .inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
// showingAddView.toggle()
print("DEBUG: Button")
} label: {
Label("Hinzufügen", systemImage: "plus.circle")
}
}
}
.background(.red) // added this
// .sheet(isPresented: $showingAddView) {
// AddMoneyView()
// }
}
}

SwiftUI Context Menu

My project was using a List but I needed a ScrollView wrapped view so I changed the List to just a ForEach loop with a view and Divider in between. I noticed my Context Menu doesn't look the same as when it was in the List as in the screenshot below.
I'd like the item selected with context menu to look like the List item selected since I can no longer use List in the code, it doesn't look as pretty. Also I have to press on the image and or text to open the Context Menu unlike in a List you can select the row. The end result would be to mimic the style of the selected List item.
/// Context Menu looks terrible
VStack (alignment: .leading, spacing: 0){
ForEach(self.welcome.views.dropLast(), id: \.id) { view in
ForEach(view.views ?? [], id: \.id) { purple in
ForEach(purple.views, id: \.id) { fluffy in
VStack (alignment: .leading, spacing: 0){
if viewClass == "FeaturedHeaderView" {
Text(title)
.font(.title3)
.fontWeight(.bold)
} else {
HStack (spacing: 15){
RequestImage(Url(image), animation: nil)
.aspectRatio(contentMode: .fit)
.frame(width: 60, height: 60)
.clipped()
.cornerRadius(13.5)
VStack (alignment: .leading){
Text(name)
.font(.headline)
.fontWeight(.bold)
Text(author)
.foregroundColor(Color.secondary)
.font(.footnote)
Text(repo)
.foregroundColor(Color.secondary)
.font(.caption)
}
}
.contextMenu(ContextMenu(menuItems: {
HStack {
Button(action: {
openURL(URL(string: "URL")!)
}) {
Label("Open in Safari", systemImage: "safari.fill")
}
}
}))
}
}
Divider()
}
}
}
.padding(.all, 5)
.padding(.leading, 5)
}
/// List Context Menu looks great but can't use List in ScrollView
List {
ForEach(self.welcome.views.dropLast(), id: \.id) { view in
ForEach(view.views ?? [], id: \.id) { purple in
ForEach(purple.views.dropLast(), id: \.id) { fluffy in
VStack (alignment: .leading, spacing: 0){
if viewClass == "FeaturedHeaderView" {
Text(title)
.font(.title3)
.fontWeight(.bold)
} else {
HStack (spacing: 15){
RequestImage(Url(image), animation: nil)
.aspectRatio(contentMode: .fit)
.frame(width: 60, height: 60)
.clipped()
.cornerRadius(13.5)
VStack (alignment: .leading){
Text(name)
.font(.headline)
.fontWeight(.bold)
Text(author)
.foregroundColor(Color.secondary)
.font(.footnote)
Text(repo)
.foregroundColor(Color.secondary)
.font(.caption)
}
}
.contextMenu(ContextMenu(menuItems: {
HStack {
Button(action: {
openURL(URL(string: "URL")!)
}) {
Label("Open in Safari", systemImage: "safari.fill")
}
}
}))
}
}
}
}
}
.padding(.all, 10)
.listRowInsets(EdgeInsets())
}
The possible solution is to add background modifier above contextMenu, like
.frame(maxWidth: .infinity) // << to make it screen-wide
.background(
RoundedRectangle(cornerRadius: 12) // << tune as needed
.fill(Color(UIColor.systemBackground)) // << fill with system color
)
.contextMenu(ContextMenu(menuItems: {
Demo with some replication (used Xcode 12.4 / iOS 14.4)

SwifUI - How to remove list row background color for card style

I made a card style List row which work fine. The issue is that the list row background color remains. I can make it disappear by setting it to systemGray6 but it's not very adaptive for dark mode and there is very likely a better way of doing this.
Card View:
var body: some View {
ZStack {
Rectangle().fill(Color.white)
.cornerRadius(10).shadow(color: .gray, radius: 4)
.frame(width: UIScreen.main.bounds.width - 40)
HStack {
Image(uiImage: (UIImage(data: myVideo.thumbnailImage!) ?? UIImage(systemName: "photo"))!)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
VStack {
Text(myVideo.title!)
.multilineTextAlignment(.center)
.font(.body)
.padding(.bottom, 10)
.frame(maxWidth: UIScreen.main.bounds.width - 40, maxHeight: .infinity, alignment: .center)
Text(myVideo.youtuber!)
.font(.subheadline)
}
}
.padding(5)
}
}
List View:
var body: some View {
NavigationView {
if myVideos.isEmpty {
Text("You have not added videos yet!")
font(.subheadline)
} else {
List() {
Section(header: Text("Not Watched")) {
ForEach(myVideos) { video in
if !video.watched {
NavigationLink(destination: MyVideoView(myVideo: video)) {
MyListRowView(myVideo: video)
}
}
}
.onDelete(perform: removeItems)
}
Section(header: Text("Watched")) {
ForEach(myVideos) { video in
if video.watched {
NavigationLink(destination: MyVideoView(myVideo: video)) {
MyListRowView(myVideo: video)
}
}
}
.onDelete(perform: removeItems)
}
.listRowBackground(Color(UIColor.systemGray6))
}
.navigationBarTitle("Videos")
.listStyle(GroupedListStyle())
}
}
}
Image: (Intended behaviour in "WATCHED" and Incorrect behaviour in "NOT WATCHED"

SwiftUI Question: Place text underneath(outside) of list view

I am trying to place this information underneath my list. I don't want it to be included in the list but rather it should be displayed on the view background. Sort of like the old settings in iOS 6. I've tried placing my code snippets in different spots and removing stacks snd even changing what stacks I'm using and I cant figure it out. Heres my code and I attached a screenshot https://i.stack.imgur.com/PcUgJ.png for reference. Thank you to anyone who can help my noob self.
My Code:
import SwiftUI
struct SettingsAboutView: View {
var body: some View {
List{
//Top Section
Section {
HStack(spacing: 30) {
Spacer()
ZStack {
Rectangle()
.frame(width: 50, height: 50)
.clipShape(Rectangle())
.shadow(radius: 2)
.foregroundColor(Color("PineGlade"))
Image(systemName: "leaf.arrow.circlepath")
.resizable()
.frame(width: 25, height: 25)
.clipShape(Rectangle())
.foregroundColor(.white)
}.cornerRadius(10)
VStack(alignment: .leading) {
Text("Gardn")
.font(.system(size: 32))
.fontWeight(.bold)
.foregroundColor(Color("ShipsOfficer"))
Text("OnlyOdds.co Labs")
.font(.system(size: 13))
.fontWeight(.medium)
.foregroundColor(Color("ShipsOfficer"))
}
Spacer()
}.padding()
NavigationLink(destination: SettingsPrivacyView()) {
Button(action: {
print("Privacy Settings")
}) {
SettingsCell(title: "Privacy", imgName: "eye.slash", clr: Color("PineGlade"))
}
}
NavigationLink(destination: SettingsNotificationsView()) {
Button(action: {
print("Notification Settings")
}) {
SettingsCell(title: "Notifications", imgName: "bell", clr: Color("PineGlade"))
}
}
}
//Technical Info
HStack(spacing: 62) {
Spacer()
Text("V \(UIApplication.appVersion!)")
.font(.system(size: 14))
.fontWeight(.light)
.foregroundColor(Color("ShipsOfficer"))
.opacity(0.5)
Text("Build \(UIApplication.appBuild!)")
.font(.system(size: 14))
.fontWeight(.light)
.foregroundColor(Color("ShipsOfficer"))
.opacity(0.5)
Spacer()
}
}.listStyle(GroupedListStyle())
.environment(\.horizontalSizeClass, .regular)
.navigationBarTitle("Settings", displayMode: .inline)
}
}
struct SettingsAboutView_Previews: PreviewProvider {
static var previews: some View {
SettingsAboutView()
}
}
extension UIApplication {
static var appVersion: String? {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
}
}
extension UIApplication {
static var appBuild: String? {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String
}
}
What you are looking for is a Footer. The Section View takes Footer as ViewBuilder as argument.
Section(footer: Text("Your footer text")) {
//Your Content here
}
You can pass Text() or create your own custom view.
Just put the List in a VStack and put
Text(yourtext)
Under the list