Xamarin窗体ListView IOS中的交替行颜色
本文关键字:颜色 窗体 ListView IOS Xamarin | 更新日期: 2023-09-27 18:26:17
我正在尝试编写一个CustomRenderer,它可以允许ListView具有交替的行颜色。我遇到了一个问题,不确定这是否是一个错误,或者我只是没有正确实现渲染器:
我对以下代码的期望是,每个自定义视图单元格都应该根据其位置获得一种颜色。然而,事实并非如此,我认为这段代码tv.IndexPathForCell(cell).Row
应该返回单元格的索引,但它并没有按预期工作。它目前正在返回一个null值(如果单元格不在部分视图中,它应该返回null值),但我认为该单元格是表视图的一部分,因此也是我的问题。如果我注释掉var index = tv.IndexPathForCell(cell).Row;
,然后将背景色设置为静态值,则代码和视图可以正常工作。此外,由于null值而引发异常,并且单元格被设置为基础,视图使用默认背景进行渲染。
我做错了什么吗?我试过其他几件事,但我相信这应该是正确的做法。
c#代码:
[assembly: ExportRenderer(typeof(CustomViewCell), typeof(CustomViewCellRenderer))]
namespace AIM.iOS {
class CustomViewCellRenderer : ViewCellRenderer {
public override UITableViewCell GetCell(Cell item, UITableView tv) {
UITableViewCell cell;
try {
cell = base.GetCell(item, tv);
var customCell = (CustomViewCell)item;
var cell = base.GetCell(item, tv);
var index = tv.IndexPathForCell(cell).Row;
cell.BackgroundColor = (index % 2 == 0) ? Color.Gray.ToUIColor() :
Color.White.ToUIColor();
}catch (Exception ex){
string message = ex.Message;
cell = base.GetCell(item, tv);
}
return cell
}
}
}
我正在扩展Xamarin Forms Labs中的ExtendedViewCell类,它为ViewCell对象添加了背景属性。
namespace AIMUI.Controls {
public class CustomViewCell : ExtendedViewCell {
public CustomViewCell() { }
}
}
这是Xaml:
<localcontrols:ListView>
<ListView.ItemTemplate>
<DataTemplate>
<localcontrols:CustomViewCell>
<localcontrols:CustomViewCell.View>
</localcontrols:CustomViewCell.View>
</localcontrols:CustomViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</localcontrols:ListView>
编辑:
好的,所以我通过使用var index = tv.IndexPathForRowAtPoint(cell.Center).Row;
解决了获取索引的问题,但是这导致了另一个问题。它第一次工作非常完美,也可以从子视图返回页面。然而,当我离开页面,从masterpage
转到另一个视图并返回时,它会将所有项目的背景设置为灰色。目前,我正在创建一个新页面,然后从菜单中将其设置为masterpage.details
。
这可以使用转换器而不是渲染器来完成。
public class StripedBackgroundIndexConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || parameter == null) return Color.White;
var index = ((ListView) parameter).ItemsSource.Cast<object>().ToList().IndexOf(value);
return index % 2 == 0 ? Color.White : Color.FromRgb(240, 240, 240);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
然后命名您的ListView,并使用x:Reference 将其作为参数传递
<ListView x:Name="MyItemsListView" ItemsSource="{Binding MyItems}" SelectedItem="{Binding SelectedMyItem, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid BackgroundColor="{Binding .,Converter={StaticResource StripedBackgroundIndexConverter}, ConverterParameter={x:Reference MyItemsListView}}">
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
当然,如果需要自定义其他元素,也可以在渲染器中使用转换器。
正如您已经发现的那样,IndexPathForRowAtPoint将返回数据源中Row的索引,即使该行不可见,这与IndexPathForCell不同,它在单元格可见之前不会正常工作。
关于您的导航问题,当您将页面推送到Xamarin.Forms navigation Stack时,它们不会被卸载,并且仍然在后台运行。这就是为什么当您导航回Navigation Stack和Pop时,您看到的页面与您导航离开的页面完全相同(当然,除非您在page事件处理程序中有一些逻辑,它将被重新调用以执行其他处理)。
在iOS中,单元格在适当的时候被Enqueued和Dequeued并且可能仍然驻留在内存中,尽管它们不可见,等待垃圾回收。
这听起来很奇怪,当你离开页面(而不是子视图),然后回到这个页面时,由于你使用的模数,它不起作用。
作为替代方案,仅用于探索和测试,在您的模型中引入另一个字段,该字段具有递增的ID,您对其执行模数以设置行的背景色,以查看是否可以隔离IndexPathForRowAtPoint函数,这可能是主要问题所在。
如果你能创建一个只有这个的小项目,这对那些进一步帮助的人会很有帮助吗?
在联系Xamarin支持并得到他们的帮助后,结果就是这样。
indexPathForPoint基于实际单元格在屏幕上的方式和时间是不可靠的。通常,GetCell方法具有可靠的NSIndexPath参数,但Forms抽象不会传递此参数。
建议作为增强HERE
作为一种变通方法,您可以使用另一种方法进行索引。然而,这对我来说并不奏效,因为它不是100%可靠的。我没有找到实现此功能的好方法。
附带说明-我觉得这在Xamarin代码设计过程中被忽略了,简单地获取每个单元格的索引应该不会那么难。