6

I am using a CollectionView and when a user selects an item, I don't want the SelectedItem to show background color at all. I have tried to achieve this effect by setting the BackgroundColor property to transparent with the VisualStateManager per the instructions in Xamarin's documentation. However, rather than the Item's Background being invisible it just becomes grayed-out when selected. The code works. If I set it to red, I see red. But I can't get the background to go away altogether.

This is happening in iOS.

Can anyone tell me how to do this?

Here's my code:

<Style TargetType="ContentView">
                <Setter Property="VisualStateManager.VisualStateGroups">
                    <VisualStateGroupList>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="Selected">
                                <VisualState.Setters>
                                    <Setter Property="BackgroundColor"
                                        Value="Transparent" />
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateGroupList>
                </Setter>
            </Style>

<CollectionView Grid.Row="0" ItemsSource="{Binding Lessons}"  BackgroundColor="Transparent"
                  SelectedItem="{Binding SelectedLesson, Mode=TwoWay}" HorizontalOptions="FillAndExpand"

                        SelectionMode="Single"
                        cal:Message.Attach="[Event SelectionChanged] = [Action ActivateLesson]">
            <CollectionView.ItemTemplate >
                <DataTemplate x:DataType="engineVm:LessonViewModel">
                    <ContentView BackgroundColor="Transparent" cal:View.Model="{Binding}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Margin="0, 0, 0, 20" />
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
Sean
  • 778
  • 6
  • 18
  • I'm not overly familiar with CollectionView. This is a solution I had to do with a ListView https://stackoverflow.com/questions/59671543/xamarin-forms-set-background-color-of-item-selected-in-listview-from-viewmodel that might help – Joe H Feb 03 '20 at 14:35
  • Thanks, using that solution, did you try to make it transparent and not just a different color? – Sean Feb 03 '20 at 15:40
  • I have tried with different colors and don't see why transparent would behave differently, but don't know that I ever explicitly tested using transparent – Joe H Feb 03 '20 at 17:00
  • @Lucas.. I will try soon again with a ListView. I believe that solution will work. I started encountering a bug with the CollectionView such that when I rotate the device to Landscape mode and then back again to portrait mode, the collectionView loses the first item in my list. ListView doesn't do this. – Sean Feb 06 '20 at 02:15
  • @Sean Does it work now? – Lucas Zhang Feb 14 '20 at 00:30
  • Use the recommended method in the documentation, it uses VisualStateManager to change the background color. https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/selection#change-selected-item-color – lavilaso Feb 10 '20 at 07:07
  • both VisualStateManager or transparent still shows greyed out background on tap and hold on latest XF 5.+ – vertique May 16 '21 at 14:08

1 Answers1

0

This can be accomplished by using Custom Renderer

using UIKit;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;

using App7.iOS;

[assembly:ExportRenderer(typeof(ViewCell),typeof(MyViewCellRenderer))]

namespace App7.iOS
{
    public class MyViewCellRenderer: ViewCellRenderer
    {
        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell= base.GetCell(item, reusableCell, tv);

            cell.SelectedBackgroundView = new UIView
            {
                BackgroundColor = Color.Transparent.ToUIColor(),
            };
            cell.SelectionStyle = UITableViewCellSelectionStyle.None;

            return cell;
        }

        
    }
}

in xaml

<CollectionView.ItemTemplate >
  <DataTemplate >
     <ViewCell>
         <ContentView BackgroundColor="Transparent" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Margin="0, 0, 0, 20" />
     </ViewCell>
  </DataTemplate>
</CollectionView.ItemTemplate>

Update

You could use the plugin FlowListView from Nuget . It provides the similar function like CollectionView .

And you could create a custom renderers for FlowListViewInternalCell in platforms specific projects which disable ListView row highlighting.

iOS

