【问题标题】:OnElementChanged in custom renderer (Entry) for Xamarin.Forms Android is only being called onceXamarin.Forms Android 的自定义渲染器(条目)中的 OnElementChanged 仅被调用一次
【发布时间】:2020-10-29 10:12:48
【问题描述】:

我相信 OnElementChanged 应该被调用两次:一次是在创建控件时,一次是在释放控件时。这适用于我的 iOS 自定义渲染器,但不适用于 Android 自定义渲染器。

在 iOS 中,当页面被显示时,e.NewElement 是控件,而 e.OldElement 为 null。当显示下一页时,这个先前的控件似乎已被丢弃,因为 e.NewElement 为 null 而 e.OldElement 是该控件。为新页面中的新控件调用 OnElementChanged。 Android 并非如此。

在 Android 中,每次显示带有控件的新屏幕时,都会调用 OnElementChanged,其中 e.OldElement 为 null,e.NewElement 为控件(如预期的那样)。但是,当显示更改为新屏幕时,不会为之前的 e.NewElement 为 null 的控件调用 OnElementChanged 方法。而是调用新页面上新控件的 OnElementChanged 方法。

这个问题在 Android 中特别出现是有原因的吗? 发生这种情况有什么原因吗?

我的目的是在控制权解除后安全地解除事件挂钩。

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;
            }
        }

        ...

    }
}

安卓:

[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;                    
            }
        }

        ...

    }
}

【问题讨论】:

  • 你是什么意思“当显示改变到一个新的屏幕”?
  • @LeoZhu-MSFT 意思是我换了一个新的观点。例如。我从主屏幕移动到另一个屏幕。

标签: c# android xamarin.forms xamarin.android xamarin.ios


【解决方案1】:

在Android上取消Dispose中的事件:

bool _disposed;

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

    _disposed = true;

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

    base.Dispose(disposing);
}  

另请参阅EntryRenderer[Android] Effects don't detach and OnElementchanged(null) is never called #2520

【讨论】:

    猜你喜欢
    • 2014-08-10
    • 2017-08-14
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 2017-01-07
    • 2014-08-29
    • 2017-10-01
    • 2016-09-03
    相关资源
    最近更新 更多