在看过一篇文章

WPF自定义控件之列表滑动特效 PowerListBox  http://www.cnblogs.com/ShenNan/p/4993374.html#3619585 实现了滑动的特效(就是动画)之后 ,觉得很有趣 也想在 UWP里面实现。最好效果如下

接下来就说说是怎么实现的吧:

一. 添加 Behaviors

右键项目 选中 “管理 NuGet 程序包”

然后搜索 Behaviors 添加

二 . 添加一个新的类

这个类就叫

ListViewBehavior 

吧 继承 DependencyObject, 继承接口 IBehavior 然后显示继承这个接口的两个方法

  public class ListViewBehavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; set; } public void Attach(DependencyObject associatedObject)
{
throw new NotImplementedException();
} public void Detach()
{
throw new NotImplementedException();
}
}

然后在这个类里面添加一些属性,等会会用到

  public DependencyObject AssociatedObject { get; set; }

        /// <summary>
/// 需要做动画的列表
/// </summary>
public ListView ListView; /// <summary>
/// listView 里面的滚动条
/// </summary>
public ScrollViewer scroll;

/// <summary>
          /// 容器的布局方向
           /// </summary>
            private Orientation _panelOrientation;

 
/// <summary>
/// 当前可视化视图的第一项
/// </summary>
private int firstVisibleIndex; /// <summary>
/// 当前可视化视图的最后一项
/// </summary>
private int lastVisibleIndex; /// <summary>
/// 上次滚动时可视化视图的第一项
/// </summary>
private int oldFirstVisibleIndex; /// <summary>
/// 上次滚动时可视化视图的最后一项
/// </summary>
private int oldLastVisibleIndex; /// <summary>
/// 标识,是否已找到第一项
/// </summary>
private bool isFindFirst; /// <summary>
/// 当前累计已遍历过的Item高度或宽度的值,用于寻找第一项和最后一项
/// </summary>
private double cumulativeNum; public void Attach(DependencyObject associatedObject)
{ } public void Detach()
{ }

属性都准备好了那我们现在开始进入正式的后续吧 , 在 Attach 方法里面添加代码

public void Attach(DependencyObject associatedObject)
{
//获取 ListView 列表对象
ListView = associatedObject as ListView; if (ListView ==null )
{
return;
} //传进来的 对象不为空,我们就对这个对象注册一个事件
ListView.Loaded += ListView_Loaded;
}

ListView_Lodaded 代码:

 /// <summary>
/// 列表对象加载完成后的逻辑代码
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ListView_Loaded(object sender, RoutedEventArgs e)
{
//查找滚动视图,并赋值到我们刚刚添加的属性里
scroll = FindVisualChild<ScrollViewer>(ListView, "ScrollViewer");
//判断是否为空,不为空的话就添加一个事件
if (scroll == null)
{
return;
}
else
{
//监听滚动事件
scroll.ViewChanged += Scroll_ViewChanged;
}

ItemsPresenter v = FindVisualChild<ItemsPresenter>(ListView, "");


ItemsStackPanel items = FindVisualChild<ItemsStackPanel>(v,"");


_panelOrientation = items.Orientation;


        }
 /// <summary>
/// 获取模板控件
/// </summary>
/// <typeparam name="T">获取的类型</typeparam>
/// <param name="obj">控件对象</param>
/// <returns></returns>
protected T FindVisualChild<T>(DependencyObject obj, string name) where T : DependencyObject
{
//获取控件可视化树中的子对象数量
int count = VisualTreeHelper.GetChildrenCount(obj); //根据索引遍历每一个对象
for (int i = ; i < count; i++)
{
var child = VisualTreeHelper.GetChild(obj, i);
//根据参数判断是不是我们要找的对象,如果是 就返回,并退出该方法,
//如果不是则再递归到下一层查找
if (child is T && ((FrameworkElement)child).Name == name)
{
return (T)child;
}
else
{
var child1 = FindVisualChild<T>(child, name); if (child1 != null)
{
return (T)child1;
} }
} return null; }

现在已经获取到了 列表的 ScrollViewer 对象了 就可以执行这个 动画最核心的部分了,就是通过监听 滚动事件 来获取我们需要做动画的控件了。

 /// <summary>
/// 监听滚动事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Scroll_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
//每次滚动时都计算当前可视化区域的首尾项
CalculationIndex();
}

再添加两个字段

 /// <summary>
/// 列表子控件的高度
/// </summary>
private double itemsHeight;
//平移特效对象
private TranslateTransform tt;
  /// <summary>
