iOS 上的 ForceUpdateSize ListView 问题
ForceUpdateSize ListView issue on iOS
我有一个使用带有单选按钮的自定义 ViewCell 的自定义 ListView。单击每个单选按钮时,ListView 会动态调整其高度以 hide/show 评论框。
在 iOS 平台中使用 ForceUpdateSize
时,单击单选按钮时 ListView 性能会迅速下降。该应用程序最终挂起并停止响应。
是否有替代解决方案可以代替 ForceUpdateSize
在运行时动态扩展 ListView 行?
我的解决办法是:尝试使用自定义渲染器。单击按钮时,我使用 tableView.ReloadRows() 动态更改单元格的大小。
首先,定义一个布尔列表,其项目等于您要在源中显示的行。我第一次用 false 初始化它的项目。
List<bool> isExpanded = new List<bool>();
public MyListViewSource(MyListView view)
{
//It depends on how many rows you want to show.
for (int i=0; i<10; i++)
{
isExpanded.Add(false);
}
}
其次,构建 GetCell 事件(我只是在我的 Cell 中放置了一个 UISwitch 用于测试),例如:
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
MyListViewCell cell = tableView.DequeueReusableCell("Cell") as MyListViewCell;
if (cell == null)
{
cell = new MyListViewCell(new NSString("Cell"));
//This event is constructed in my Cell, when the switch's value changed it will be fired.
cell.RefreshEvent += (refreshCell, isOn) =>
{
NSIndexPath index = tableView.IndexPathForCell(refreshCell);
isExpanded[index.Row] = isOn;
tableView.ReloadRows(new NSIndexPath[] { index }, UITableViewRowAnimation.Automatic);
};
}
cell.switchBtn.On = isExpanded[indexPath.Row];
return cell;
}
最后,我们可以覆盖 GetHeightForRow 事件。根据 isExpanded 中的项目设置一个大或小的值:
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
if (isExpanded[indexPath.Row])
{
return 80;
}
return 40;
}
这是我手机的一部分供您参考:
//When switch's value changed, this event will be called
public delegate void RefreshHanle(MyListViewCell cell, bool isOn);
public event RefreshHanle RefreshEvent;
switchBtn.AddTarget((sender, args) =>
{
UISwitch mySwitch = sender as UISwitch;
RefreshEvent(this, mySwitch.On);
}, UIControlEvent.ValueChanged);
在需要更改 ViewCell 大小的任何地方定义 ViewCell 大小更改事件
public static event Action ViewCellSizeChangedEvent;
在您的情况下,它应该由您的单选按钮触发。像这样称呼它:
ViewCellSizeChangedEvent?.Invoke();
然后它将使用 ListView 渲染器更新 iOS TableView。
public class CustomListViewRenderer : ListViewRenderer
{
public CustomListViewRenderer()
{
WhatEverContentView.ViewCellSizeChangedEvent += UpdateTableView;
}
private void UpdateTableView()
{
var tv = Control as UITableView;
if (tv == null) return;
tv.BeginUpdates();
tv.EndUpdates();
}
}
它应该可以解决您的性能问题,同时继续使用您的 Xaml 而不是创建不需要的自定义 ViewCell。
我有一个使用带有单选按钮的自定义 ViewCell 的自定义 ListView。单击每个单选按钮时,ListView 会动态调整其高度以 hide/show 评论框。
在 iOS 平台中使用 ForceUpdateSize
时,单击单选按钮时 ListView 性能会迅速下降。该应用程序最终挂起并停止响应。
是否有替代解决方案可以代替 ForceUpdateSize
在运行时动态扩展 ListView 行?
我的解决办法是:尝试使用自定义渲染器。单击按钮时,我使用 tableView.ReloadRows() 动态更改单元格的大小。
首先,定义一个布尔列表,其项目等于您要在源中显示的行。我第一次用 false 初始化它的项目。
List<bool> isExpanded = new List<bool>();
public MyListViewSource(MyListView view)
{
//It depends on how many rows you want to show.
for (int i=0; i<10; i++)
{
isExpanded.Add(false);
}
}
其次,构建 GetCell 事件(我只是在我的 Cell 中放置了一个 UISwitch 用于测试),例如:
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
MyListViewCell cell = tableView.DequeueReusableCell("Cell") as MyListViewCell;
if (cell == null)
{
cell = new MyListViewCell(new NSString("Cell"));
//This event is constructed in my Cell, when the switch's value changed it will be fired.
cell.RefreshEvent += (refreshCell, isOn) =>
{
NSIndexPath index = tableView.IndexPathForCell(refreshCell);
isExpanded[index.Row] = isOn;
tableView.ReloadRows(new NSIndexPath[] { index }, UITableViewRowAnimation.Automatic);
};
}
cell.switchBtn.On = isExpanded[indexPath.Row];
return cell;
}
最后,我们可以覆盖 GetHeightForRow 事件。根据 isExpanded 中的项目设置一个大或小的值:
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
if (isExpanded[indexPath.Row])
{
return 80;
}
return 40;
}
这是我手机的一部分供您参考:
//When switch's value changed, this event will be called
public delegate void RefreshHanle(MyListViewCell cell, bool isOn);
public event RefreshHanle RefreshEvent;
switchBtn.AddTarget((sender, args) =>
{
UISwitch mySwitch = sender as UISwitch;
RefreshEvent(this, mySwitch.On);
}, UIControlEvent.ValueChanged);
在需要更改 ViewCell 大小的任何地方定义 ViewCell 大小更改事件
public static event Action ViewCellSizeChangedEvent;
在您的情况下,它应该由您的单选按钮触发。像这样称呼它:
ViewCellSizeChangedEvent?.Invoke();
然后它将使用 ListView 渲染器更新 iOS TableView。
public class CustomListViewRenderer : ListViewRenderer
{
public CustomListViewRenderer()
{
WhatEverContentView.ViewCellSizeChangedEvent += UpdateTableView;
}
private void UpdateTableView()
{
var tv = Control as UITableView;
if (tv == null) return;
tv.BeginUpdates();
tv.EndUpdates();
}
}
它应该可以解决您的性能问题,同时继续使用您的 Xaml 而不是创建不需要的自定义 ViewCell。