Search code examples
iosswiftuitoolbarswiftui-navigationstackbottombar

Why bottom toolbar items placement is changing when i apply toolbar color scheme modifier in SwiftUI?


So when there is more than 2 toolbar items the default item placement is all the items (ToolbarItem) in the hierarchy to the left and the last item (ToolbarItem) in the hierarchy to the right.

After i apply .toolbarColorScheme(.light, for: .bottomBar) or .toolbarColorScheme(.dark, for: .bottomBar) modifier, and scroll all the way to the bottom, the 2nd item also goes to the right side.

//
//  ToolbarGlitchDemo.swift
//  ToolbarGlitchDemo
//
//  Created by rayhaanlykhan on 15/04/2024.
//

import SwiftUI

struct ToolbarGlitchDemo: View {
    
    var body: some View {
        
        NavigationStack {
            
            ZStack {
                
                Color.gray.ignoresSafeArea()
                
                ScrollView {
                    
                    ForEach(0..<15) { _ in
                        
                        Rectangle()
                            .fill(.blue)
                            .frame(width: 200, height: 200)
                            .frame(maxWidth: .infinity)
                    }
                }
            }
            .navigationTitle("Toolbar Glitch Demo")
            
            .toolbar {
                                
                ToolbarItem(placement: .bottomBar) { // center
                    
                    HStack {
                        Image(systemName: "scribble")
                        Image(systemName: "gear")
                    }
                    .background(.yellow)
                }
                
                ToolbarItem(placement: .bottomBar) {
                    
                    HStack {
                        Image(systemName: "person.fill")
                    }
                    .background(.red)
                }
                
                ToolbarItem(placement: .bottomBar) {
                    
                    HStack {
                        Image(systemName: "person")
                        Image(systemName: "person")
                    }
                    .background(.green)
                }
            }
            .toolbarColorScheme(.light, for: .bottomBar)
        }
    }
}

#Preview {
    ToolbarGlitchDemo()
}

Solution

  • Interesting! Since all 3 ToolbarItem are being given placement .bottomBar, the actual positions within the bottom bar are probably undefined.

    I discovered than when you add the images individually (in other words, as 5 ToolbarItem) then it starts off as 4+1 and switches to 1+4 when you scroll to the bottom -> also inconsistent.

    You can fix by setting one single ToolbarItem consisting of an HStack where you define the spacing:

    .toolbar {
        ToolbarItem(placement: .bottomBar) {
            HStack {
                HStack {
                    Image(systemName: "scribble")
                    Image(systemName: "gear")
                }
                .background(.yellow)
    
                Spacer()
    
                HStack {
                    Image(systemName: "person.fill")
                }
                .background(.red)
    
                Spacer()
    
                HStack {
                    Image(systemName: "person")
                    Image(systemName: "person")
                }
                .background(.green)
            }
        }
    }
    .toolbarColorScheme(.light, for: .bottomBar)