/// 计算可视化区域的第一项和最后一项
/// </summary>
private void CalculationIndex()
{
//赋值旧的第一个可视化视图
oldFirstVisibleIndex = firstVisibleIndex;
//赋值最后一个可视化视图
oldLastVisibleIndex = lastVisibleIndex; ;
//标记第一项是否找到了
isFindFirst = false;
//判断列表的方向
if (_panelOrientation == Orientation.Vertical)
{
cumulativeNum = 0.0; //遍历列表的全部可视化视图,寻找第一项和最后一项
for (int i = ; i < ListView.Items.Count; i++)
{ //转换成 ListViewItem 对象,用于操作
var _item = ListView.ContainerFromIndex(i) as ListViewItem; //这里有个坑,应为 ListView 支持虚拟化的,所以每次获取列表的
//子项最多只会有20项左右,所以我们要记录一下 高度,将所遍历到的
//可视化视图的高度累加。 if (_item == null)
{ cumulativeNum += itemsHeight;
}
else
{
itemsHeight = _item.ActualHeight;
cumulativeNum += _item.ActualHeight + _item.Margin.Top + _item.Margin.Bottom; }
//判断当前所累加的高度大于我们滚动的距离找到 现在显示在屏幕上的第一项
if (!isFindFirst && cumulativeNum >= scroll.VerticalOffset)
{
//记录第一项的索性
firstVisibleIndex = i;
//表明第一项已经找到了
isFindFirst = true; Up();
} //当前所累加的高度 大于 当前移动的距离和 滚动视图的可见高度,找出最后一项
if (cumulativeNum >= (scroll.VerticalOffset + scroll.ViewportHeight))
{
//记录最后一项的索引
lastVisibleIndex = i; Down(); //已经找到的第一项和最后一项了 跳出循环
break;
} ; }
} }

最后 两个进行动画的方法:

  /// <summary>
/// 滚动条向下,类容向上移动
/// </summary>
private void Down()
{ if ((firstVisibleIndex == oldFirstVisibleIndex && lastVisibleIndex == oldLastVisibleIndex) || oldFirstVisibleIndex == && oldLastVisibleIndex == )
return; //判断 当前最后一项 是否大于上次移动的最后一项
if (lastVisibleIndex > oldLastVisibleIndex)
{
//获取可视化对象
var _item = ListView.ContainerFromIndex(lastVisibleIndex) as ListViewItem;
//
tt = new TranslateTransform(); //这里要判断一下 当前可视化是否为空,如果你移动得比较快的化,列表的虚拟化会给不到对象来的。
if (_item == null)
{
return;
} _item.RenderTransform = tt; Storyboard board = new Storyboard(); //创建一个 double 动画
DoubleAnimation animation = new DoubleAnimation() { AutoReverse = false, RepeatBehavior = new RepeatBehavior(), EnableDependentAnimation = true, To = , From = _item.ActualWidth / , Duration = TimeSpan.FromSeconds(0.2) };
Storyboard.SetTarget(animation, tt);
Storyboard.SetTargetProperty(animation, nameof(TranslateTransform.X)); board.Children.Add(animation); board.Begin(); }
} /// <summary>
/// 滚动条向上,内容向下
/// </summary>
private void Up()
{
if (firstVisibleIndex < oldFirstVisibleIndex)
{
var _item = ListView.ContainerFromIndex(firstVisibleIndex) as ListViewItem; tt = new TranslateTransform();
if (_item == null)
{
return;
}
_item.RenderTransform = tt; Storyboard board = new Storyboard(); DoubleAnimation animation = new DoubleAnimation() { AutoReverse = false, RepeatBehavior = new RepeatBehavior(), EnableDependentAnimation = true, To = , From = _item.ActualWidth / , Duration = TimeSpan.FromSeconds(0.3) };
Storyboard.SetTarget(animation, tt);
Storyboard.SetTargetProperty(animation, nameof(TranslateTransform.X)); board.Children.Add(animation); board.Begin(); }
}

这个了类已经完成了最后我们在前台调试一下吧:前台代码:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView x:Name="listView" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem" >
<Setter Property="HorizontalContentAlignment" Value="Stretch" ></Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Rectangle Height="" Fill="Red" HorizontalAlignment="Stretch" Margin="" ></Rectangle>
<TextBlock Text="{Binding }" FontSize="" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="" ></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate> <interactivity:Interaction.Behaviors>
<local:ListViewBehavior></local:ListViewBehavior>
</interactivity:Interaction.Behaviors>
</ListView> </Grid>

就这样我们就完成了一个滚动列表特效了,大家可以在 Down 和 Up 这两个方法里面修改其动画效果可以变得更加酷点,
第一次写博客。。。。。。。呜呜呜

