xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.62k stars 1.87k forks source link

[Enhancement] CollectionView: support highlight on touch-down #14103

Open softlion opened 3 years ago

softlion commented 3 years ago

Summary

On a collectionview's cell, both Android and iOS views have those independent properties:

The second one is used to temporarily highlight a cell that is touch down, for example triggering the ripple effect on android. Take note that a native view can be both selected and highlighted at the same time, leading to a different view state.

There is no such highlighted property in xamarin forms as there is no representation of the "cell" in a collectionview. And customizing the highlightning of a CollectionView's cell on touch down is nearly impossible on Forms.

API Changes

Add highlighted state to VSM Add IsCellHighlighted property to collectionview, or provide a way to access the underlying cell object from the datatemplate.

Intended Use Case

see above.

softlion commented 3 years ago

Adding a new state "highlighted" in states would do the trick.

in https://github.com/xamarin/Xamarin.Forms/blob/5.0.0/Xamarin.Forms.Platform.iOS/CollectionView/TemplatedCell.cs

public override bool Highlighted
{
    get => base.Highlighted;
    set
    {
        base.Highlighted = value;

        var element = VisualElementRenderer?.Element;

        if (element != null)
        {
            VisualStateManager.GoToState(element, value
                ? VisualStateManager.CommonStates.Highlighted
                :  Selected ? VisualStateManager.CommonStates.Selected
                                              : VisualStateManager.CommonStates.Normal);
        }
    }
}
meJevin commented 3 years ago

@softlion this would be an amazing addition!

I've faced similar issues when trying to highlight certain elements in a CollectionView. I found a similar hacky way to synthetically highlight an item with a grid inside of a DataTemplate. But I had a weird bug, where CollectionView had troubles rendering items properly. Here's the issue I filed: https://github.com/xamarin/Xamarin.Forms/issues/14098

hartez commented 3 years ago

@softlion I think your suggestion of a "highlighted" state for the VSM is excellent, though we might call it "Pressed" or something like that. But we should definitely add something to handle this.

Until we can do that (and get another release out), it is possible to modify the cell highlight behavior on iOS if you're willing to do a little customization. Take a look at this branch of my SelectedItemStyling repo: https://github.com/hartez/SelectedItemStyling/tree/ios-highlight

In the iOS project, I've added a custom renderer for the CollectionView which lets you use a custom UICollectionViewDelegateFlowLayout delegate. In there you can override the ItemHighlighted and ItemUnhighlighted methods and control the cell appearance (e.g., setting a background color).

It's limited - because of an unfortunate decision to make the VisualElementRenderer member of TemplatedCell be internal (sorry about that), there's no access to the Forms Element in the cell, and therefore no way to apply a new VisualState. (Unless you want to use reflection.) But you do have access to the cell instance, so you can set colors, background views, and anything else you can do to a UICollectionViewCell.

spiralham commented 3 years ago

@hartez Thanks for the example, been banging my head on this for awhile. Is there any way to make it work with a grouped CollectionView? The pressed color state works perfectly, but the group headers aren't shown when using the custom renderer.

Edit: I just realized selection events are no longer firing either, almost like the custom ViewController and/or Delegate didn't inherit everything from the parent. Does that make sense?