好像园子里对 Xamarin 感兴趣的人很少啊...
来, 先给各位爷们逗个笑, 本山大爷本色出演:
照例, 上源码:
https://github.com/gruan01/ListViewExtend
目前只有 WP 的效果, Android 还在研究, IOS 的还没计划.
------------------------------------------------------
Xamarin.Form 的 ListView 只支持下拉刷新 (这里有用法), 上拉 加载更多 没有对应的事件. 这个先放一边, 今天先说说 WP 下, ListView 的下拉动画效果的替换.
用反编译工具查看 ListViewRenderer
OnElementChanged 中, 声明了一个 FixedLongListSelector 的控件, 然后将这个控件设为 NativeControl, 并对这个控件的 PullToRefreshXXXX 事件设置处理程序.
我的目的很简单, 就是替换掉下拉动画. 所以这几个事件必定是入口点.
FixedLongListSelector 继承自 LongListSelector, 很不幸, 它是 internal 的! 不过没关系, 用反射也很容易.
用反射清理/新增事件处理程序:
private void ClearEventHandlers(object obj, string evtName) { var t = obj.GetType(); //var fs = t.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); var evt = t.GetEvent(evtName); var f1 = t.GetField(evtName, BindingFlags.NonPublic | BindingFlags.Instance); if (evt != null && f1 != null) { var handler = (EventHandler)f1.GetValue(obj); var ds = handler.GetInvocationList(); evt.RemoveEventHandler(obj, handler); } } private void AddEventHandler(object obj, string evtName, Delegate handler) { var t = obj.GetType(); var evt = t.GetEvent(evtName); evt.AddEventHandler(obj, handler); }
昨天有个面试的说他用的很多反射, 我随口就问了如何用反射清理已存在的事件处理程序, 并新增自已的处理程序, 小伙闸想了半天没回答上来 , 我是不是有点那个啊...
能清理和新增事件处理程序还不够, WP 的 LongListSelector 不自带下拉动画效果, XF 是通过新增一个 ProgressBar 来做的这个效果, 如下:
这个 ProgressBar 默认是不可见的 (progressBar.Visibility = Visibility.Collapsed;), PullToRefreshXXXX事件的处理程序会跟据相关的属性, 对这个 ProgressBar 做更新, 已达到上面图上所示的动画效果.
知道了这些, 那就好办了, 我们额外定义一个 ListView 的渲染器:
自己声明一个 UIElement 对象, 通过 this.Children.Add(xxx) , 添加进来, 然后在自己的事件处理程序里对这个对象做动画播放与停止.
1 protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e) { 2 base.OnElementChanged(e); 3 ... 4 ... 5 this.Grid.Children.Add(this.Viewbox); 6 this.Viewbox.Child = this.Border; 7 this.Children.Add(this.Grid); 8 ... 9 this.SB = new SA.Storyboard() { 10 Duration = new Duration(TimeSpan.FromMilliseconds(1000)), 11 AutoReverse = true, 12 RepeatBehavior = SA.RepeatBehavior.Forever 13 }; 14 ... 15 ... 16 this.OverrideEvents(); 17 }
private void UpdateIsRefreshing() { this.Grid.Visibility = this.Element.IsRefreshing ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed; if (this.Element.IsRefreshing) this.SB.Begin(); else this.SB.Stop(); }
代码很简单, 其它部分不在在赘述.
动画效果丑了点, 只做参考..
另外, 反编译了一下 Android 的 ListViewRenderer, 它的下拉刷新是通过 SwipeRefreshLayout 来实现的.
这个控件自带动画效果. 搜了一下, 好像它不能重写动画, 只能设置几个颜色....这就不好办了...