Android ListView功能扩展,实现高性能的瀑布流布局,kotlin入门教程

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() 方法的参数:

void fillGap(boolean down, int startOffset) {

final int count = getChildCount();

startOffset = count > 0 ? startOffset + mDividerHeight : get

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值