前言
虽然google文档中明确反对在ScrollView中嵌套ListView,但这种场景在UI设计中仍然很普遍,一般遇到的问题是ListView的高度计算不正确,该问题网上已经有很多解,本文要记录的是使用定制的控件主题后滑动效果的问题。
场景
当ListView数据很少,ScrollView内容区域未超过一屏时,ListView仍然存在滑动效果,UI要求页面顶部区域展示一张logo,logo下方存在一个高度根据内容计算的数据列表,在数据列表未占满屏幕时,页面整体只存在回弹效果,列表本身不能滑动。滑动控件的回弹由定制主题实现,但是在该主题下,ListView即便数据未被遮挡,仍然存在滑动回弹效果,如下图所示。
页面未滑动:
在空白处拖动,页面整体下拉滑动,松开后回弹:
在列表上下拉滑动,列表本身滑动并被遮挡,不是期望的页面整体滑动:
解决
问题显然出在ListView能够接收到滑动事件上,在验证时还发现,当ListView内容超过屏幕边界时,ListView就不存在滑动效果了。推测ScrollView在页面超过屏幕边界时intercept了滑动事件,未超过边界时仍然分发了事件。
打开SrollView源码找找证据:
在onInterceptTouchEvent方法中,第3个if判断条件证实猜测。
getScrollY==0说明scrollView顶部内容位置未变,canScrollVertically用于判断是否能向下滑动。
虽然定制主题让控件存在滑动回弹效果,但是并未改变控件本身的属性,这两个方法返回值是正确的。
canScrollVertically是public方法,且ScrollView只在onInterceptTouchEvent中调用了,可以安全的重写。
创建CustomSrollView,重写canScrollVertically方法,验证问题解决。
结束
Android版本多,厂商也多,SrollView嵌套ListView不仅会带来性能问题,也会带来一些适配问题,不偷懒定制ListView是更稳妥的解决方案。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。