การจัดตำแหน่งข้อความ SwiftUI


97

จากคุณสมบัติมากมายของTextมุมมองฉันไม่พบสิ่งใดที่เกี่ยวข้องกับการจัดแนวข้อความ ฉันเคยเห็นในการสาธิตว่ามันจัดการ RTL โดยอัตโนมัติและเมื่อวางสิ่งของโดยใช้ View's bodyมันจะตั้งศูนย์โดยอัตโนมัติเสมอ

มีแนวคิดบางอย่างที่ฉันขาดหายไปเกี่ยวกับระบบเลย์เอาต์ในSwiftUIและถ้าไม่มีฉันจะตั้งค่าคุณสมบัติการจัดแนวข้อความเป็นTextอย่างไร

คำตอบ:



96

จาก SwiftUI beta 3 ไปข้างหน้าคุณสามารถจัดกึ่งกลางมุมมองข้อความด้วยตัวปรับแต่งเฟรม:

Text("Centered")
    .frame(maxWidth: .infinity, alignment: .center)

49

พยายามที่จะเข้าใจสิ่งนี้ด้วยตัวเองเนื่องจากคำตอบอื่น ๆ ที่นี่กล่าวถึงText.multilineTextAlignment(_:)/ VStack(alignment:)/ frame(width:alignment:)แต่แต่ละวิธีแก้ปัญหาเฉพาะ ในที่สุดก็ขึ้นอยู่กับความต้องการ UI และการรวมกันของสิ่งเหล่านี้


VStack(alignment:)

alignmentนี่คือมุมมองด้านในที่เกี่ยวข้องกับอีกคนหนึ่ง
ดังนั้นการระบุ.leadingจะเชื่อมโยงมุมมองภายในทั้งหมดให้มีแกนนำสอดคล้องกัน

VStack(alignment: .leading, spacing: 6) {
  Text("Lorem ipsum dolor")
        .background(Color.gray.opacity(0.2))
  Text("sit amet")
        .background(Color.gray.opacity(0.2))
}
.background(Color.gray.opacity(0.1))

ภาพ


.frame

ในframe(width:alignment:)หรือframe(maxWidth:alignment:)ที่alignmentสำหรับเนื้อหาภายในความกว้างที่กำหนด

VStack(alignment: .leading, spacing: 6) {
  Text("Lorem ipsum dolor")
      .background(Color.gray.opacity(0.2))
  Text("sit amet")
      .background(Color.gray.opacity(0.2))
}
.frame(width: 380, alignment: .trailing)
.background(Color.gray.opacity(0.1))

มุมมองชุดชั้นในจะนำชิดที่เกี่ยวข้องกับอีกคนหนึ่ง VStackแต่มุมมองของตัวเองจะถูกลากชิดที่เกี่ยวข้องกับ

ภาพ


.multilineTextAlignment

สิ่งนี้ระบุการจัดแนวของข้อความภายในและสามารถมองเห็นได้ดีที่สุดเมื่อมีหลายบรรทัดเป็นอย่างอื่นโดยไม่มีการกำหนดframe(width:alignment)ความกว้างจะถูกปรับโดยอัตโนมัติและได้รับผลกระทบจากค่าเริ่มต้นalignments

VStack(alignment: .trailing, spacing: 6) {
  Text("0. automatic frame\n+ view at parent's specified alignment\n+ multilineTA not set by default at leading")
    .background(Color.gray.opacity(0.2))
  Text("1. automatic frame\n+ view at parent's specified alignment\n+ multilineTA set to center")
  .multilineTextAlignment(.center)
  .background(Color.gray.opacity(0.2))
  Text("2. automatic frame\n+ view at parent's specified alignment\n+ multilineTA set to trailing")
  .multilineTextAlignment(.trailing)
  .background(Color.gray.opacity(0.2))
}
.frame(width: 380, alignment: .trailing)
.background(Color.gray.opacity(0.1))

ภาพ


การทดสอบด้วยชุดค่าผสม:

VStack(alignment: .trailing, spacing: 6) {
  Text("1. automatic frame, at parent's alignment")
  .background(Color.gray.opacity(0.2))
  Text("2. given full width & leading alignment\n+ multilineTA at default leading")
  .frame(maxWidth: .infinity, alignment: .leading)
  .background(Color.gray.opacity(0.2))
  Text("3. given full width & center alignment\n+ multilineTA at default leading")
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("4. given full width & center alignment\n+ multilineTA set to center")
  .multilineTextAlignment(.center)
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("5. given full width & center alignment\n+ multilineTA set to trailing")
  .multilineTextAlignment(.trailing)
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("6. given full width but no alignment\n+ multilineTA at default leading\n+ leading is based on content, looks odd sometimes as seen here")
  .frame(maxWidth: .infinity)
  .background(Color.gray.opacity(0.2))
}
.frame(width: 380)
.background(Color.gray.opacity(0.1))

