Xamarin.forms: [Bug] ListView item background color not set on tap

Created on 25 Sep 2019  路  27Comments  路  Source: xamarin/Xamarin.Forms

Description

On iOS, tapping a ListView item no longer provides visual feedback about which item was tapped. This is a regression; it worked before I updated to XF 4.2.0.815419 and iOS 13.

Steps to Reproduce

  1. Create a ListView such that tapping on an item navigates to another page.
  2. On iOS, tap on an item in the ListView.

Expected Behavior

On finger down, the background of the selected item should turn grey. It should stay grey after finger up and until the page transition is complete.

Actual Behavior

The background of the selected item remains white and the bottom border of the selected selected line disappears.

Basic Information

  • Version with issue: 4.2.0.815419
  • Last known good version: 4.0?
  • IDE: VS 16.3.0 (Windows), VS 3.8 (build 1805) (Mac), Xcode 11
  • Platform Target Frameworks:

    • iOS: 13.1

listview 3 iOS 13 in-progress mobcat iOS 馃崕 bug

Most helpful comment

I was able to get the selected item background to work following the advice above with a small change:

        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);
            var view = item as ExtendedViewCell;
            cell.ContentView.BackgroundColor = null;
            cell.ContentView.Opaque = false;
            cell.SelectedBackgroundView = new UIView
            {
                BackgroundColor = view.SelectedItemBackgroundColor.ToUIColor(),
            };

            return cell;
        }

All 27 comments

I confirm problem. It occurs on iPads with iOS 13.0, but not on iOS 12.4.1. When on ListView I click on first item nothing shows and on others presents only separator line.

Basic info

Xamarin.Forms Version 4.2.0.815419
VS for Mac 8.3 (build 1805)
Deployment Target iOS: 11.0 (checked also iOS 12.4)

@breyed Can you please attach a small project that demonstrates this issue? Thanks!

@samhouts I don't have an isolated repro for this bug. It shows up in a production app that isn't doing anything special with its ListViews. I expect it will readily repro for you on an existing test project using the latest XF and iOS. If you have trouble reproing, let me know.

Same on me.
I also tried with ViewCell Custom Render.

    public class MyViewCellRender : ViewCellRenderer
    {
        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);
            if (cell != null)
            {
                // Disable native cell selection color style - set as *Transparent*
                cell.SelectionStyle = UITableViewCellSelectionStyle.Blue;
            }
            return cell;
        }
    }

I can verify that this is an issue with iOS versions 13.0 and not with previous versions, like 12.2.
Xamarin.Forms version does not matter, I tested with Xamarin 4.2, 4.1, 4.0 and 3.6 all behave the same on a 13.0 device.

Run sample project on a 13.0 Simulator device and the ViewCell seems to be highlighted the same color as the ListView. If you do the same on a 12.2 the Listview is grey.

Here is a very simple sample project.
ListViewTest.zip

Same on me.
I also tried with ViewCell Custom Render.

    public class MyViewCellRender : ViewCellRenderer
    {
        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);
            if (cell != null)
            {
                // Disable native cell selection color style - set as *Transparent*
                cell.SelectionStyle = UITableViewCellSelectionStyle.Blue;
            }
            return cell;
        }
    }

Going one step further then this, even creating a Custom SelectedBackgroundView no longer works

public class OverrideTextCellRenderer : TextCellRenderer
    {
        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);
            cell.SelectedBackgroundView = new UIView()
            {
                BackgroundColor = Color.FromHex("#5503a9f4").ToUIColor()
            };

            return cell;
        }

        public override void SetBackgroundColor(UITableViewCell tableViewCell, Cell cell, UIColor color)
        {
            base.SetBackgroundColor(tableViewCell, cell, color);
        }
    }

Still looking into a workaround for this issue, but this is related to changes to iOS 13
Changes to iOS 13 have resulted in this, not sure how to fix yet

https://developer.apple.com/documentation/ios_ipados_release_notes/ios_13_release_notes

Per iOS 13 release notes (https://developer.apple.com/documentation/ios_ipados_release_notes/ios_ipados_13_beta_8_release_notes) - The UITableViewCell class no longer changes the backgroundColor or isOpaque properties of the contentView and any of its subviews when cells become highlighted or selected.

The UITableViewCell class no longer changes the backgroundColor or isOpaque properties of the contentView and any of its subviews when cells become highlighted or selected. If you are setting an opaque backgroundColor on any subviews of the cell inside (and including) the contentView, the appearance when the cell becomes highlighted or selected might be affected. The simplest way to resolve any issues with your subviews is to ensure their backgroundColor is set to nil or clear, and their opaque property is false. However, if needed you can override the setHighlighted(:animated:) and setSelected(:animated:) methods to manually change these properties on your subviews when moving to or from the highlighted and selected states.

Based on this information I was able to implement a custom renderer that can "Mostly" resolve the issue.

public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);
            cell.ContentView.BackgroundColor = null;
            cell.ContentView.Opaque = false;
            return cell;
        }

but it appears that the background and Opaque settings of subView's do not get set, so you will have to deal with each of these on their own, or write some recursive function that will clear these settings on all subviews.
Here you can see a side by side example of what it will look like using a standard TextViewCell
image

We are having the same problem, can you give me any indication when this will be solved? We can't update our app now, using the newest SDK.

