Post

Adding a Button to a List Section Title

I have a couple of different applications I am writing as part of my journey of learning swift. One of the applications that I am excited about making is a Pomodoro application. I know there are plenty of them in the app store, but none of them seem to be exactly what I want.

One of the things that I want to be able to do is add multiple saved timers. I like to use different time blocks depending on the activity. For an admin session I like to limit my block to 25 minutes. When I am writing code I like to have a 75 minute block so that I have time to get in the flow.

Creating the Section view to display the saved timers was pretty easy using ForEach and NavigationLink:

1
2
3
4
5
6
7
8
9
10
Section(header: Text("Saved Timers")) {
	ForEach(timers) { timer in
		NavigationLink(timer.name) {
			SessionEditorView(timer: timer)
				.navigationBarBackButtonHidden(true)
		}
	}
	.onDelete(perform: deleteTimer)
}
.headerProminence(.increased)

This results in a section in my list that looks like this:

SavedTimers.png Initial Form

Of course having a list to edit is great, but I need to be able to add new ones as well. So I started playing around with having a button as the first entry. The trick here was to still be able to use the NavigationLink but having a + rather than the >. This was a little trickier.

1
2
3
4
5
6
7
8
9
10
11
Section(header: Text("Saved Timers")) {
ZStack {
	HStack {
		Text("Add Timer")
		Spacer()
		Image(systemName: "plus")
	}
	.foregroundColor(.blue)
	NavigationLink("", destination: SessionEditorView(timer: nil).navigationBarBackButtonHidden(true))
		.opacity(0)
}

This resulted in the ability to add new timers. I was getting closer to what I wanted, but I still did not really like it.

SavedTimers.png Add Form

What I really wanted was to have a + to the right of the Saved Timers section header. That way I wasn’t wasting one of the rows in my list on a button. I also thing it looks nicer. After searching around and some trial and error, I was able to get exactly what I want.

The first thing that I did was create a new struct called ButtonView that contained a HStack with the text and button I want to display.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct ButtonView: View {
    var body: some View {
        HStack {
            Text("Saved Timers")
            Spacer()
            Button {
            } label: {
                NavigationLink(destination: TimerEditorView(timer: nil).navigationBarBackButtonHidden(true)) {
                    Image(systemName: "plus")
                }
                
            }
        }
    }
}

Then I just added the ButtonView to the header of the Section.

1
2
3
4
5
6
7
8
9
Section(header: ButtonView()) {
    ForEach(timers) { timer in
        NavigationLink(timer.name) {
            TimerEditorView(timer: timer)
                .navigationBarBackButtonHidden(true)
        }
    }
    .onDelete(perform: deleteTimer)
}

Now I have a nice and pretty add button for my Saved Timers section.

SavedTimersFinal.png Final Form

If you know a better way, I’d love to hear it. Leave a comment below.

Comments powered by Disqus.