1

I'm creating a settings view that lists "libraries" you can select.

My main question is, how do you space the right-hand side view to be something like the (second) screenshot I attached below? It should essentially push the buttons and list to the left side, making the right side view use all the space there is. The current setup I'm working with is like so:

struct LibrarySettingsView: View {

    @State private var libraryInstallations = [Library]()
    @State private var selectedListItem: Library?

    // ... (constants)

    var body: some View {
        Form {
            HStack {
                VStack {
                    Button("Add library...", action: /* addLibrary */)
                    Button("Remove", action: /* removeLibrary */)
                        .disabled(selectedListItem == nil)
                    Spacer()
                }
                
                List(selection: $selectedListItem) {
                    ForEach(libraryInstallations) { library in
                        Text(library.name)
                            .tag(library)
                    }
                }
                .border(SeparatorShapeStyle())

                VStack {
                    // I'd guess a NavigationLink would be the better option right here
                    // as it would be more "native" with the examples I've already seen
                    if selectedListItem != nil {
                        // ... (view)
                    } else {
                        Text("No Item Selected")
                    }
                }
            }
        }
        .frame(width: 300)
    }

    // ... (functions)
}

(I removed a few irrelevant options.)

enter image description here

The style I'd like to go for is something like this, with the right side utilising the entire rest of the view. (Bonus: is there a native way to add this sort of "embed" around the right-hand side content?):

enter image description here

Smally
  • 1,556
  • 1
  • 8
  • 27

2 Answers2

2
struct LibraryList: View {

    @AppStorage("libraryInstallations") private var libraryInstallations = [/* LibrarySettingsView.Library */]()

    @Binding var selectedListItem: /* LibrarySettingsView.Library */?

    var body: some View {
        VStack {
            List(selection: $selectedListItem) {
                ForEach(libraryInstallations) { library in
                    Text(library.name)
                        .tag(library)
                }
            }
            .padding(.bottom, 0)
            .border(SeparatorShapeStyle())
            
            HStack {
                Button(action: addLibrary) {
                    Image(systemName: "plus")
                        .frame(width: 12.5, height: 12.5)
                }
                
                Button(action: removeLibrary) {
                    Image(systemName: "minus")
                        // Custom frame needed to get a better clickbox
                        .frame(width: 12.5, height: 12.5)
                }
                .disabled(selectedListItem == nil)
                
                Spacer()
            }
            .buttonStyle(BorderlessButtonStyle())
            .padding(1)
        }
        .frame(width: 150)
    }

    func addLibrary() {
        // ...
    }

    func removeLibrary() {
        // ...
    }
}

To get the view to the left, you can use a Spacer in the parent view.

HStack {
    LibraryList(selectedListItem: $selectedListItem)

    if let selectedListItem = selectedListItem {
        /* LibraryTarget */(selectedListItem: selectedListItem)
    } else {
        // Text in the middle
        Spacer()
        Text("No Item Selected")
            .font(.title2)
    }

    // It's necessary to get the list to the left
    Spacer()
}

Finished result

Smally
  • 1,556
  • 1
  • 8
  • 27
1

looks like you search for this:

HStack (spacing:0) {
    VStack{
        Text("1")
    }
    .frame(minWidth: 150, maxHeight: .infinity)
    .background(Color.blue)
    
    
    VStack{
        Text("2")
    }
    .frame(minWidth: 150, maxHeight: .infinity)
    .background(Color.green)
    
    VStack{
        Text("3")
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .background(Color.red)
}
.frame(minWidth: 500)    

enter image description here

enter image description here

enter image description here

Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101
  • A `HSplitView` doesn't quite extend the edges of the right-side view, and it also lowers both the buttons and list down to a few lines. Is there some kind of "size to fit window" modifier for the right-side `VStack` (or a group of some sort)? – Smally Jun 19 '21 at 12:03
  • can you show on the screenshot what did you get with some notes directly on it? As I do not understand you clear enough – Andrew_STOP_RU_WAR_IN_UA Jun 19 '21 at 12:06
  • The change of `HSplitView` resulted in [this](https://imgur.com/a/zkoQ6WM) (compared to the first screenshot I attached in the question). I'd like something like [this example I created with photo-editing software](https://imgur.com/a/rep3cMu), much like the second screenshot I had attached in the question. – Smally Jun 19 '21 at 12:27
  • ok, so you need 3 horisontal blocks. This is easy. Do you need to have an ability to resize central block? or first 2 must to have a static size? – Andrew_STOP_RU_WAR_IN_UA Jun 19 '21 at 12:31
  • Horizontal blocks already created in the original question. First two can be static, and when resizing the window, behaviour should be that the view on the right should get extended. My question being, how does one space out that right view to utilise all the window (and pushes the two left ones to the edge of the left side)? – Smally Jun 19 '21 at 12:33
  • Ah, seems great! Is there a way to have the width of the two left views be dependant on the content of those views? Such as the button width, and default list width, for example? – Smally Jun 19 '21 at 12:47
  • yes, it's possible, but will be more tricky code. Need to measure content size of first 2 blocks and replace 400 with its width. – Andrew_STOP_RU_WAR_IN_UA Jun 19 '21 at 12:56
  • sth like here: https://stackoverflow.com/questions/56573373/swiftui-get-size-of-child – Andrew_STOP_RU_WAR_IN_UA Jun 19 '21 at 12:58
  • I have update the code to the better one. – Andrew_STOP_RU_WAR_IN_UA Jun 19 '21 at 14:59