最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - How to create in SwiftUI a CenterAligned Navbar where the title goes centralised even with leading and trailing content

programmeradmin1浏览0评论

I'm trying to create a Navbar that has a leading and trailing view and my title at center or left aligned.

At the beginning I was trying to do so with a simple HStack:

Hstack{
   leading()
      .frame(alignment: .leading)
   Spacer()
   title()
   Spacer()
   trailing()
      .frame(alignment: .trailing)
}

The problem here is that the leading and trailing they are: 1 - Optional, some cases only the lading can be present and no trailing 2 - Different widths leading can be bigger than trailing and vice versa

So it can cause the issue where the title is not correctly center aligned.

So what I tried was the following:

    @State var widthNavigation: CGFloat = 0.00
    @State var widthActions: CGFloat = 0.00
    @State var titleWidth: CGFloat = 0.00
    @State var totalWidth: CGFloat = 0.00

    public var body: some View {
      HStack(alignment: .center, spacing: 0) {
        navigationIcon()
          .background(GeometryReader { geoNav in
            Color.clear.onAppear { self.widthNavigation = geoNav.size.width }
          })

        title()
          .background(GeometryReader { geoTitle in
            Color
              .clear
              .onAppear {
                titleWidth = geoTitle.size.width
              }
            }
          )
          .offset(
            x: totalWidth/2 - titleWidth/2
          )

        actions()
          .background(GeometryReader { geoAct in
            Color.clear.onAppear { self.widthActions = geoAct.size.width }
          })
      }
      .background(
        GeometryReader { geometry in
          Color.clear.onAppear { self.totalWidth = geometry.size.width }
        }
      )
      .frame(maxWidth: .infinity)
      .padding(.horizontal, 8)
    }

Basically this code get the width of the views and tries to infer an offset to the title. (I've tried many different offset logic but still

This is what I need to achieve:

This is my result in general:

I'm trying to create a Navbar that has a leading and trailing view and my title at center or left aligned.

At the beginning I was trying to do so with a simple HStack:

Hstack{
   leading()
      .frame(alignment: .leading)
   Spacer()
   title()
   Spacer()
   trailing()
      .frame(alignment: .trailing)
}

The problem here is that the leading and trailing they are: 1 - Optional, some cases only the lading can be present and no trailing 2 - Different widths leading can be bigger than trailing and vice versa

So it can cause the issue where the title is not correctly center aligned.

So what I tried was the following:

    @State var widthNavigation: CGFloat = 0.00
    @State var widthActions: CGFloat = 0.00
    @State var titleWidth: CGFloat = 0.00
    @State var totalWidth: CGFloat = 0.00

    public var body: some View {
      HStack(alignment: .center, spacing: 0) {
        navigationIcon()
          .background(GeometryReader { geoNav in
            Color.clear.onAppear { self.widthNavigation = geoNav.size.width }
          })

        title()
          .background(GeometryReader { geoTitle in
            Color
              .clear
              .onAppear {
                titleWidth = geoTitle.size.width
              }
            }
          )
          .offset(
            x: totalWidth/2 - titleWidth/2
          )

        actions()
          .background(GeometryReader { geoAct in
            Color.clear.onAppear { self.widthActions = geoAct.size.width }
          })
      }
      .background(
        GeometryReader { geometry in
          Color.clear.onAppear { self.totalWidth = geometry.size.width }
        }
      )
      .frame(maxWidth: .infinity)
      .padding(.horizontal, 8)
    }

Basically this code get the width of the views and tries to infer an offset to the title. (I've tried many different offset logic but still

This is what I need to achieve:

This is my result in general:

Share Improve this question edited Nov 20, 2024 at 10:13 Benzy Neez 22.6k3 gold badges15 silver badges43 bronze badges asked Nov 20, 2024 at 6:23 José CaiqueJosé Caique 111 silver badge1 bronze badge 5
  • 1 This answer might help: SwiftUI view adding trailing and leading icons – Benzy Neez Commented Nov 20, 2024 at 6:56
  • @BenzyNeez In your custom header example in linked answers, how to deal with case where title is too long? – duckSern1108 Commented Nov 20, 2024 at 7:25
  • @duckSern1108 If the text is long then I would suggest applying some horizontal padding to reserve space for the buttons, like in this answer. If you want the long text to be truncated instead of wrapping then apply .lineLimit(1). – Benzy Neez Commented Nov 20, 2024 at 8:41
  • @BenzyNeez but there will be the case if left View or right View width is too large. I think for this case, it might be better if we use UIView :D – duckSern1108 Commented Nov 20, 2024 at 9:11
  • 1 @duckSern1108 Answer added, which addresses the issue of a long title too. – Benzy Neez Commented Nov 20, 2024 at 10:41
Add a comment  | 

1 Answer 1

Reset to default 2

I would suggest splitting the buttons and the title into two layers, so that the title is independent of the buttons.

A ZStack can be used to combine the two layers:

ZStack {
    HStack {
        navigationIcon()
        Spacer()
        actions()
    }
    title()
}
.padding(.horizontal, 8)

If there is any risk that the title may be long and overlap with one of the icon groups, then you could reserve space for the buttons using hidden copies. Since you don't know which group will be the widest, you can use another ZStack to build the footprint:

private var footprintForIcons: some View {
    ZStack {
        navigationIcon()
        actions()
    }
    .disabled(true)
    .hidden()
}

This is then used as followss:

ZStack {
    HStack {
        navigationIcon()
        Spacer()
        actions()
    }
    HStack {
        footprintForIcons
        title()
        footprintForIcons
    }
}
.padding(.horizontal, 8)

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论