uwp ListView列表滑动特效的更多相关文章

  1. WPF自定义控件之列表滑动特效 PowerListBox

    列表控件是应用程序中常见的控件之一,对其做一些绚丽的视觉特效,可以让软件增色不少. 本人网上看过一个视频,是windows phone 7系统上的一个App的列表滚动效果,效果非常炫 现在在WPF上用 ...

  2. Android一个ListView列表之中插入两种不同的数据

    http://www.cnblogs.com/roucheng/ Android一个ListView列表之中插入两种不同的数据 代码如下: public class ViewHolder{ Butto ...

  3. 【转】Android 实现ListView的滑动删除效果

    http://www.cnblogs.com/weixiao870428/p/3524055.html http://download.csdn.net/download/love_javc_you/ ...

  4. [置顶] android 自定义ListView实现动画特效

    通过自定义ListView实现动画特效,被点击元素A向前移,A之前元素往后移动. 重点在于动画的实现: 具体代码如下: package com.open.widget; import java.uti ...

  5. ListView列表拖拽排序

    ListView列表拖拽排序能够參考Android源代码下的Music播放列表,他是能够拖拽的,源代码在[packages/apps/Music下的TouchInterceptor.java下]. 首 ...

  6. Android 开源库StickyListHeadersListView来实现ListView列表分组效果

    项目中有一新的需求,要求能像一些Android机带"联系人列表"一样,数据可以自动分组,且在列表滑动过程中,列表头固定在顶部,效果图如下: 下面就带大家实现上面的效果, 首先,我们 ...

  7. 基于slideout.js实现的移动端侧边栏滑动特效

    HTML5现在本领太大了,PC端已经无法满足它的胃口了,它将强势攻入移动端,所以移动端中各种特效也得基于HTML5实现,看看我们将要介绍的slideout.js,能帮我们实现怎么样的侧边栏滑动特效呢~ ...

  8. Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果

    本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/18311877) 今天还是给大家带来自定义控件的编写,自定义一个Lis ...

  9. Android项目开发全程(四)-- 将网络返回的json字符串轻松转换成listview列表

    前面几篇博文介绍了从项目搭建到获取网络字符串,对一个项目的前期整体工作进行了详细的介绍,本篇接着上篇介绍一下怎么样优雅将网络返回的json字符串轻松转换成listview列表. 先上图,看一下效果. ...

随机推荐

  1. python之socket运用之传输大文件

    socket建议最大的传输单元是8192个字符,但是如果超过8192就会出现问题,我们可以用下面的方法处理 客户端代码 import subprocess import socket ip_bind ...

  2. Python学习记录day7

    目录 Python学习记录day7 1. 面向过程 VS 面向对象 编程范式 2. 面向对象特性 3. 类的定义.构造函数和公有属性 4. 类的析构函数 5. 类的继承 6. 经典类vs新式类 7. ...

  3. Spring依赖注入servlet会话监听器

    Spring提供了一个 “ContextLoaderListener” 监听器,以使 Spring 依赖注入到会话监听器. 在本教程中,通过添加一个 Spring 依赖注入一个bean 到会话监听器修 ...

  4. AOP不起作用的原因之一

    在-servlet.xml配置context:component-scan后,Spring在扫描包时,会将所有带 @Service注解的类都扫描到容器中.而-servlet.xml和applicati ...

  5. stl学习记录(1)

    Effective STL 中文版学习记录 条款4 判断容器是否为空 使用empty而不是size().size()操作在实现上不是一个时间常数操作条款5 尽量使用区间成员函数代替它们的单元素兄弟.S ...

  6. 2018.09.14 bzoj2982: combination(Lucas定理)

    传送门 貌似就是lucas的板子题啊. 练一练手感觉挺舒服的^_^ 代码: #include<bits/stdc++.h> #define mod 10007 #define ll lon ...

  7. java报错java/lang/NoClassDefFoundError: java/lang/Object

    安装完java出错 javac和java -version 都无效,报错如上 解决方法,更改文件中的两个文件(前提是你的 vim  /etc/profile  文件路径写的正确) /usr/java/ ...

  8. BZOJ 1008 [HNOI2008]越狱 (简单排列组合 + 快速幂)

    1008: [HNOI2008]越狱 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 10503  Solved: 4558[Submit][Status ...

  9. HDU 1503 Advanced Fruits (LCS+DP+递归)

    题意:给定两个字符串,让你求一个最短的字符串,并且这个字符串包含给定的两个. 析:看到这个题,我知道是DP,但是,不会啊...完全没有思路么,我就是个DP渣渣,一直不会做DP. 最后还是参考了一下题解 ...

  10. 百度地图(icon,zIndex)

    百度地图v2.0参考http://lbsyun.baidu.com/cms/jsapi/reference/jsapi_reference.html#a3b2 覆盖物(Marker) Icon: va ...