pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

ListView用法中與滾動相關的需求實現

這篇文章主要介紹了ListView用法中與滾動相關的需求實現,獲取并設置ListView的滾動位置,以及獲取滾動位置處的項目,具有一定的參考價值,感興趣的小伙伴們可以參考一下

在 App 的開發過程中,ListView 控件是比較常用的控件之一。掌握它的用法,能幫助我們在一定程度上提高開發效率。本文將會介紹 ListView 的一種用法——獲取并設置ListView的滾動位置,以及獲取滾動位置處的項目。這里多說一句,由于這個描述有點,所以本文的標題實在不好起。

舉個例子,如果你正在開發的應用有這樣一個需求,當用戶從一個列表頁(包括 ListView 控件)返回到前一頁面時,你需要得到用戶在瀏覽 ListView 中的內容到哪個位置以及哪一項了,以便告訴用戶最近瀏覽項,并且可以讓用戶再次打開列表時,直接從上次瀏覽的位置處繼續瀏覽。如下圖:

本文介紹了實現上述需求的方法。具體來說,這個需求可細分為兩個小需求,即:

  • 獲取、設置 ListView 的滾動位置;
  • 獲取 ListView 滾動位置處的項目。

以下我會通過上面配圖中的 Demo 應用逐一說明(本文末尾有源碼下載鏈接),這個 Demo 包括兩個頁面,一個主頁 (MainPage),一個列表頁 (ItemsPage)。主頁中包括:

按鈕:可以導航到 ItemsPage;
最近瀏覽信息區域:可以查看上次瀏覽的項目,并提供一個按鈕可以導航到列表頁中上次瀏覽的項目處;

而列表頁,則包括一個 ListView 控件,展示若干個項目。

一、獲取、設置 ListView 的滾動位置

關于獲取、設置 ListView 的滾動位置,微軟已經提供了相關的例子,我在這個 Demo 中是直接套用的。這個功能主要是通過 ListViewPersistenceHelper 來實現的,它提供以下兩個方法:


//獲取 ListView 的滾動位置
public static string GetRelativeScrollPosition(ListViewBase listViewBase, ListViewItemToKeyHandler itemToKeyHandler)

// 設置 ListView 的滾動位置
public static IAsyncAction SetRelativeScrollPositionAsync(ListViewBase listViewBase, String relativeScrollPosition, ListViewKeyToItemHandler keyToItemHandler)

這兩個方法中各有一個參考是委托類型,分別是ListViewItemToKeyHandler 和 ListViewKeyToItemHandler,它們的作用是告訴這個類如何處理列表項與 Key 的對應關系,好使得該類可以正確地獲取或設置滾動位置。這里的 Key 是 ListViewItem 所代表的項目的一個屬性(比如 Demo 中 Item 類的 Id 屬性),這個屬性的值在整個列表中是唯一的;而 Item 是在 Item 對象本身。在 Demo 中它們的實現分別如下:


 private string ItemToKeyHandler(object item)
  {
   Item dataItem = item as Item;
   if (dataItem == null) return null;

   return dataItem.Id.ToString();
  }

  private IAsyncOperation<object> KeyToItemHandler(string key)
  {
   Func<System.Threading.CancellationToken, Task<object>> taskProvider = token =>
   {
    var items = listView.ItemsSource as List<Item>;
    if (items != null)
    {
     var targetItem = items.FirstOrDefault(m => m.Id == int.Parse(key));
     return Task.FromResult((object)targetItem);
    }
    else
    {
     return Task.FromResult((object)null);
    }
   };
   return AsyncInfo.Run(taskProvider);
  }

實現這兩個方法后,重載列表頁的  OnNavigatingFrom 方法,在其中加入以下代碼,來實現獲取滾動位置并保存:


string position = ListViewPersistenceHelper.GetRelativeScrollPosition(this.listView, ItemToKeyHandler);
NavigationInfoHelper.SetInfo(targetItem, position);

