在看过一篇文章

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. VCP考试系统

      题目的格式如下,题目和题目之间用“==”隔开,每个题目的“题干”,“选项”,“答案”用“*”号隔开 An administrator wants to provide users restrict ...

  2. iPhone iPad 各种控件默认高度

    iPhone和iPad下各种常见控件的宽度和标准是一样的,所以这里就用iPhone说明. 以下是常见的几种控件的高度.Statusbar,Navigationbar和Tabbar的宽度极其图标大小. ...

  3. 20-java 对象链表空没空呢

    写了一个 对象链表,往里面add了一些对象,最后我想看下链表是否为空,用  == null  为假,也看不出, 看下长度? 好吧, size() = 1: 打印  null ,  那到底是不是空 啊, ...

  4. Struts2的拦截器技术

    1. 拦截器的概述 * 拦截器就是AOP(Aspect-Oriented Programming,面向切面)的一种实现.(AOP是指用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作 ...

  5. 如何定义一个高逼格的原生JS插件

    插件的需求 我们写代码,并不是所有的业务或者逻辑代码都要抽出来复用.首先,我们得看一下是否需要将一部分经常重复的代码抽象出来,写到一个单独的文件中为以后再次使用.再看一下我们的业务逻辑是否可以为团队服 ...

  6. Bioconductor简介

    Bioconductor简介 2012-10-09 ~ ADMIN 源:Bioconductor: open software development for computational biolog ...

  7. POJ 1122.FDNY to the Rescue! Dijkstra

    FDNY to the Rescue! Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 2808   Accepted: 86 ...

  8. Jmeter Ant Task如何让beanshell断言失败的详细信息展示在report里面

    首先必须给beanshell断言添加FailureMessage if(${TotalClient_SS}+2!=${TotalClient_SS2}){Failure=true;       Fai ...

  9. Hadoop 系列(一)基本概念

    Hadoop 系列(一)基本概念 一.Hadoop 简介 Hadoop 是一个由 Apache 基金会所开发的分布式系统基础架构,它可以使用户在不了解分布式底层细节的情況下开发分布式程序,充分利用集群 ...

  10. 2018.08.18 NOIP模拟 travel(贪心)

    Travel 题目背景 SOURCE:NOIP2015-SHY4 题目描述 小 A 要进行一次旅行.这回他要在序号为 1 到 n 的 n 个城市之间旅行.这 n 个城市之间共有 m 条连接两个城市的单 ...