Xamarin.Form下拉刷新动画


Xamarin.Form 下拉刷新动画

Xamarin.Form


092058196273935.gif-194.9kB

照例, 上源码:

https://github.com/gruan01/ListViewExtend

目前只有 WP 的效果, Android 还在研究, IOS 的还没计划.


Xamarin.Form 的 ListView 只支持下拉刷新 (这里有用法), 上拉 加载更多 没有对应的事件. 这个先放一边, 今天先说说 WP 下, ListView 的下拉动画效果的替换.

用反编译工具查看 ListViewRenderer

092129437683520.jpg-318.8kB

OnElementChanged 中, 声明了一个 FixedLongListSelector 的控件, 然后将这个控件设为 NativeControl, 并对这个控件的 PullToRefreshXXXX 事件设置处理程序.

我的目的很简单, 就是替换掉下拉动画. 所以这几个事件必定是入口点.

FixedLongListSelector 继承自 LongListSelector, 很不幸, 它是 internal 的! 不过没关系, 用反射也很容易.

用反射清理/新增事件处理程序:

  1. private void ClearEventHandlers(object obj, string evtName) {
  2. var t = obj.GetType();
  3. //var fs = t.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
  4. var evt = t.GetEvent(evtName);
  5. var f1 = t.GetField(evtName, BindingFlags.NonPublic | BindingFlags.Instance);
  6. if (evt != null && f1 != null) {
  7. var handler = (EventHandler)f1.GetValue(obj);
  8. var ds = handler.GetInvocationList();
  9. evt.RemoveEventHandler(obj, handler);
  10. }
  11. }
  12. private void AddEventHandler(object obj, string evtName, Delegate handler) {
  13. var t = obj.GetType();
  14. var evt = t.GetEvent(evtName);
  15. evt.AddEventHandler(obj, handler);
  16. }

昨天有个面试的说他用的很多反射, 我随口就问了如何用反射清理已存在的事件处理程序, 并新增自已的处理程序, 小伙闸想了半天没回答上来 , 我是不是有点那个啊...

能清理和新增事件处理程序还不够, WP 的 LongListSelector 不自带下拉动画效果, XF 是通过新增一个 ProgressBar 来做的这个效果, 如下:

092144314554959.gif-86.3kB

这个 ProgressBar 默认是不可见的 (progressBar.Visibility = Visibility.Collapsed;), PullToRefreshXXXX事件的处理程序会跟据相关的属性, 对这个 ProgressBar 做更新, 已达到上面图上所示的动画效果.

知道了这些, 那就好办了, 我们额外定义一个 ListView 的渲染器:

https://github.com/gruan01/ListViewExtend/blob/master/ListViewExtend/ListViewExtend.WinPhone/Renders/ListViewRender.cs

自己声明一个 UIElement 对象, 通过 this.Children.Add(xxx) , 添加进来, 然后在自己的事件处理程序里对这个对象做动画播放与停止.

  1. 1 protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e) {
  2. 2 base.OnElementChanged(e);
  3. 3 ...
  4. 4 ...
  5. 5 this.Grid.Children.Add(this.Viewbox);
  6. 6 this.Viewbox.Child = this.Border;
  7. 7 this.Children.Add(this.Grid);
  8. 8 ...
  9. 9 this.SB = new SA.Storyboard() {
  10. 10 Duration = new Duration(TimeSpan.FromMilliseconds(1000)),
  11. 11 AutoReverse = true,
  12. 12 RepeatBehavior = SA.RepeatBehavior.Forever
  13. 13 };
  14. 14 ...
  15. 15 ...
  16. 16 this.OverrideEvents();
  17. 17 }
  1. private void UpdateIsRefreshing() {
  2. this.Grid.Visibility = this.Element.IsRefreshing ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
  3. if (this.Element.IsRefreshing)
  4. this.SB.Begin();
  5. else
  6. this.SB.Stop();
  7. }

代码很简单, 其它部分不在在赘述.

动画效果丑了点, 只做参考..

另外, 反编译了一下 Android 的 ListViewRenderer, 它的下拉刷新是通过 SwipeRefreshLayout 来实现的.

这个控件自带动画效果. 搜了一下, 好像它不能重写动画, 只能设置几个颜色....这就不好办了...

作者:xling
原文地址:http://www.cnblogs.com/xling/p/4634402.html

分享到