Xamarin.Forms Android 的自定义渲染器(条目)中的 OnElementChanged 仅被调用一次
OnElementChanged in custom renderer (Entry) for Xamarin.Forms Android is only being called once
我相信 OnElementChanged 应该被调用两次:一次是在创建控件时,一次是在它被释放时。这对我的 iOS 自定义渲染器按预期工作,但在 Android 自定义渲染器中没有。
在 iOS 中,当页面显示时 e.NewElement 是控件,e.OldElement 是空的。当显示下一页时,这个先前的控件似乎被处理掉了,因为 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;
}
}
...
}
}
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;
}
}
...
}
}
在 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 and [Android] Effects don't detach and OnElementchanged(null) is never called #2520
我相信 OnElementChanged 应该被调用两次:一次是在创建控件时,一次是在它被释放时。这对我的 iOS 自定义渲染器按预期工作,但在 Android 自定义渲染器中没有。
在 iOS 中,当页面显示时 e.NewElement 是控件,e.OldElement 是空的。当显示下一页时,这个先前的控件似乎被处理掉了,因为 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;
}
}
...
}
}
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;
}
}
...
}
}
在 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 and [Android] Effects don't detach and OnElementchanged(null) is never called #2520