修正开源项目TableFixHeaders滑动不流畅的问题

修正开源项目TableFixHeaders滑动不流畅的问题,有需要的朋友可以参考下。TableFixHeaders项目介绍: http://jcodecraeer.com/a/opensource/2014/1113/1970.html

最近因为项目的原因,使用了TableFixHeaders来处理表格数据,却遇到了左右,上下滑动时,不够流畅的问题,,与系统提供的scrollView的滑动有着很大的区别。我是个菜鸟,没有读过scrollView的源码,也没有很高深的view滑动绘制的经验,各位大虾们就不要喷了。

先说说TableFixHeaders实现的原理。

TableFixHeaders继承自ViewGroup,每一个表格都被设计成一个子View,通过在onLayout和onMeasure里面,重新设定每一个子View的顺序以及位置,来绘制所有的view。

我理解的是,它在一开始就绘制了所有的的子View。 在滑动的时候,好像有动态的添加和移除子View,我看的不是太明白。

在视图滑动的时候,通过监听手势,来重新绘制子View,来达到滑动的效果,通过Flinger类,来实现滚动的效果。

下面是重点,主要是描述我遇到的问题,以及解决的方案。

我遇到的第一个问题,是我看不懂下面的代码:

源码中的第798行开始:

private void addTableView(View view, int row, int column) {
    if (row == -1 && column == -1) {
        addView(view, getChildCount() - 4);
    } else if (row == -1 || column == -1) {
        addView(view, getChildCount() - 5);
    } else {
        addView(view, 0);
    }
}

阅读源码,可以看到所有的子table(子表格)都是通过这个方法加到ViewGroup里面去的。里面居然出现这样的代码 addView(view,index),这个index是可以为负数的。

我一直以为这个index最小是0,然后依次排列。比如我要添加5个view到ViewGroup里面,一般情况下是addView(view,0),addView(view,1),addView(view,2)...等等。它这边全部通过addView(view, 0)来实现。这不就是在不停的替换子view吗?

实际上不是的,写几个测试程序,才发现,不停的addView(view, 0)是可以实现顺序addview的.. 涨见识了。

第二个问题,为什么滑动的时候,总是不流畅。

我看了原作者在处理事件的时候,确实写了滑动,速度监听以及滚动的处理。,为什么会没有生效。

经过测试,我发现在case MotionEvent.ACTION_UP:里面:

final VelocityTracker velocityTracker = this.velocityTracker;
velocityTracker.computeCurrentVelocity(1000, maximumVelocity);
int velocityX = (int) velocityTracker.getXVelocity();
int velocityY = (int) velocityTracker.getYVelocity();

这片程序获得的velocityX 和velocityY 总是零,下面的flinger.start()方法完全不可能会启用,所以界面不会滚动,只有滑动的效果。

找到问题了,解决方案就来了。 首先写测试程序,velocityX 和velocityY在什么情况下,才有值,是正在在检测滑动。 很容易发现,这2个值,只有在case MotionEvent.ACTION_MOVE时会有值,case MotionEvent.ACTION_UP时已经变为零了。

解决办法,将velocityX 和velocityY 这2个值变为全局,在MotionEvent.ACTION_MOVE里面获取,在case MotionEvent.ACTION_UP里面调用,调用结束后直为零。

这样修改过之后,我立刻去调试,发现界面确实可以滑动了,但是是偶尔会滑动,偶尔不会滑动。 只有在我非常认真的滑动时,才会滑动,随手一滑,是不会动的。

这给了我很大的信心,继续检测velocityX 和velocityY 值,发现随手一滑,这2个值会在最后变为0,导致界面不滑动。

解决办法,MotionEvent.ACTION_MOVE里面添加临时变量,当velocityX 和velocityY 值不为0时,才赋值给velocityX 和velocityY 值,以便于传递给case MotionEvent.ACTION_UP。修正之后,滑动十分顺畅。

之后做过简单测试,在samsung S5和华为荣耀3C上测试,十分流畅。

结束语:因为我不懂界面如何滑动,如何绘制。这看似简单的bug,却足足困扰了我将近1个礼拜的时间。 好在原作者十分给力,事先就想好了一切,只是有个小bug。

不足的地方是,滑动时没有滚动条,滑动顶部和底部时,没有彩色图案,用于标记不能再滑了。