SwiftUI horizontal alignment from center to the right

谁都会走 提交于 2021-01-29 11:42:50

问题


I am trying to align a dynamic collection (ie of varying count) of views to the right of a centered view, without moving the center view from its original, center position.

For example, the center view is Text("12") and the views to the right are [Text("+3"), Text("+10"), Text("-1")] so I want the views to the right of 12 be displayed to its right, while 12 is centered horizontally on the screen:

| 12 +3 +10 -1 |

If I try using an HStack the 12 will move away from center. Is there a view modifier I can use? ex. Text("12").alignToRight(...)

This solution aligns the collection to the left of the right edge of the screen, but that's not the same thing.

ZStack {
  Text("12")

  HStack(spacing: 4) {
    Spacer()
    Text("+3")
    Text("+10")
    Text("-1")
  }
}

I would prefer not to have to duplicate the HStack on the left side and then make it disappear so as to balance the HStack on the right (that is a ridiculous way of creating a layout, plus the example I'm providing here is simple, in actuality I have to use a ForEach over the dynamic collection), ie

HStack {

  Spacer()

  HStack(spacing: 4) {
    Spacer()
    Text("+3")
    Text("+10")
    Text("-1")
  }
  .opacity(0)

  Text("12")

  HStack(spacing: 4) {
    Spacer()
    Text("+3")
    Text("+10")
    Text("-1")
  }

  Spacer()

}

Using something like Text("12").overlay(myCollectionView.offset(x: 16) is also winging it, as the font size of the center text will vary, and so I'd have to guess and adjust the offset manually as well -- I'd rather have a padding between the two views.


回答1:


Here is possible approach based on alignment guides. Tested with Xcode 11.3 / iOS 13.3.

demo

Define custom alignment

extension HorizontalAlignment {
   private enum HCenterAlignment: AlignmentID {
      static func defaultValue(in dimensions: ViewDimensions) -> CGFloat {
         return dimensions[HorizontalAlignment.center]
      }
   }
   static let hCenterred = HorizontalAlignment(HCenterAlignment.self)
}

align needed element of internal HStack to external VStack using custom alignment guide

struct TestRightCenterred: View {
    var body: some View {
        GeometryReader { gp in
            VStack(alignment: .hCenterred) {
                HStack(spacing: 4) {
                    Text("12").border(Color.red) // << just for test
                        .alignmentGuide(.hCenterred, computeValue: { $0.width / 2.0 })
                    Text("+3")
                    Text("+10")
                    Text("-1")
                }
            }
            .frame(maxWidth: gp.size.width, alignment: Alignment(horizontal: .hCenterred, vertical: .center))
        }
    }
}



回答2:


I was struggling with same problem and come with this solution

struct ContentView: View {
    var body: some View {
        HStack(spacing: 4) {
            HStack {               //HStack1
                Spacer()
                Spacer()
            }
            
            Text("12")
            
            HStack(spacing: 4) {   //HStack2
                Text("+3")
                Text("+10")
                Text("-1")
                Spacer()
            }
        }
    }
}

This code cause "HStack1" and "HStack2" have same width, I got this understanding from this answer

Two Spacers in Hstack1 are needed because one is ignored without other content (can be changed on empty Text("") for example, but I prefer Spacer)



来源:https://stackoverflow.com/questions/60710872/swiftui-horizontal-alignment-from-center-to-the-right

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!