zoukankan      html  css  js  c++  java
  • 【UWP】列表项宽度自适应的实现

    目的

    在UWP开发中,我们常常用到两个显示列表的控件:ListView和GridView。而这两个列表控件在PC等大屏幕上如果能多列“智能”调整自己的大小(通常是根据当前窗口大小调整宽度),那么用户就会在同一屏幕内接收到更多信息,同时空间的利用率得以提高,也会提高应用的视觉体验。这是我的第一篇博客,向大家分享一下列表项宽度自适应的实现。

    实现思路及方法

    我们最初的想法可能是,定义列表项模板,给模板里的Panel起个名字,在窗口的SizeChanged事件里加入调整其宽度的代码。这种想法最朴素,然而在操作中遇到了一些问题:我们不能在后台代码里直接访问DataTemplete里的元素。而且,当同一页面中存在多个列表时,给大家都分配一个名字也比较傻,而且后台代码会堆积,不利于维护。

    这个时候,数据绑定就可以大显身手了。

    我们可以在Xaml里定义一个随便什么元素(当然,它只起到一个“桥”的作用,不能影响当前布局。(废话))这里,我们定义一个Border即可:

    1 <Border x:Name="width"/>

    然后,创建一个我们想要实现自适应的列表,注意其中的绑定

    1 <GridView  x:Name="testlist">
    2   <GridView.ItemTemplate>
    3     <DataTemplate>
    4       <Grid Width="{Binding ElementName=width,Path=Width}">
    5                ......                                    
    6       </Grid>
    7     </DataTemplate>
    8   </GridView.ItemTemplate>
    9 </GridView>

    接下来我们所要做的只有一步:在后台的SizeChanged事件中加入对width宽度的调整即可。这里为了方便,我们把它写成一个方法,可以放在自己App的Helper类里供应用内所有列表调用。这个方法长成这个样子:

     1   class WidthFit
     2     {
     3         /// <summary>
     4         /// 获取自适应列表项宽度
     5         /// </summary>
     6         /// <param name="width">当前窗口宽度</param>
     7         /// <param name="max">列表项最大宽度</param>
     8         /// <param name="min">列表项最小宽度</param>
     9         /// <param name="offset">偏移量</param>
    10         /// <returns></returns>
    11         public static double GetWidth(double width, int max, int min, int offset = 8)
    12         {
    13             if (offset < 0 || offset > 12)
    14             {
    15                 offset = 8;
    16             }
    17             double w = 1;
    18             int column = 1;
    19             int maxcolumn = (int)width / min;
    20             double i2 = width / min;
    21             for (int i = 1; i <= maxcolumn; i++)
    22             {
    23                 if (Math.Abs(i - i2) < 1) 
    24                 {
    25                     column = (int)Math.Truncate(i2) == 0 ? 1 : (int)Math.Truncate(i2);
    26                 }
    27             }
    28             w = width / column;
    29             w -= offset * column;
    30             return w;
    31         }
    32     }

    代码很易读,在这里不做过多说明。只说明一下,offset这个参数用来设定宽度的偏移量,因为我们的列表项之间、列表与父面板间通常会有间距,这个间距也要被考虑到,否则实际显示的列数可能会减少,很不美观。

    这样,我们可以方便地调用此方法:

    1 private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
    2 {
    3   width.Width = WidthFit.GetWidth(ActualWidth, 600, 300);
    4 }

    实现的效果就不贴出来了,大家可以动手试一试。

    还有什么没提到……

    ListView能实现这种效果吗?能。具体做法也很简单,更改一下ListView默认的ItemPanel即可,余下的工作与GridView完全一样。

     1 <ListView.Style>
     2     <Style TargetType="ListView">
     3         <Setter Property="ItemsPanel">
     4             <Setter.Value>
     5                 <ItemsPanelTemplate>
     6                     <ItemsWrapGrid  Orientation="Horizontal"/>
     7                 </ItemsPanelTemplate>
     8             </Setter.Value>
     9         </Setter>
    10     </Style>
    11 </ListView.Style>        

    到了要说“但是”的时候了。上面提到的GetWidth方法有一个小缺陷:可能会造成看上去像是“显示的列数受到损失”的情况(当然啦,这个概率很小)。我们发现,这个Bug出现在列数发生变动的临界值附近。而原因其实也很简单,此时我们定义的最大宽度小于当前窗口宽度与计算出的列数的比,因而无法铺满窗口的宽度,看上去就像是少了一列一样。这个小缺陷当然也易于修正,大家可以在GetWidth方法里做点文章,怠惰一点的话,也可以直接使最大宽度设置得大一点。

    明明快到考期了,可我还是“死猪不怕开水烫,越到考期我越浪”,强行水了我的第一篇博客。如果有什么错误与不周到的地方还望大佬们指正。我去补作业了……

  • 相关阅读:
    linux权限补充:rwt rwT rws rwS 特殊权限
    关于Linux操作系统下文件特殊权限的解释
    Java学习笔记——Java程序运行超时后退出或进行其他操作的实现
    Java实现 蓝桥杯 算法提高 判断名次
    Java实现 蓝桥杯 算法提高 判断名次
    Java实现 蓝桥杯 算法提高 日期计算
    Java实现 蓝桥杯 算法提高 日期计算
    Java实现 蓝桥杯 算法提高 概率计算
    Java实现 蓝桥杯 算法提高 概率计算
    Java实现 蓝桥杯 算法提高 复数四则运算
  • 原文地址:https://www.cnblogs.com/DaweiX/p/6158198.html
Copyright © 2011-2022 走看看