0

I'm creating a scrollable selection bar. I would like a selection indicator under the text to match the width of the text rect above it. So in the image below, the red would fit the full width of the black area.

import SwiftUI

struct TabSelectionView: View {
    let tabs: [String]
    @State var selectedIndex: Int
    
    var tabHeight: CGFloat = 40
    var tabHorizontalPadding: CGFloat = 8
    var tabVerticalPadding: CGFloat = 16
    var selectedTabColor = Color.primary
    var selectedTextColor = Color.white
    var unselectedTabColor = Color.gray
    var unselectedTextColor = Color.black
    var selectionBarColor = Color.red
    var selectionBarHeight: CGFloat = 4
    
    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 0) {
                ForEach(0..<tabs.count, id: \.self) { index in
                    tabView(for: index)
                }
            }
        }
    }
    
    private func tabView(for index: Int) -> some View {
        let isSelected = index == selectedIndex
        let tabColor = isSelected ? selectedTabColor : unselectedTabColor
        let textColor = isSelected ? selectedTextColor : unselectedTextColor
        let barColor = isSelected ? selectionBarColor : unselectedTabColor
        
        return VStack(spacing: 0) {
            Text(tabs[index])
                .foregroundColor(textColor)
                .padding(.horizontal, tabHorizontalPadding)
                .padding(.vertical, tabVerticalPadding)
                .background(tabColor)
                .frame(height: tabHeight - selectionBarHeight)
            
            if selectionBarHeight > 0 {
                Rectangle()
                    .foregroundColor(barColor)
                    .frame(maxWidth: .infinity)
                    .frame(height: selectionBarHeight)
            }
        }
        .contentShape(Rectangle())
        .onTapGesture {
            selectedIndex = index
        }
        
    }
}

struct TabSelectionView_Previews: PreviewProvider {
    static var previews: some View {
        let tabs1 = ["All", "Grouping 1", "Grouping 2", "Grouping 3", "Sub Grouping 1", "Grouping 4", "Groupint 5", "Sub Grouping 2"]
                
        TabSelectionView(tabs: tabs1, selectedIndex: .constant(0))
            .previewLayout(PreviewLayout.sizeThatFits)
    }
}

Tab Selection Bar

Aaron Bratcher
  • 6,051
  • 2
  • 39
  • 70

0 Answers0