Android ListView功能扩展,实现高性能的瀑布流布局

本文详细介绍了如何在Android中扩展ListView,实现高性能的瀑布流布局。通过对原有ListView的改造,包括列宽计算、子View布局调整、缓存管理和滑动优化,实现了流畅的瀑布流滚动效果。内容包括对滑动事件的处理,子View的回收与复用,以及在滑动过程中如何避免空白区域,确保每一列都被填满。
摘要由CSDN通过智能技术生成

final int footerViewsStart = mItemCount - getFooterViewsCount();

final int top = listPadding.top - incrementalDeltaY;

for (int i = 0; i < childCount; i++) {

final View child = getChildAt(i);

if (child.getBottom() >= top) {

int position = firstPosition + i;

if (position >= headerViewsCount && position < footerViewsStart) {

mRecycler.addScrapView(child);

int columnIndex = (Integer) child.getTag();

if (columnIndex >= 0 && columnIndex < mColumnCount) {

mColumnViews[columnIndex].remove(child);

final int bottom = getHeight() - listPadding.bottom - incrementalDeltaY;

for (int i = childCount - 1; i >= 0; i–) {

final View child = getChildAt(i);

if (child.getTop() <= bottom) {

int position = firstPosition + i;

if (position >= headerViewsCount && position < footerViewsStart) {

mRecycler.addScrapView(child);

int columnIndex = (Integer) child.getTag();

if (columnIndex >= 0 && columnIndex < mColumnCount) {

mColumnViews[columnIndex].remove(child);

mMotionViewNewTop = mMotionViewOriginalTop + deltaY;

mBlockLayoutRequests = true;

detachViewsFromParent(start, count);

tryOffsetChildrenTopAndBottom(incrementalDeltaY);

final int absIncrementalDeltaY = Math.abs(incrementalDeltaY);

if (spaceAbove < absIncrementalDeltaY || spaceBelow < absIncrementalDeltaY) {

fillGap(down, down ? lastBottom : firstTop);

if (!inTouchMode && mSelectedPosition != INVALID_POSITION) {

final int childIndex = mSelectedPosition - mFirstPosition;

if (childIndex >= 0 && childIndex < getChildCount()) {

positionSelector(getChildAt(childIndex));

mBlockLayoutRequests = false;

invokeOnItemScrollListener();

从第 9 行开始看,这里我们使用了一个循环,遍历瀑布流 ListView 中的所有列,每次循环都去获取该列的第一个元素和最后一个元素,然后和 firstTop 及 lastBottom 做比较,以此找出所有列中最靠近屏幕上边缘的元素位置和最靠近屏幕下边缘的元素位置。注意这里除了 firstTop 和 lastBottom 之外,我们还计算了一个 endBottom 的值,这个值记录最底部的元素位置,用于在滑动时做边界检查的。

最重要的修改就是这些了,不过在其它一些地方还做了一些小的改动。观察第 75 行,这里是把被移出屏幕的子 View 添加到 RecycleBin 当中,其实也就是说明这个 View 已经被回收了。那么还记得我们刚刚添加的全局变量 mColumnViews 吗?它用于缓存每一列的子 View,那么当有子 View 被回收的时候,mColumnViews 中也需要进行删除才可以。在第 76 行,先调用 getTag() 方法来获取该子 View 的所处于哪一列,然后调用 remove() 方法将它移出。第 96 行处的逻辑是完全相同的,只不过一个是向上移动,一个是向下移动,这里就不再赘述。

另外还有一点改动,就是我们在第 115 行调用 fillGap() 方法的时候添加了一个参数,原来的 fillGap() 方法只接收一个布尔型参数,用于判断向上还是向下滑动,然后在方法的内部自己获取第一个或最后一个元素的位置来获取偏移值。不过在瀑布流 ListView 中,这个偏移值是需要通过循环进行计算的,而我们刚才在 trackMotionScroll() 方法中其实已经计算过了,因此直接将这个值通过参数进行传递会更加高效。

现在 AbsListView 中需要改动的内容已经结束了,那么我们回到 ListView 当中,首先修改 fillGap() 方法的参数&

  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值