Open softlion opened 3 years ago
Adding a new state "highlighted" in states would do the trick.
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);
}
}
}
@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
@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
.
@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?
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.
On Android, a workaround using a grid at the root of the DataTemplate with a simple effect can bypass this limitation, as the highlighted property is propagated to all subviews of the cell. This grid is a subview and settings a StateListDrawable as its background works as expected.
On iOS, there is no simple way to get the UICollectionViewCell from a control inside the DataTemplate, in order to subscribe to its highlighted property, and temporarily change its BackgroundView. And there is no way to override the renderer of the cell, as it would be a DataTemplate.
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.