如何在 ListView 出现在 Xamarin Forms iOS 之前将 ListView 滚动位置设置为底部?
How to set a ListView Scroll position to bottom, before ListView will appears in Xamarin Forms iOS?
在 iOS 的 Xamarin Forms 中,我尝试在 ListView 出现之前设置它的滚动位置。
当 ListView 显示时,触发明显滚动到底部。
有什么想法,如何在 ListView 出现之前设置滚动位置?
[assembly: ExportRenderer(typeof(MyListView), typeof(NativeiOSListViewRenderer))]
namespace MyApp.iOS.Renderers
{
public class NativeiOSListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var element = e.NewElement as MyListView;
if (element.ItemsSource is IList items && items.Count > 0)
{
var tableView = Control as UITableView;
var indexPath = NSIndexPath.FromItemSection(itemIndexitems.Count - 1, 0);
tableView.ScrollToRow(indexPath, UITableViewScrollPosition.Bottom, false);
}
}
}
}
}
原因:
当你在方法OnElementChanged
中调用将列表视图滚动到按钮的代码时。列表视图尚未完成初始化。所以它没有用。
解法:
您可以使用MessagingCenter
在方法OnAppearing
中发送滚动列表视图的通知。
in your contentPage
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Send<Object>(this, "ScrollToButtom");
}
in iOS Renderer
public class NativeiOSListViewRenderer : ListViewRenderer
{
public NativeiOSListViewRenderer ()
{
MessagingCenter.Subscribe<Object>(this, "ScrollToButtom", (obj) => {
var element = Element as MyListView;
if (element.ItemsSource is IList<string> items && items.Count > 0)
{
var tableView = Control as UITableView;
var indexPath = NSIndexPath.FromItemSection(items.Count - 1, 0);
tableView.ScrollToRow(indexPath, UITableViewScrollPosition.Bottom, false);
}
});
}
}
更新:
该解决方案在我的 device.If 上运行良好,但在您的 project.You 上仍然无法运行 可以覆盖方法 WillDisplay
public class MyListViewRenderer:ListViewRenderer,IUITableViewDelegate
{
bool isFirstLoad = true;
public MyListViewRenderer()
{
}
[Export("tableView:willDisplayCell:forRowAtIndexPath:")]
public void WillDisplay(UITableView tableView,UITableViewCell cell,NSIndexPath indexPath)
{
if(isFirstLoad)
{
var element = Element as MyListView;
if (element.ItemsSource is IList<string> items && items.Count > 0)
{
if(indexPath.Row!=items.Count-1)
{
NSIndexPath nSIndexPath = NSIndexPath.FromItemSection(indexPath.Row + 1, 0);
tableView.ScrollToRow(nSIndexPath, UITableViewScrollPosition.Bottom, false);
}
else
{
isFirstLoad = false;
}
}
}
}
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
Control.WeakDelegate = this;
}
}
}
我已经上传了我的示例here,你可以下载试试。
虽然它是 hack,但您可以隐藏 table 然后在它滚动时取消隐藏(或者玩透明,这一定有效)。
在 iOS 的 Xamarin Forms 中,我尝试在 ListView 出现之前设置它的滚动位置。 当 ListView 显示时,触发明显滚动到底部。 有什么想法,如何在 ListView 出现之前设置滚动位置?
[assembly: ExportRenderer(typeof(MyListView), typeof(NativeiOSListViewRenderer))]
namespace MyApp.iOS.Renderers
{
public class NativeiOSListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var element = e.NewElement as MyListView;
if (element.ItemsSource is IList items && items.Count > 0)
{
var tableView = Control as UITableView;
var indexPath = NSIndexPath.FromItemSection(itemIndexitems.Count - 1, 0);
tableView.ScrollToRow(indexPath, UITableViewScrollPosition.Bottom, false);
}
}
}
}
}
原因:
当你在方法OnElementChanged
中调用将列表视图滚动到按钮的代码时。列表视图尚未完成初始化。所以它没有用。
解法:
您可以使用MessagingCenter
在方法OnAppearing
中发送滚动列表视图的通知。
in your contentPage
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Send<Object>(this, "ScrollToButtom");
}
in iOS Renderer
public class NativeiOSListViewRenderer : ListViewRenderer
{
public NativeiOSListViewRenderer ()
{
MessagingCenter.Subscribe<Object>(this, "ScrollToButtom", (obj) => {
var element = Element as MyListView;
if (element.ItemsSource is IList<string> items && items.Count > 0)
{
var tableView = Control as UITableView;
var indexPath = NSIndexPath.FromItemSection(items.Count - 1, 0);
tableView.ScrollToRow(indexPath, UITableViewScrollPosition.Bottom, false);
}
});
}
}
更新:
该解决方案在我的 device.If 上运行良好,但在您的 project.You 上仍然无法运行 可以覆盖方法 WillDisplay
public class MyListViewRenderer:ListViewRenderer,IUITableViewDelegate
{
bool isFirstLoad = true;
public MyListViewRenderer()
{
}
[Export("tableView:willDisplayCell:forRowAtIndexPath:")]
public void WillDisplay(UITableView tableView,UITableViewCell cell,NSIndexPath indexPath)
{
if(isFirstLoad)
{
var element = Element as MyListView;
if (element.ItemsSource is IList<string> items && items.Count > 0)
{
if(indexPath.Row!=items.Count-1)
{
NSIndexPath nSIndexPath = NSIndexPath.FromItemSection(indexPath.Row + 1, 0);
tableView.ScrollToRow(nSIndexPath, UITableViewScrollPosition.Bottom, false);
}
else
{
isFirstLoad = false;
}
}
}
}
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
Control.WeakDelegate = this;
}
}
}
我已经上传了我的示例here,你可以下载试试。
虽然它是 hack,但您可以隐藏 table 然后在它滚动时取消隐藏(或者玩透明,这一定有效)。