ภาพ


1
นั่นเป็นคำตอบที่น่าสนใจมาก ขอขอบคุณ. ฉันจะพิจารณาให้คำตอบนี้เป็นที่ยอมรับเช่นกัน
inokey

1
@inokey ยินดีที่จะแบ่งปันข้อสังเกตของฉัน :) ต่อมาฉันพบบทความที่น่าสนใจในเชิงลึกมากขึ้นด้วยการจัดตำแหน่งมุมมองโดยทั่วไป: Alignment Guides ใน SwiftUI
staticVoidMan

คนน่ากลัว SwiftUI พัฒนาขึ้นอย่างมากตั้งแต่ฉันโพสต์คำถามนั้นครั้งแรก
inokey

17

ฉันพบปัญหาที่ต้องจัดแนวข้อความในบรรทัดเดียว สิ่งที่ฉันพบว่าได้ผลคือ:

Text("some text")
    .frame(alignment: .leading)

หากคุณรวมสิ่งนี้กับพารามิเตอร์ความกว้างของเฟรมคุณจะได้รับการจัดรูปแบบบล็อกข้อความที่ดีสำหรับป้ายกำกับและอื่น ๆ


15

ฉันเดาว่าSwiftUIต้องการให้เราใช้เครื่องห่อเหมือนกองสำหรับสิ่งเหล่านี้

ดังนั้นแทนที่จะเขียนสิ่งที่ชอบText("Hello World").aligned(.leading)ขอแนะนำสิ่งต่อไปนี้:

VStack(alignment: .leading) {
    Text("Hello World")
}

1
ฉันจึงไม่สามารถวางป้ายกำกับที่ไม่ขึ้นกับกองได้?
inokey

@inokey ฉันไม่พบตัวปรับแต่งสำหรับสิ่งนี้อย่างน้อย
fredpi

ฉันไม่ได้ทำเช่นกัน ดูเหมือนว่าฉันจะพลาดแนวคิดพื้นฐานบางอย่างจาก SUI ฉันไม่สามารถแม้แต่จะวาง "มุมมอง" ระหว่างสองสิ่งและให้มันเป็นสีได้เช่นพวกเขาไม่มีวัตถุ a-la-uiview ธรรมดาอยู่ในนั้น
inokey

ตัวปรับแต่งเฟรมมีพารามิเตอร์การจัดตำแหน่ง
EmilioPelaez

ดูเหมือนจะโง่ที่ต้องทำ (แม้ว่าจะได้ผล) คุณได้ยินสิ่งนี้มาจากไหน?
MobileMon

6

เราจำเป็นต้องจัดแนวข้อความไม่ใช่กองที่อยู่ดังนั้นการโทรmultilineTextAlignment(.center)และการตั้งค่าขีด จำกัด บรรทัดฉันจึงสามารถเห็นข้อความที่จัดชิดกึ่งกลางได้ ฉันไม่รู้ว่าทำไมฉันต้องตั้งขีด จำกัด บรรทัดฉันคิดว่ามันจะขยายได้ถ้าคุณมีข้อความขนาดใหญ่

Text("blahblah")
        .font(.headline)
        .multilineTextAlignment(.center)
        .lineLimit(50)

6

หากคุณต้องการคงความกว้างของข้อความไว้ให้คงที่ ".multilineTextAlignment (.leading)" จะไม่มีผลใด ๆ จนกว่าจะมีข้อความเพียงบรรทัดเดียว

นี่คือวิธีแก้ปัญหาที่เหมาะกับฉัน:

struct LeftAligned: ViewModifier {
    func body(content: Content) -> some View {
        HStack {
            content
            Spacer()
        }
    }
}


extension View {
    func leftAligned() -> some View {
        return self.modifier(LeftAligned())
    }
}

การใช้งาน:

Text("Hello").leftAligned().frame(width: 300)

4

คุณสามารถตั้งค่าการจัดแนวสำหรับ Vertical stackView เป็นชั้นนำ เช่นด้านล่าง

 VStack(alignment: .leading) {
            Text("Turtle Rock")
                .font(.title)
            Text("Joshua Tree National Park")
                .font(.subheadline)
        }

ป้อนคำอธิบายภาพที่นี่


2

ฉันต้องการใช้Spacer()มุมมองเพื่อจัดแนวบล็อกข้อความ ตัวอย่างนี้แสดงข้อความที่ด้านท้าย:

HStack{
    Spacer()
    Text("Wishlist")
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.