Swiftpack.co - Package - franklynw/Listy

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.

franklynw/Listy

Replacement for SwiftUI List, with more customisation options

Listy

A replacement for SwiftUI List, which offers a number of benefits & customisation options

Example 1 Example 2 Example 3

Installation

Swift Package Manager

In Xcode:

Example

NB: All examples require import Listy at the top of the source file

var body: some View {

    ZStack {
        Listy(viewModel)
            .title(viewModel.title, color: viewModel.titleColor)
            .titleBarColor(viewModel.titleBarColor)
            .titleMenu(viewModel.titleBarContextMenuSections)
            .leftBarItem(.menu(menuSections: viewModel.leftBarItemContextMenuSections, iconName: Image.SystemName.ellipsis))
            .rightBarItem(.button(iconName: Image.SystemName.plus, action: viewModel.addItem))
            .allowsRowDragToReorder(viewModel.canReorderRows)
            .onTapped(viewModel.completeItem)
            .itemContextMenuItems(viewModel.itemContextMenuItems)
            .refresh(viewModel.reloadTable)
    }
    .actionSheet(isPresented: $isShowingActionSheet) {
        ActionSheet(
            title: Text("Settings"),
            message: nil,
            buttons: viewModel.settingsButtons()
        )
    }
}

Initialise

public init(_ viewModel: DataSource)

The viewModel must conform to the ListyDataSource protocol, and the list items to the ListyIdentifiableView protocol

Set the title

You can provide a title for the list, which will make it appear like the example images at the top. If no title is provided, it appears as a list only. The parameters are bindings to model vars

Listy(viewModel)
    .title(viewModel.title, color: viewModel.titleColor)

Set the title bar colour

If you provide a title, you can set the colour of the title bar. If no title is provided and you use this, nothing will happen. The parameter is a binding to a model var

Listy(viewModel)
    .title(viewModel.title, color: viewModel.titleColor) // the title is needed or it's a no-op
    .titleBarColor(viewModel.titleBarColor)

Provide title context menu items

If you provide a title, you can also give it a context menu. If no title is provided and you use this, nothing will happen

Listy(viewModel)
    .title(viewModel.title, color: viewModel.titleColor) // the title is needed or it's a no-op
    .titleMenu(viewModel.titleBarContextMenuSections)

Left and right "barButtonItems"

If you provide a title, you can also have left & right bar buttons. If no title is provided and you use this, nothing will happen

Listy(viewModel)
    .title(viewModel.title, color: viewModel.titleColor) // the title is needed or it's a no-op
    .leftBarItem(.menu(menuSections: viewModel.leftBarItemContextMenuSections, iconName: Image.SystemName.ellipsis))
    .rightBarItem(.button(iconName: Image.SystemName.plus, action: viewModel.addItem))

You have the option of adding the item as a button or as a menu, as shown above

Enable or disable row reordering by dragging

This can be switched on or off, with a binding to the model Bool var

Listy(viewModel)
    .allowsRowDragToReorder(viewModel.canReorderRows)

Item moved action

Will be invoked after an item has been dragged & reordered ** NOT IMPLEMENTED YET **

Listy(viewModel)
    .onMove {
        viewModel.itemMoved($0, $1)
    }

Item delete action

This is invoked if the user swipes to delete an item. The swipe-to-delete functionality doesn't appear unless this action is provided

Listy(viewModel)
    .onDelete(viewModel.deleteItem)

Item tapped action

Invoked when an item is tapped

Listy(viewModel)
    .onTapped(viewModel.completeItem)

Item context menus

Provide context menus for items in the list

Listy(viewModel)
    .itemContextMenu(viewModel.itemContextMenuSections)

List insets

Add insets around the list

Listy(viewModel)
    .contentInsets(EdgeInsets(top: 0, leading: 10, bottom: 30, trailing: 10))

Row padding

Add padding around the list rows

Listy(viewModel)
    .rowPadding(EdgeInsets(top: 5, leading: 0, bottom: 5, trailing: 0))

Observe the (vertical) content offset

If you need to react to the list's vertical content offset -

@State var offset: CGFloat = 0

then -

Listy(viewModel)
    .observeContentOffset($offset)

Force list refresh

If the viewModel toggles the refresh Bool, the list will be redrawn

Listy(viewModel)
    .refresh(viewModel.reloadTable)

ListyContextMenuItem

This is the struct used to define context menu items for the list & title. It has various options -

Initialise as an "action" row

public init(title: String, systemImage: String? = nil, shouldAppear: ((String) -> Bool)? = nil, action: @escaping (String) -> ())
  • title - the menu item's title
  • systemImage - the systemName of the icon for the menu item, if none is provided there will be no icon
  • shouldAppear - a closure which lets you control whether or not the menu item should be shown
  • action - invoked when the menu item is selected

Initialise as a "sub-menu" row

public init(title: String, systemImage: String? = nil, shouldAppear: ((String) -> Bool)? = nil, menuSections: @escaping (String) -> [ListyContextMenuSection])
  • title - the menu item's title
  • systemImage - the systemName of the icon for the menu item, if none is provided there will be no icon
  • shouldAppear - a closure which lets you control whether or not the menu item should be shown
  • subMenuItems - an array of ListyContextMenuItems for the sub-menu

Dependencies

Requires -

  • ButtonConfig, which is linked. GitHub page is here
  • FWCommonProtocols, which is linked. GitHub page is here

Included in the code is SwiftUITrackableScrollView - it's not included as a dependency as Swift Package Manager couldn't resolve an unversioned packed with Listy, which is versioned. In any case, take a look at it here as there's some clever stuff there.

Issues

There is one annoying issue (so far!) where if you drag to reorder, but release the item before moving it, the highlighted row remains highlighted. If anyone can figure out how to solve this, I'll be really happy...

License

Listy is available under the MIT license