繼續為頁面注冊 Loaded 事件,在 Loaded 事件中加入以下代碼來實現設置滾動位置:


 if (navigationParameter != null)
   {
    if (NavigationInfoHelper.IsHasInfo)
    {
     await ListViewPersistenceHelper.SetRelativeScrollPositionAsync(listView, NavigationInfoHelper.LastPosition, KeyToItemHandler);
    }
   }

這里需要注意的是,設置滾動位置的方法是異步的,所以 Loaded 方法需要加上 async 修飾符。而上述代碼中對 navigationParameter 參數的判斷則是為了區別:在導航時是否定位到最近瀏覽的位置,具體可參考 Demo 的代碼。

二、獲取 ListView 滾動位置處的項目

關于第二個需求的實現,我們首先需要明白以下三點:

  • ListView 的模板 (Template) 中包括 ScrollViewer,我們可以通過 VisualTreeHelper 獲取到此控件;
  • ListView 提供 ContainerFromItem 方法,它使們可以通過傳遞 Item 獲取包括此 Item 的 Container,即 ListViewItem;
  • UIElement 提供 TransformToVisual 方法,可以得到某控件相對指定控件的位置轉換信息;

所以我們的思路就是:得到 ListView 控件中的 ScrollViewer,并遍歷 ListView 中所有的 Item,在遍歷過程中,得到每一項目的 ListViewItem,并判斷它的位置是否位于 ScrollViewer 的位置中。以下是獲取 ListView 中當前所有可見項的代碼:


public static List<T> GetAllVisibleItems<T>(this ListViewBase listView)
  {
   var scrollViewer = listView.GetScrollViewer();
   if (scrollViewer == null)
   {
    return null;
   }

   List<T> targetItems = new List<T>();
   foreach (T item in listView.Items)
   {
    var itemContainer = listView.ContainerFromItem(item) as FrameworkElement;
    bool isVisible = IsVisibileToUser(itemContainer, scrollViewer, true);
    if (isVisible)
    {
     targetItems.Add(item);
    }
   }

   return targetItems;
  }

在上述代碼的 foreach 循環中的部分,正是我們前述思路的體現。而其中所調用的 IsVisibleToUser 方法,則是如何判斷某一 ListViewItem 是否在 ScrollViewer 中為當前可見。其代碼如下:


/// <summary>
  /// Code from here:
  /// https://social.msdn.microsoft.com/Forums/en-US/86ccf7a1-5481-4a59-9db2-34ebc760058a/uwphow-to-get-the-first-visible-group-key-in-the-grouped-listview?forum=wpdevelop
  /// </summary>
  /// <param name="element">ListViewItem or element in ListViewItem</param>
  /// <param name="container">ScrollViewer</param>
  /// <param name="isTotallyVisible">If the element is partially visible, then include it. The default value is false</param>
  /// <returns>Get the visibility of the target element</returns>
  private static bool IsVisibileToUser(FrameworkElement element, FrameworkElement container, bool isTotallyVisible = false)
  {
   if (element == null || container == null)
    return false;

   if (element.Visibility != Visibility.Visible)
    return false;

   Rect elementBounds = element.TransformToVisual(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
   Rect containerBounds = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);

   if (!isTotallyVisible)
   {
    return (elementBounds.Top < containerBounds.Bottom && elementBounds.Bottom > containerBounds.Top);
   }
   else
   {
    return (elementBounds.Bottom < containerBounds.Bottom && elementBounds.Top > containerBounds.Top);
   }
  }

可以看出,我們是能過得到兩個 Rect 值。Rect 類型的值代表一個矩形區域的位置和大小,我們對這兩個值進行比較后,返回最終的結果。