using System;
using DLToolkit.Forms.Controls;
using DLToolkitControlsSamples.iOS;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(FlowListViewInternalCell), typeof(FlowListViewInternalCellRenderer))]
namespace DLToolkitControlsSamples.iOS
{
    // DISABLES FLOWLISTVIEW ROW HIGHLIGHT
    public class FlowListViewInternalCellRenderer : ViewCellRenderer
    {
        public override UIKit.UITableViewCell GetCell(Xamarin.Forms.Cell item, UIKit.UITableViewCell reusableCell, UIKit.UITableView tv)
        {
                    tv.AllowsSelection = false;
            var cell = base.GetCell(item, reusableCell, tv);
            cell.SelectionStyle = UITableViewCellSelectionStyle.None;

            return cell;
        }
    }
}

Android

using System;
using DLToolkit.Forms.Controls;
using DLToolkitControlsSamples.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(FlowListViewInternalCell), typeof(FlowListViewInternalCellRenderer))]
namespace DLToolkitControlsSamples.Droid
{
    // DISABLES FLOWLISTVIEW ROW HIGHLIGHT
    public class FlowListViewInternalCellRenderer : ViewCellRenderer
    {
        protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, Android.Views.ViewGroup parent, Android.Content.Context context)
        {
            var cell = base.GetCellCore(item, convertView, parent, context);

            var listView = parent as Android.Widget.ListView;

            if (listView != null)
            {
                listView.SetSelector(Android.Resource.Color.Transparent);
                listView.CacheColorHint = Android.Graphics.Color.Transparent;
            }

            return cell;
        }
    }
}

For more details and usage of the plugin you could check https://github.com/daniel-luberda/DLToolkit.Forms.Controls/tree/master/FlowListView/

Community
  • 1
  • 1
Lucas Zhang
  • 17,010
  • 3
  • 7
  • 19
  • Thanks, Lucas. I may try again with the CollectionView but please see above my comment regarding the CollectionView bug. For now I've gone back to a ListView because there are 2 bugs I've found with CollectionView. One of them involves weird display issues when using inside of SlideOverKit's pull down menu. Sometimes it still appears on the screen even after I've dismissed the SlideOver menu. Sometimes CollectionVIew loses one of the bound items after rotating the device. Maybe it's something wrong with my setup but I'm not having those issues with ListView. Thanks! – Sean Feb 06 '20 at 02:18
  • I will be happy to give this a try and mark it as a correct. I cannot do it tonight but will do so ASAP. Thanks! – Sean Feb 06 '20 at 02:44
  • 1
    No, When I try to put a ViewCell into the DataTemplate of the CollectionView, it throws the following exception and crashes: – Sean Feb 07 '20 at 22:07
  • CollectionView] An attempt to prepare a layout while a prepareLayout call was already in progress (i.e. reentrant call) has been ignored. Please file a bug. UICollectionView instance is (; layer = ; contentOffset: {0, 0}; contentSize: {372.5, 0}; adjustedContentInset: {0, 0, 0, 0}; layout: ; dataSource: – Sean Feb 07 '20 at 22:08
  • Correction to my comment above: When I try to put a ViewCell into the DataTemplate of the CollectionView, it throws the following exception and crashes: Value cannot be null. Parameter name: view ... I guess it's not supposed to have a ViewCell like ListView. The long error message beginning with "[CollectionView] An attempt to prepare a layout" occurs regardless of whether or not use the ViewCell. However, that error does not crash it. There is something wrong with CollectionView. – Sean Feb 07 '20 at 22:16
  • Thanks! I didn't know about the FlowListView. I just looked at it on GitHub: "Fixed or automatic column count" for grid layout is exactly what I've needed several times. CollectionView I believe only offers fixed. I'll integrate this into my project ASAP and let you know soon. – Sean Feb 10 '20 at 15:26
  • Yes, had a chance to give it a try today and it works as expected. – Sean Feb 19 '20 at 19:20
  • So if it's not possible to do for CollectionView, I guess question shouldn't be marked as "answered".. Im interested in it too – neuromouse May 24 '21 at 12:48