列表视图的单元格重用问题和自定义渲染器的视图单元格

Cell-reusing issue with list view and view cells with custom renderer

我正在尝试显示一个列表视图,其中包含使用自定义 iOS 渲染器渲染的单元格。滚动列表时,会出现令人讨厌的叠加层(如下所示)。我将其归结为以下代码行。

App 包含一个 ListView,其 ItemsSource 设置为从 A 到 Z 的所有字符的虚拟列表。ItemTemplate 是使用自定义 ItemCell定义如下。

public class App : Application
{
    public App()
    {
        MainPage = new ContentPage {
            Content = new ListView {
                ItemsSource = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray(),
                ItemTemplate = new DataTemplate(typeof(ItemCell)),
            },
        };
    }
}

ItemCell 包含绑定到列表项的 Label

public class ItemCell: ViewCell
{
    public ItemCell()
    {
        View = new Label();
        View.SetBinding(Label.TextProperty, ".");
    }
}

在 iOS 上 Label 使用以下 FixedLabelRenderer 呈现。它设置由包含 ElementText.

UILabel 表示的本机控件
public class FixedLabelRenderer : ViewRenderer<Label, UILabel>
{
    protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
    {
        base.OnElementChanged(e);

        SetNativeControl(new UILabel(RectangleF.Empty) { Text = Element.Text });
    }
}

现在的问题是,显然,当重新使用一个单元格时,控件并没有被删除,而只是创建了一个新的控件。所以我得到了下面屏幕截图中显示的叠加层。

(左:滚动前,右:滚动后)

有趣的是,Xamarin.Forms 1.2.3 或 1.3.1 不会出现此问题,但 1.3.5 和 1.4.0 会出现此问题。

哦,我找到了解决办法on the Xamarin Forum

protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
    base.OnElementChanged(e);

    if (Control == null)
        SetNativeControl(new UILabel());

    if (e.NewElement != null)
        Control.Text = e.NewElement.Text;
}

所以基本上你需要确保只创建 一个 UILabel 然后再使用它。