If I understand the discussion so far correctly, the underlying problem is that Xamarin.Forms has been working contrary to Apple's design intent all along by applying a background by default to all its controls. In the past, you could get away with this because iOS was modifying background color to show highlighting, but now that it uses a different mechanism, the free lunch is over. What would happen if Xamarin.Forms were updated to not supply a background by default to any of its controls? Would that fix this bug? Would it break compatibility?

I was able to get the selected item background to work following the advice above with a small change:

        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);
            var view = item as ExtendedViewCell;
            cell.ContentView.BackgroundColor = null;
            cell.ContentView.Opaque = false;
            cell.SelectedBackgroundView = new UIView
            {
                BackgroundColor = view.SelectedItemBackgroundColor.ToUIColor(),
            };

            return cell;
        }

I guess it's because Apple changed UITableViewCell behavior. Seems like it's not a Xamarin.Forms issue. Native iOS developers have that issue too.

User @jfversluis posted a quick fix using a Transparent BackgroundColor value over in issue #7850 that doesn't require custom renderers.

User @jfversluis posted a quick fix using a Transparent BackgroundColor value over in issue #7850 that doesn't require custom renderers.

Thanks for the info, in my case I need to use custom renderers because I want to customize the selection color. I can confirm I have it working correctly on iOS 13 now.

OK, so. This "issue" is a new feature in iOS 13 apparently. From the iOS Release Notes

The UITableViewCell class no longer changes the backgroundColor or isOpaque properties of the contentView and any of its subviews when cells become highlighted or selected. If you are setting an opaque backgroundColor on any subviews of the cell inside (and including) the contentView, the appearance when the cell becomes highlighted or selected might be affected. The simplest way to resolve any issues with your subviews is to ensure their backgroundColor is set to nil or clear, and their opaque property is false. However, if needed you can override the setHighlighted(:animated:) and setSelected(:animated:) methods to manually change these properties on your subviews when moving to or from the highlighted and selected states.

Therefore closing this issue.

I think the core problem is that the default background color for cells is incorrect (white but should be nil). On prior versions of iOS, it happened to work, but with the iOS 13 change, the free lunch is now over.

If no change is made to XF, every new user of the platform will read the docs on using ListView (which don't say anything about customizing cell background color, nor should it, unless the user is customizing the look), add the cell, and then wonder why the app feels awkward when he tests it out. If he's lucky, he'll end up here and figure out that he needs to override the cell's background color. Hardly a it-just-works experience.

Yes, there is an easy workaround, but it's just a workaround. And it's not at all obvious until you stumble across it. This issue shouldn't be closed without a PR to fix the underlying problem, which is to correct the background color in the ViewCell etc.

@breyed I might agree with you, but how do you explain the native developers coming across the same issue? Wouldn't their background be nil as well?

In addition, this issue might be considered duplicate since we already have an issue in place (#7683 & #7304) that will handle dark mode and because of that, hard coded colors like these.

@jfversluis My guess is that Apple native developers generally don't set the background color, and so the change impacts only a small percentage of developers who were explicitly working with the background color. They were already opting into managing it already to some extent - and now have to manage it fully or opt back out. Presumably, Apple saw enough benefits to making the change in iOS behavior to outweigh the instances of incompatibility.

The Xamarin.Forms case is reversed. Instead of impacting only the few who were explicitly dealing with background color anyway, it impacts the masses who weren't even thinking about background color.

So I think it's important that the issue be fixed. If it's most efficient to merge implementation and testing into another issue with a similar timeframe, that's fine.

Agreed. Let me see if I can create a fix for this in advance as the whole operation "dark mode/fixed colors" might take a bit longer.

There is a quick fix in the Xamarin forum:

add BackgroundColor="Transparent" to your ListView AND the root element within the ViewCell

The bug still occurs in XF 4.3.0.908675? I wasn't expecting that based on this workflow update:

vNext (4.3.0) automation moved this from In Progress to Done 6 hours ago

@rmarinho Can you clarify how this fix will be rollout out?

@breyed It'll be in the next 4.3.0 service release. Thanks for your patience!

There is a quick fix in the Xamarin forum:

add BackgroundColor="Transparent" to your ListView AND the root element within the ViewCell

This is perfect. Exactly what I have been looking for and by far the cleanest and most elegant solution. Especially when setting them as global resource styles, all my problems went away in one easy fix. Thanks for this

@AndrewSatMap and all; the next service release is out where this should be fixed too :)

@jfversluis, maybe missed point, but is there way to have custom non-transparent ViewCell background (want to have Color.White) and bring normal selection behavior back?
Using XF 4.3.0.991250, selection working ok only if I set Color.Transparent manually or via renderer. Thanks

@GenPike I'm not entirely sure what you mean. For iOS 13 and up the cell should be transparent and show the right selection behavior. For anything before iOS 13 the behavior should be the same.

In all cases the selection behavior should show the right way. If you believe that is not the case please open a new issue with a reproduction project and refer to this one. Thanks! :)

This is still happening or at least is happening again.
You can easily replicate this with the code below. The selected row in the listview uses the same color as the background.
Is this going to be fixed?

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="XamarinListViewBug.MainPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackLayout>
        <ListView Margin="10" BackgroundColor="White">
            <ListView.ItemsSource>
                <x:Array Type="{x:Type x:String}">
                    <x:String>France</x:String>
                    <x:String>Germany</x:String>
                    <x:String>England</x:String>
                    <x:String>Italy</x:String>
                </x:Array>
            </ListView.ItemsSource>

            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Label Margin="3" Text="{Binding}" />
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>

</ContentPage>

Edit: Nevermind, just read #9935.

Was this page helpful?
0 / 5 - 0 ratings