简体   繁体   中英

OnElementChanged in custom renderer (Entry) for Xamarin.Forms Android is only being called once

I believe that OnElementChanged is supposed to be called twice: once when the control is created and once when it is disposed. This works as expected for my iOS custom renderer but not in Android custom renderer.

In iOS when a page is dipslayed e.NewElement is the control and e.OldElement is null. When the next page is shown, this previous control seems disposed of as e.NewElement is null and e.OldElement is that control. OnElementChanged is called for the new controls in the new page. This is not the case for Android.

In Android, each time a new screen with the controls is displayed, OnElementChanged is called with e.OldElement as null and e.NewElement as the control (as expected). However, when the display is changed to a new screen, the OnElementChanged method is not called for the previous controls with e.NewElement as null. Instead, the OnElementChanged methods for the new controls on the new page are called.

Is there a reason why this issue is happening specifically in Android? Are there any reasons why this could be happening?

My purpose is to safely unhook the event once that control is disposed of.

iOS:

[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace iOS.Renderers
{
    public class MyEntryRenderer: EntryRenderer
    {
        private UIButton _myButton = null;

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            // update control UI
            ...

            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                // Unsubscribe
                _myButton .TouchUpInside -= OnClearButtonTouched;
            }
            if (e.NewElement != null)
            {
                if (_myButton == null)
                {
                    // create button
                    _myButton = ...;
                }

                // Subscribe
                _myButton.TouchUpInside += OnClearButtonTouched;
            }
        }

        ...

    }
}

Android:

[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace Android.Renderers
{
    public class MyEntryRenderer: EntryRenderer
    {
        private FormsEditText _formsEditText;
        private Drawable _leftDrawable = null;

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

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            // update control UI
            ...

            base.OnElementChanged(e);

            // set appropriate event handler for when text is cleared

            if (_leftDrawable == null) {
                // get appropriate search drawable
                _leftDrawable = ...;
            }

            if (e.OldElement != null)
            {
                // Unsubscribe
                Control.AfterTextChanged -= AfterEntryTextChanged;
            }
            if (e.NewElement != null)
            {
                if (Control == null)
                {
                    _formsEditText = new FormsEditText(Context);
                    SetNativeControl(_formsEditText);
                }

                // Subscribe
                Control.AfterTextChanged += AfterEntryTextChanged;                    
            }
        }

        ...

    }
}

On Android unhook the event in Dispose :

bool _disposed;

protected override void Dispose(bool disposing)
{
    if (_disposed)
        return;

    _disposed = true;

    if (Control != null && disposing)
    {
        _myButton.TouchUpInside -= OnClearButtonTouched;
    }

    base.Dispose(disposing);
}  

See also EntryRenderer and [Android] Effects don't detach and OnElementchanged(null) is never called #2520

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM