Rob N
Rob N

Reputation: 16409

SwiftUI stop Divider from expanding vertically in HStack

I'm using SwiftUI to create something like an alert popup, which I present from UIKit code using UIHostingController. The view looks like this:

VStack(spacing: 0) {
    // Some text ...   

    HStack(spacing:0) {
        Button(action: self.onCancel) { Text("Cancel") }
           .padding().inExpandingRectangle().fixedSize(horizontal: false, vertical: true)

        // This divider is the problem
        Divider() // .fixedSize()

        Button(action: self.onDelete) {  Text("Delete") }
           .padding().inExpandingRectangle().fixedSize(horizontal: false, vertical: true)
    }
}.frame(minHeight: 0)

The inExpandingRectangle is something I found in another stackoverflow question. It centers the text in each side of the HStack.

extension View {
    func inExpandingRectangle() -> some View {
        ZStack {
            Rectangle().fill(Color.clear)
            self
        }
    }
}

It looks like this. Garbage.

enter image description here

If I put the .fixedSize() on the divider, it does this. Not horrible, but the divider is stupid looking and doesn't expand to the size of the buttons.

enter image description here

Upvotes: 29

Views: 10561

Answers (4)

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119302

💡 Alternative: without fixedSize modifier

Since fixedSize invalidates the expanding behavior of all content and you may not want this, you can use a simple overlay modifier and add the divider there:

HStack(spacing:0) {
    Button(action: { }) { Text("Cancel").frame(maxWidth: .infinity) }

    /* Divider() */ // 👈 1. Get rid of this

    Button(action: { }) { Text("Delete").frame(maxWidth: .infinity) }
}
.overlay { HStack { Divider() } } // 👈 2. Add it like this

Note that I wrapped the divider inside a simple HStack to make it grow vertically.

Upvotes: 0

Asperi
Asperi

Reputation: 257711

Here is a demo of possible simplified alternate, without that artificial extension. Tested with Xcode 11.4 / iOS 13.4.

demo

Divider() // or Rectangle().fill(Color.gray).frame(height: 1)
HStack {
    Button(action: {}) { Text("Cancel").fixedSize() }
        .padding().frame(maxWidth: .infinity)

    Divider() // or Rectangle().fill(Color.gray).frame(width: 1)

    Button(action: {}) {  Text("Delete").fixedSize() }
        .padding().frame(maxWidth: .infinity)

}.fixedSize(horizontal: false, vertical: true)

Note: It worth also to consider custom divider, like

Rectangle().fill(Color.gray).frame(width: 1) // or any other color

than might give much appropriate visual feedback, like

demo2

Upvotes: 33

Rohit Makwana
Rohit Makwana

Reputation: 4875

You can try below code hope its help you (Xcode 11.2.1)

Note: Change Font, Frame and Color as per your requirement

var body: some View {

    VStack(spacing: 0) {

        Text("Delete")
            .font(Font.system(size: 20, weight: .bold))

        Text("Are you sure you want to delete ?")
            .font(Font.system(size: 18, weight: .regular))
            .padding([.top,.bottom], 15)

        Rectangle().fill(Color.gray.opacity(0.5)).frame(height:0.5)

        HStack(spacing:0) {

            Button(action: {
                //Your action
            }) {
                Text("Cancel")
                    .foregroundColor(Color.black)
                    .font(Font.system(size: 18, weight: .medium))
            }
            .frame(minWidth: 150, maxWidth: .infinity, minHeight: 40, maxHeight: 40, alignment: .center)

            Rectangle().fill(Color.gray.opacity(0.5)).frame(width:0.5,height:20)

            Button(action: {
                //Your action
            }) {
                Text("Delete")
                    .font(Font.system(size: 18, weight: .medium))
                    .foregroundColor(Color.red)
            }
            .frame(minWidth: 150, maxWidth: .infinity, minHeight: 40, maxHeight: 40, alignment: .center)
        }
    }
}

Output :

enter image description here

Upvotes: 0

sfung3
sfung3

Reputation: 2377

Putting a fixedSize() modifier on the HStack instead of the Divider fixies the problem.

    var body : some View {
        VStack(spacing: 0) {
            // Some text ...
            Text("gsfdsfkajflkasdjflkas,jdflaskjf")
            HStack(spacing:0) {
                Button(action: {print("hi")}) { Text("Cancel") }
                    .padding().inExpandingRectangle().fixedSize(horizontal: true, vertical: true)

                // This divider is the problem
                Divider()


                Button(action: {print("hello")}) {  Text("Delete") }
                    .padding().inExpandingRectangle().fixedSize(horizontal: true, vertical: true)
            }.fixedSize()        <------- Insert this
        }.frame(minHeight: 0)
    }

Result:

enter image description here

Upvotes: 11

Related Questions