Xamarin.forms: Entry focus issue inside ListView

Created on 18 Jan 2018  路  29Comments  路  Source: xamarin/Xamarin.Forms

Description

There seems to be a bug when using the focus event of an Entry inside a listview.
I've created a test app that contains a listview with a datatemplate selector.
Some rows will render an Entry that has a focus function, these rows have a blue background. When the Entry is focussed the text is changed to the current datetime.
The other rows are normal Entries that do nothing when focussed, these rows have a green background.
Focussing the first blue Entry will enter the current datetime in that Entry.
Focussing the first green Entry will cause the text of the first blue Entry to be updated continuously, trying to type in the green Entry won't add any text.
Focussing any of the other blue Entries will cause the text of that Entry and the text of the first Entry to be updated continuously.

Note: tested on Android version 6.0 and 7.0. Not sure if this occurs on iOS as well.
Note: tested with cachingstrategy RetainElement and RecycleElement, results are the same.

Steps to Reproduce

  • Run the test app
  • Tap on first Entry, the current datetime will appear in the Entry
  • Tap on second Entry, the current datetime will be updated in the first Entry continuously
  • Tap the third Entry, the current datetime will be updateed in the first and third Entry continuously

Expected Behavior

Focussing an Entry sets the text to the current date.

Actual Behavior

The text of two entries are updated in an infinite loop.

Basic Information

  • Version with issue: 2.5.0.122203
  • Last known good version: unknown
  • IDE: Visual Studio
  • Platform Target Frameworks:

    • Android: tested on 6.0 and 7.0

  • Android Support Library Version: 25
    DataTemplateSelector.zip
listview 3 help wanted high impact Android bug up-for-grabs

Most helpful comment

@davidortinau can you guys consider this a new F100000000000000?
This a serious critical bug for many basic use cases.

All 29 comments

@JellisHogenbijl I cannot decompress the zip file. Windows tells me it's "invalid".

Created a new zip, let me know if you still have issues opening this zip.
DataTemplateSelector.zip

I am also having the same issue.

Any news of when it will be fixed?

Any news about this issue?

Any news of when it will be fixed?

Any news of when it will be fixed?

@davidortinau can you guys consider this a new F100000000000000?
This a serious critical bug for many basic use cases.

@ederbond did you find a way around. @samhouts can you offer some help with this. As mentioned Entries/Editors in a listview is a basic use case and is critical to my app. It looks very much related to the keyboard overlaying the Entry/Editor control on focus. I get repeated cycles of Focus/Unfocus. Also if I've manually focused the control then unfocus, scroll the control out of view, when the control is scrolled back into view it automatically focuses the control again. Even other entry controls I haven't touched in the listview are cycling focus/unfocus events.

Sorry @ledragon101 I didn't found a solution for this. I thought about replacing the ListView to a CollectionView or maybe a ScrollView with a StackLayout with a BindadbleLayout but I didn't had time to test it yet. I guess this is just another of the countless bugs of ListView. At least I hope.

@ederbond Just noticed this from BindableLayout docs "Bindable layouts should only be used when the collection of items to be displayed is small, and scrolling and selection isn't required. While scrolling can be provided by wrapping a bindable layout in a ScrollView, this is not recommended as bindable layouts lack UI virtualization." Something to bear in mind. FYI I've tried ditching the listview and added the controls to a stacklayout and it works much better. Tested up to about 100 entry/editor/picker/etc controls and it seems to work fine...device dependant though of course.

@ledragon101 I was aware about the performance concerns using BindableLayouts, that's why I've also suggested CollectionView witch BTW it's still in preview...

BTW I've worked around the multiple calls from XF's Entry.Focused using the code bellow:
PS: Here I'm using https://github.com/dotnet/reactive nuget package:

using System;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Windows.Input;
using My.Mobile.Extensions;
using Reactive.Bindings.Extensions;
using Xamarin.Forms;

namespace My.Mobile.Controls
{
    public class EnhancedEntry : Entry
    {
        public static readonly BindableProperty OnFocusedCommandProperty =
            BindableProperty.Create(nameof(OnFocusedCommand), typeof(ICommand), typeof(EnhancedEntry));

        public static readonly BindableProperty OnFocusedCommandParameterProperty =
            BindableProperty.Create(nameof(OnFocusedCommandParameter), typeof(object), typeof(EnhancedEntry));

        private readonly CompositeDisposable _disposables = new CompositeDisposable();

