FunctionalTableData icon indicating copy to clipboard operation
FunctionalTableData copied to clipboard

Feature request: TableCell highlighting

Open runmad opened this issue 6 years ago • 9 comments

UITableViewCells have a function built in: setHighlighted(_ highlighted: Bool, animated: Bool)`, which allows you to manipulate any subviews as needed when the user touches down on a cell.

With FunctionalTableData, this callback does not occur for free. There's currently no way in a HostCell implementation to override this callback.

The most common use case is when you have a UIView or UIImageView with an opaque background color. On highlight, UITableViewCell will automatically remove the background color for any subviews to ensure the selection color is visible. In the cases where you want to retain the background color of any subviews during selection and highlighting with a UITableViewCell you'd simply override setHighlighted and ensure the background is set for either state.

CellActions currently provides some state overriding, such as SelectionState, however none exist for a highlighted state.

I reckon something like the following would be good:

public typealias HighlightingAction = (_ sender: UIView, highlighted: Bool) -> HighlightingState

with

public enum HighlightingState {
	case highlighted
	case unhighlighted
}

At the same time, I do see two callbacks for selection/deselection, so highlighting could have the same two, or perhaps selection could be reconfigured to one callback to have the two be the same:

public typealias SelectionAction = (_ sender: UIView, selected: Bool) -> SelectionState

runmad avatar Apr 23 '19 03:04 runmad

Contemplating this one a bit now. If we hook into it with an action similar to SelectionAction you lose a bit of the type safety in that your view would come through as a UIView and would require a force/optional cast to the expected type before digging into the view hierarchy to manipulate backgroundColor.

I wonder if we should change the signature of the update function: func update(cell: UITableViewCell, in tableView: UITableView)

to be more along the lines of func update(cell: UITableViewCell, in tableView: UITableView, context: UpdateContext)

UpdateContext could then be something along the lines of

enum UpdateContext {
    case default // the regular old case of just updating the data
    case selection // maybe?
    case highlight
    case ... // I don't know, are there more cases? begin a drag? move? edit mode initiated on the table...
}

FunctionalTableData Delegate/Datasource's would then, on highlight/select/etc calls trigger this. HostCell would then have its own implementation of this and the cellUpdater function would be extended to support the context argument. This would then mean that the update function would be passed a concrete view type, the state, and the context.

I think this could be introduced in a backwards compatible way as well.

@runmad thoughts? @raulriera could use your opinions here as well

g-Off avatar Apr 23 '19 21:04 g-Off

I really like that suggestion!

With the actions, I definitely feel like we're missing parts of what comes for free with UITableViewCell callbacks on selection and highlighting within the view itself.

I think starting with selection/highlighting seems appropriate for now and more closely resemble func setSelected(Bool, animated: Bool) and func setHighlighted(Bool, animated: Bool).

Is this somewhat related to https://github.com/Shopify/FunctionalTableData/issues/54?

runmad avatar Apr 23 '19 21:04 runmad

The highlight delegate methods are:

func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool
func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath)

returning false on the shouldHighlightRowAt "halts the selection process and does not cause the currently selected row to lose its selected look while the touch is down"

didHighlightRowAt might be called after the highlight is finished, which is possibly too late and the highlight animation on the cell may have finished. I don't currently have time at the moment to dig into the nuances of these functions vs UITableViewCell's func setHighlighted(_ highlighted: Bool, animated: Bool). If the delegate one triggers at the right time then that's the better one to tie into as it would no longer require any special implementation on the cell level. If the setHighlighted is the right spot then we'd need to have our TableCell implementation (that backs HostCell) implement that behaviour (a bit more annoying but doable as well).

And yeah, this could be somewhat related to #54 as it could be one of the cases used in the Context enum

g-Off avatar Apr 23 '19 21:04 g-Off

That's true. I suppose this ties in a bit with functionality in FunctionalTableData+Cells.swift

runmad avatar Apr 23 '19 21:04 runmad

The Context change will be a good addition, but complexity for implementing a cell will skyrocket. Now we are dealing with many more "states". I would be inclined for some magic here, an UIView extension for shouldHighlightItem and didHighlightItem that HostCell automatically call to all its subviews.

This will have to work with highlight from CellStyle to shut it down I assume, otherwise we will have multiple "highlight" API

raulriera avatar Apr 24 '19 14:04 raulriera

@g-Off @raulriera any thoughts on this?

runmad avatar Jun 27 '19 19:06 runmad

Looks like iOS 13 changes the way highlighting works, which affects CellConfigs

runmad avatar Sep 24 '19 21:09 runmad

Looks like iOS 13 changes the way highlighting works

How did they change?

raulriera avatar Sep 24 '19 21:09 raulriera

For example:

Selections don't show up here using functionalTableData.select(keyPath:animated:) image

and when tapping: image

runmad avatar Sep 24 '19 21:09 runmad