Xamarin.forms: SelectionMode None keep the highlighting and Ripple

Created on 2 Aug 2018  路  5Comments  路  Source: xamarin/Xamarin.Forms

Description

When we set the SelectionMode to None, we still have the Highlighting color on iOS and the Ripple effect on android

Steps to Reproduce

  1. Set a ListView
  2. Set the SelectionMode to None
  3. Touch an Item

Expected Behavior

Nothing append

Actual Behavior

iOS : We see the Highlighting color
Android : we see the Ripple effect

Basic Information

  • Version with issue: 3.1
  • IDE: Visual Studio Mac
listview 3 help wanted Android iOS 馃崕 bug up-for-grabs

Most helpful comment

I ran into this issue as well. For anyone else seeking a quick fix here is how I solved it for my app. Please note that I am not doing anything fancy with SelectionMode. For every ListView in my app it is set once and never changed.

iOS
The initial PR #1801 indicates that this property should change the AllowsSelection on the UITableView. It appears that this detail was missed when the renderer was implemented.

Here is my iOS renderer.
```C#
public class ListViewRendererEx : ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null && Control != null)
{
UpdateSelectionMode();
}
}

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);
    switch (e.PropertyName)
    {
        case nameof(ListView.SelectionMode):
            UpdateSelectionMode();
            break;
    }
}

private void UpdateSelectionMode()
{
    if (Element is ListView listView &&
        Control is UITableView tableView)
    {
        switch (listView.SelectionMode)
        {
            case ListViewSelectionMode.None:
                tableView.AllowsSelection = false;
                break;
            case ListViewSelectionMode.Single:
                tableView.AllowsSelection = true;
                break;
        }
    }
}

}


**Android**
On Android the ripple effect is controlled by the `Selector` drawable. To fix it in my app I simply replaced the drawable with a transparent color drawable. I am not confident this will work in all cases, but for my simplistic needs it solves the issue.

Here is my Android renderer.
```C#
public class ListViewRendererEx : ListViewRenderer
{
    private Drawable _SelectorDrawable;

    public ListViewRendererEx(Context context) 
        : base(context)
    { }

    protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
    {
        base.OnElementChanged(e);
        if (e.NewElement != null && Control != null)
        {
            UpdateSelectionMode();
        }
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        switch (e.PropertyName)
        {
            case nameof(ListView.SelectionMode):
                UpdateSelectionMode();
                break;
        }
    }

    private void UpdateSelectionMode()
    {
        if (Element is ListView listView &&
            Control is Android.Widget.ListView droidListView)
        {
            switch (listView.SelectionMode)
            {
                case ListViewSelectionMode.None:
                    _SelectorDrawable = droidListView.Selector;
                    droidListView.Selector = new ColorDrawable(Color.Transparent);
                    break;
                case ListViewSelectionMode.Single:
                    if (_SelectorDrawable != null)
                    {
                        droidListView.Selector = _SelectorDrawable;
                    }
                    break;
            }
        }
    }
}

All 5 comments

I ran into this issue as well. For anyone else seeking a quick fix here is how I solved it for my app. Please note that I am not doing anything fancy with SelectionMode. For every ListView in my app it is set once and never changed.

iOS
The initial PR #1801 indicates that this property should change the AllowsSelection on the UITableView. It appears that this detail was missed when the renderer was implemented.

Here is my iOS renderer.
```C#
public class ListViewRendererEx : ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null && Control != null)
{
UpdateSelectionMode();
}
}

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);
    switch (e.PropertyName)
    {
        case nameof(ListView.SelectionMode):
            UpdateSelectionMode();
            break;
    }
}

private void UpdateSelectionMode()
{
    if (Element is ListView listView &&
        Control is UITableView tableView)
    {
        switch (listView.SelectionMode)
        {
            case ListViewSelectionMode.None:
                tableView.AllowsSelection = false;
                break;
            case ListViewSelectionMode.Single:
                tableView.AllowsSelection = true;
                break;
        }
    }
}

}


**Android**
On Android the ripple effect is controlled by the `Selector` drawable. To fix it in my app I simply replaced the drawable with a transparent color drawable. I am not confident this will work in all cases, but for my simplistic needs it solves the issue.

Here is my Android renderer.
```C#
public class ListViewRendererEx : ListViewRenderer
{
    private Drawable _SelectorDrawable;

    public ListViewRendererEx(Context context) 
        : base(context)
    { }

    protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
    {
        base.OnElementChanged(e);
        if (e.NewElement != null && Control != null)
        {
            UpdateSelectionMode();
        }
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        switch (e.PropertyName)
        {
            case nameof(ListView.SelectionMode):
                UpdateSelectionMode();
                break;
        }
    }

    private void UpdateSelectionMode()
    {
        if (Element is ListView listView &&
            Control is Android.Widget.ListView droidListView)
        {
            switch (listView.SelectionMode)
            {
                case ListViewSelectionMode.None:
                    _SelectorDrawable = droidListView.Selector;
                    droidListView.Selector = new ColorDrawable(Color.Transparent);
                    break;
                case ListViewSelectionMode.Single:
                    if (_SelectorDrawable != null)
                    {
                        droidListView.Selector = _SelectorDrawable;
                    }
                    break;
            }
        }
    }
}

Same issue for me...

We have a release date for this fix ? That we can remove the renderers and only use the framework

Related to #3156. The workaround for this on UWP is to set SelectionMode="None" _and_ the legacy accessibility setting: :
c# InitializeComponent(); ListViewName.On<Windows>().SetSelectionMode(ListViewSelectionMode.Inaccessible);

No news after one Year ?

Was this page helpful?
0 / 5 - 0 ratings