        //Static field that accumulate multiple call's to the XF's Entry.Focused event.
        //It throttles multiple the calls and allow just the first one to be executed.
        //This is a workaround to this https://github.com/xamarin/Xamarin.Forms/issues/3759 bug
        private static readonly Subject<EventPattern<FocusEventArgs>> FocusSubject = new Subject<EventPattern<FocusEventArgs>>();

        static EnhancedEntry()
        {
            FocusSubject
                .ThrottleFirst(TimeSpan.FromMilliseconds(250))
                .ObserveOnUIDispatcher()
                .Subscribe(x => { OnFocused(x.Sender, x.EventArgs); });
        }

        public EnhancedEntry()
        {
            Observable.FromEventPattern<FocusEventArgs>(h => Focused += h, h => Focused -= h)
                .Subscribe(FocusSubject)
                .AddTo(_disposables);
        }

        ~EnhancedEntry()
        {
            _disposables.Dispose();
        }

        public ICommand OnFocusedCommand
        {
            get => (ICommand) GetValue(OnFocusedCommandProperty);
            set => SetValue(OnFocusedCommandProperty, value);
        }

        public object OnFocusedCommandParameter
        {
            get => (object) GetValue(OnFocusedCommandParameterProperty);
            set => SetValue(OnFocusedCommandParameterProperty, value);
        }

        private static void OnFocused(object sender, FocusEventArgs e)
        {
            var control = (EnhancedEntry) sender;
            var param = control.OnFocusedCommandParameter ?? new FocusedArgs(control);

            if (control.OnFocusedCommand == null || !control.OnFocusedCommand.CanExecute(param)) return;

            control.OnFocusedCommand.Execute(param);
        }
    }

    public class FocusedArgs
    {
        public object ViewModel => Sender.BindingContext;
        public EnhancedEntry Sender { get; private set; }

        public FocusedArgs(EnhancedEntry sender)
        {
            Sender = sender;
        }
    }
}

public static class ExtensionsOfObservable
{
        public static IObservable<T> ThrottleFirst<T>(this IObservable<T> observable, TimeSpan? delay = null, IScheduler scheduler = null)
        {
            delay = delay ?? TimeSpan.FromSeconds(1);

            return observable.Publish(o => o.Take(1)
                .Concat(o.IgnoreElements().TakeUntil(Observable.Return(Unit.Default).Delay(delay.Value, scheduler ?? Scheduler.Default)))
                .Repeat()
                .TakeUntil(o.IgnoreElements().Concat(Observable.Return(default(T)))));
        }
}

@ederbond Hi thanks for the code....will try it out. Have you noticed which versions of Android you see this behaviour? I've only tested v9 and v6 and I see on v6 but not v9

Does anyone have a workaround that wouldn't use Rx?

I've seen this on Android 8 and 8.1

I tried with Syncfusion Listview and it worked fine without the issue with focus but scrolling was jerky so I scrapped it and decided not to bother with a list view and just add the controls individually. Same as ederbond I've noticed this up to v8.1 but seems to be fixed in v9.

I didn't tested yet but I guess CollectionView could not have this issue...

I'm hoping too but not gonna touch it until it's released fully. Should be soon now huh!

FYI: CollectionView doesn't have this issue.

@lassana Good to know! Would you mind sharing what version of Android you tested with?

@lassana Good to know! Would you mind sharing what version of Android you tested with?

Android 6.0 + X.F 4.1.0.709244

Seeing this issue as well against a non-Forms Xamarin.Android project targeting a Android 9 emulator

@stonedauwg With ListView or CollectionView?

Seeing the bug with ListView. This issue is abt ListView, right?

Seeing the bug with ListView. This issue is abt ListView, right?

Yes that's right...just checking as lassana mentioned CollectionView doesn't suffer the same issue and I'm banking on using it when it's moved out of preview ;-)

@ledragon101 Makes sense. I used RecyclerView as a replacement for now. Works. Has this issue been assigned?

@stonedauwg who knows! My guess is they're banking on people switching to CollectionView so putting efforts into that. Fine by me but I wish they'd hurry up ;-) My lists aren't long so I've switched to ScrollView and Stacklayout BindableLayout for now. Works fine for me. Wish I'd figured that out weeks ago! Should've listened to @ederbond but I didn't realise what BindableLayout was at the time.

Oh, as an aside...I came across this Listview issue on a Huawai P20 with Android 9 today. Never gonna touch a Listview again...way too much aggro!

@samhouts - When will we get the fix of this reported issue? Please make this as high priority

Was this page helpful?
0 / 5 - 0 ratings