獲取 ListViewItem 的 Rect 值: element.TransformToVisual(container) 返回的結果是 GeneralTransform 類型,這個值表明了 ListViewItem 相對于 Container(即 ScrollViewer)的位置轉換信息。GeneralTransform 類型可能我們并不太熟悉,不過,從它派生出來的這些類: ScaleTransform、TranslateTransform ,我們就熟悉了,GeneralTransform 正是它們的基類。GeneralTransform 包括以下兩個重要的方法:

  • TransformPoint, 可以將得到的轉換信息計算成 Point 值,表示某控件相對于另一控件的坐標位置
  • TransformBounds,可以將得到的轉換信息計算成 Rect 值,表示某控件相對于另一控件的坐標位置及所占的區域。

所以,我們通過 TransformBounds 方法就得到了 ListViewItem 相對于 ScrollViewer 的位置和所占區域的信息。

獲取 ScrollViewer 的 Rect 值: 直接實例化一個 Rect,以 0,0 作為你左上角的坐標位置點, ScrollViewer 的 ActualWidth 和 ActualHeight 作為其大小。

接下來,就是比較的過程:這里,我們做了一個判斷,判斷是否要求元素 (ListViewItem) 完全在 ScrollViewer 中(而非僅部分在其中)。如果要求部分顯示即可,則只要元素的 Top 小于 Container 的 Bottom 值,并且元素的 Bottom 大于 Container 的 Top;如果要求全部顯示,那么算法是:元素的 Top 大于 Container 的 Top 并且元素的 Bottom 小于 Container 的 Bottom。如果您對語言描述或者代碼都還不明白,也可以在紙上畫一下進行比較。

接下來,我們照著 GetAllVisbleItems 方法的思路可以實現 GetFirstVisibleItem 方法,即獲取列表中第一個可見項,代碼可參考 Demo 的源碼,在此不再贅述。

我們在之前重載的方法 OnNavigatingFrom 中加上這句代碼,即可以獲取到用戶瀏覽位置處的那一項。


var targetItem = this.listView.GetFirstVisibleItem<Item>();

至此,所有主要功能已經基本完成。

結語

本文介紹了如何獲取和設置 ListView 的滾動位置,以及獲取滾動位置處的那一項,前者主要是借助于 ListViewPersistenceHelper 來實現,后者則是通過獲取 ListViewItem 和 ScrollViewer 的 Rect 值并進行比較而最終實現的。如果您有更好的方法、不同的看見,請留言,共同交流。

源碼下載

參考資料:

ListView Sample
How to get the first visible group key in the grouped listview

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持html5模板網。

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

