在 Xamarin Forms iOS 中出现 ListView 之前,如何将 ListView 滚动位置设置为底部?

Posted

技术标签:

【中文标题】在 Xamarin Forms iOS 中出现 ListView 之前,如何将 ListView 滚动位置设置为底部?【英文标题】:How to set a ListView Scroll position to bottom, before ListView will appears in Xamarin Forms iOS? 【发布时间】:2019-06-28 03:10:28 【问题描述】:

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);
                 
            
         
    

【问题讨论】:

检查我的更新答案。 【参考方案1】:

原因:

当您在方法OnElementChanged 中调用将列表视图滚动到按钮的代码时,列表视图尚未完成初始化。所以它没有用。

解决方案:

您可以在OnAppearing方法中使用MessagingCenter发送滚动列表视图的通知。

在您的内容页面中

 protected override void OnAppearing()
 
   base.OnAppearing();
   MessagingCenter.Send<Object>(this, "ScrollToButtom");
 

在 iOS 渲染器中

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);
            
        );
    


更新: 该解决方案在我的设备上运行良好。如果它仍然无法在您的项目上运行。您可以覆盖方法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,你可以下载试试。

【讨论】:

在我的情况下滚动有效。主要问题是明显的滚动。 OnAppearing 不合适,因为它使用户可以注意到滚动。我需要打开页面,并且列表视图已经必须滚动到底部位置,就像在 WhatApp 一样。我尝试使用 SetContentOffset(offset, false),但结果相同:在页面出现一次之前,滚动会很明显。 你试过我的解决方案了吗?列表视图在出现之前已经滚动 好的,我再检查一遍 你在哪里调用了SetContentOffset(offset, false)方法? 在 OnAppearing 事件引发时处理了 SetContentOffset (offset, false) 方法。【参考方案2】:

虽然这是一个 hack,但您可以隐藏表格,然后在它滚动时取消隐藏(或者玩透明度,这必须有效)。

【讨论】:

谢谢。但对我来说最好的解决方案是覆盖方法 WillDisplay

以上是关于在 Xamarin Forms iOS 中出现 ListView 之前,如何将 ListView 滚动位置设置为底部?的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.Forms/iOS,出现异常,“You_Should_Not_Call_Base_In_This_Method”?

Xamarin Forms - iOS 上的键盘覆盖条目(文本字段)

无法构建 Xamarin.Forms iOS 项目

mvvmcross xamarin.forms PictureChooser

Xamarin.forms(或)xamarin.ios/xamarin.android(或)本机

在 iOS 上的 Xamarin.Forms.Maps 中使用 Xamarin.Essentials Geolocation 获取设备位置的奇怪问题