Even with the images loading quickly and on demand and only getting each shape instead of every element, the Picker view was loading at an unacceptable speed. So I decided to use a list and allow the user to pick from that. This was an experience. The first thing I discovered is that once you go beyond the simplest View, a lot of things need to be explicitly defined.

It just works (if you don’t want to do anything complicated)

I started with a simple Text field for the shape ID and that worked well enough. You touch the row, it highlights, you touch the “Add” button and it does the thing. But I have a whole view for showing a piece and I would like to use it. But once I did that, the row no longer displayed a highlight when I clicked it, tapping the row didn’t select the item. Just nothing.

First, I learned I had to do my own tap handling. Not too big of a deal, the .onTapGesture is right there. You can define the body in a closure, set your selected property to the current property, and things are now selected. But even though the action was happening, there wasn’t any sort of indication that it had happened.

So I started messing around with various background settings and properties, but they would color just the area of the image and text and no further. It didn’t stretch to the edges of the row.

Eventually, I learned about .listRowBackground. It’s a property of a View that allows you to show a custom background for a list row item. First, a caveat. This is a property of the View you are using as the list item.

//Like this:
List(yourCollection) { current in
    MyComplexView(current).listRowBackground(Color.Red)
}

//Not this:
List(yourCollection) { current in
    MyComplexView(current)
}.listRowBackground(Color.Red)

I also put the property right on the end of the View rather than what seems to be the more idiomatic way just to emphasize which View it belongs to. And you have to do it on the View that is the direct child of the List. Eventually, I put my custom View inside another View but forgot to move the .listRowBackground and .onTapGesture properties and everything stopped working, again.

Now, something nice. As you can see in my example, I didn’t specify a full View. I just specified a Color. Because Colors are treated as Views. And since it’s a property of the row’s item view, you can use any information available to you. And we wind up with something like this

List(yourCollection) { current in
    MyComplexView(current)
        .onTapGesture(self.selectedItem = current)
        .listRowBackground(self.selectedItem == current ? Color.Red : Color.Blue)
}

Now that it works again, let’s break it again

What I want, what I really, really want is to be able to select individual colors as well. But I don’t want to clutter things up. So what I wanted was to be able to touch the piece and have the colors drop down underneath. Then be able to select from them.

Searching “Swift accordion”, “drop down thing Swift”, “expandable row item Swift” were all not getting me quite there. It’s hard to find something when you don’t quite have the words to describe what you want. Eventually, I found SwiftUI’s DisclosureGroup, which is pretty much what I want. And like all Views, you can specify anything for its content and label, including more Views.

Swift don’t flex

Now, what I was looking to do was to basically create a flexbox for the “Disclosure” part of it. The first thing I tried was to just ForEach the items, just see if it would do the thing I wanted. That was a disaster. It created a row for each with a divider in between each item. I looked into HStacks, VStacks, scrollable versions of both, but nothing is quite there. Eventually what I wound up doing was just creating a Grid and managing the columns and rows myself. There’s probably a better way, but for now, that’ll do pig.

Too many images

I realize that every view keeping a catalog of used images is probably not great. My next goal is to move the images to the central model data structure and load them as needed. I’ve started this process, but it causes the auto-updating nature of the views to fail. I have to first get that back.

By toast