主站蜘蛛池模板: 龙门加工中心-数控龙门加工中心厂家价格-山东海特数控机床有限公司_龙门加工中心-数控龙门加工中心厂家价格-山东海特数控机床有限公司 | 玖容气动液压设备有限公司-气液增压缸_压力机_增压机_铆接机_增压器 | 专业的新乡振动筛厂家-振动筛品质保障-环保振动筛价格—新乡市德科筛分机械有限公司 | 分类168信息网 - 分类信息网 免费发布与查询 | 无负压供水设备,消防稳压供水设备-淄博创辉供水设备有限公司 | 玉米深加工设备|玉米加工机械|玉米加工设备|玉米深加工机械-河南成立粮油机械有限公司 | 上海单片机培训|重庆曙海培训分支机构—CortexM3+uC/OS培训班,北京linux培训,Windows驱动开发培训|上海IC版图设计,西安linux培训,北京汽车电子EMC培训,ARM培训,MTK培训,Android培训 | POS机办理_个人POS机免费领取 - 银联POS机申请首页 | 水平垂直燃烧试验仪-灼热丝试验仪-漏电起痕试验仪-针焰试验仪-塑料材料燃烧检测设备-IP防水试验机 | 石牌坊价格石牌坊雕刻制作_石雕牌坊牌楼石栏杆厂家_山东嘉祥石雕有限公司 | 石家庄小程序开发_小程序开发公司_APP开发_网站制作-石家庄乘航网络科技有限公司 | 直齿驱动-新型回转驱动和回转支承解决方案提供商-不二传动 | 工控机-工业平板电脑-研华工控机-研越无风扇嵌入式box工控机 | 玻璃钢格栅盖板|玻璃钢盖板|玻璃钢格栅板|树篦子-长沙川皖玻璃钢制品有限公司 | 超声骨密度仪-骨密度检测仪-经颅多普勒-tcd仪_南京科进实业有限公司 | 干洗店加盟_洗衣店加盟_干洗店设备-伊蔻干洗「武汉总部」 | 煤粉取样器-射油器-便携式等速飞灰取样器-连灵动 | ERP企业管理系统永久免费版_在线ERP系统_OA办公_云版软件官网 | 深圳3D打印服务-3D打印加工-手板模型加工厂-悟空打印坊 | 真石漆,山东真石漆,真石漆厂家,真石漆价格-山东新佳涂料有限公司 | 济南网站策划设计_自适应网站制作_H5企业网站搭建_济南外贸网站制作公司_锐尚 | 不锈钢丸厂家,铝丸,铸钢丸-淄博智源铸造材料有限公司 | 佛山商标注册_商标注册代理|专利注册申请_商标注册公司_鸿邦知识产权 | 磁力去毛刺机_去毛刺磁力抛光机_磁力光饰机_磁力滚抛机_精密金属零件去毛刺机厂家-冠古科技 | 渣土车电机,太阳能跟踪器电机,蜗轮蜗杆减速电机厂家-淄博传强电机 | 企业管理培训,企业培训公开课,企业内训课程,企业培训师 - 名课堂企业管理培训网 | 武汉画册印刷厂家-企业画册印刷-画册设计印刷制作-宣传画册印刷公司 - 武汉泽雅印刷厂 | 天津仓库出租网-天津电商仓库-天津云仓一件代发-【博程云仓】 | 气弹簧定制-气动杆-可控气弹簧-不锈钢阻尼器-工业气弹簧-可调节气弹簧厂家-常州巨腾气弹簧供应商 | 镀锌角钢_槽钢_扁钢_圆钢_方矩管厂家_镀锌花纹板-海邦钢铁(天津)有限公司 | 上海洗地机-洗地机厂家-全自动洗地机-手推式洗地机-上海滢皓洗地机 | 深圳天际源广告-形象堆头,企业文化墙,喷绘,门头招牌设计制作专家 | 焊接烟尘净化器__焊烟除尘设备_打磨工作台_喷漆废气治理设备 -催化燃烧设备 _天津路博蓝天环保科技有限公司 | 艾默生变频器,艾默生ct,变频器,ct驱动器,广州艾默生变频器,供水专用变频器,风机变频器,电梯变频器,艾默生变频器代理-广州市盟雄贸易有限公司官方网站-艾默生变频器应用解决方案服务商 | 步进驱动器「一体化」步进电机品牌厂家-一体式步进驱动 | 垃圾压缩设备_垃圾处理设备_智能移动式垃圾压缩设备--山东明莱环保设备有限公司 | 贵州科比特-防雷公司厂家提供贵州防雷工程,防雷检测,防雷接地,防雷设备价格,防雷产品报价服务-贵州防雷检测公司 | 废气处理_废气处理设备_工业废气处理_江苏龙泰环保设备制造有限公司 | 智能风向风速仪,风速告警仪,数字温湿仪,综合气象仪(气象五要素)-上海风云气象仪器有限公司 | Copeland/谷轮压缩机,谷轮半封闭压缩机,谷轮涡旋压缩机,型号规格,技术参数,尺寸图片,价格经销商 CTP磁天平|小电容测量仪|阴阳极极化_双液系沸点测定仪|dsj电渗实验装置-南京桑力电子设备厂 | 好物生环保网、环保论坛 - 环保人的学习交流平台 |