最近公司项目要求主页为上方多布局 下方list的形式 当list第一条滚动到顶部时 开始显示title 反之则隐藏title
第一感觉是用ScrollView嵌套ListView 然后判断ScrollView的滚动距离 控制title的显示与隐藏
结果发现ScrollView嵌套ListView之后 ListView只能显示一行数据 需要自定义ListView 重写ListView的onMeasure()方法
@Override
/**
* 重写该方法,达到使ListView适应ScrollView的效果
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
使用后发现ListView确实可以正常显示了 但是下拉刷新和上拉加载都没了 而且也失去了ListView的高性能
于是决定使用ScrollView的上拉加载来加载ListView的数据
并且ScrollView好像无法实时获取当前的滚动距离
百度了一下说需要自定义ScrollView 重写ScrollView的OnScrollChanged()方法结果就成了这样
<pre name="code" class="java">@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
View view = (View) getChildAt(getChildCount() - 1);
int d = view.getBottom();
d -= (getHeight() + getScrollY());
//滚动到底部时
if (d == 0) {
// you are at the end of the list in scrollview
// do what you wanna do here
scrollChangedListener.onScrollToBottom(l, t, oldl, oldt);
}
super.onScrollChanged(l, t, oldl, oldt);
scrollChangedListener.onScrollChanged(l, t, oldl, oldt);
}
public void setOnScrollChangedListener(
OnScrollChangedListener scrollChangedListener) {
this.scrollChangedListener = scrollChangedListener;
}
public interface OnScrollChangedListener {
/**
* 开始滚动时
*
* @param curx
* @param cury
* @param oldx
* @param oldy
*/
void onScrollChanged(int curx, int cury, int oldx, int oldy);
/**
* ScrollView滚动到底部
*
* @param curx
* @param cury
* @param oldx
* @param oldy
*/
void onScrollToBottom(int curx, int cury, int oldx, int oldy);
}
也就是增加了一个接口, 在onScrollChanged()方法里 调用了接口里的方法传递参数,再到需要调用的类里设置相应的监听即可获取滚动高度
而上面的 t 就是指当前滚动的高度
然后在MainActivity里调用了上方布局的getHeight()方法获取了上方布局的高度
判断 t 是否大于 上方布局高度 大于则显示title 小于则隐藏
同时上啦加载也实现了
但是又发现一个问题 :listView在上拉加载数据时界面会卡在那里 加载完成后才能恢复
调试发现问题在于加载数据时listView调用了n次onMeasure()方法来测量子控件高度
这就尴尬了。。。
不重写onMeasure()方法 ListView只能显示一条
而重写了 上拉加载又卡在那里
百度了好多地方都没找到解决方法
又因为催的紧 又解决不了
无奈只能找别的方法,于是又找到一种方法:
将上方的布局与listView分开单独写成一个headerView
通过ListView.addHeaderView(headerView)方法添加到listView的头部
再设置headerView相应的点击事件
这样整个界面就是一个ListView了 高性能又回来了 下拉刷新上拉加载也回来了
不过发现一个问题:ListView好像也没有获取当前滚动距离的方法
无奈继续百度,结果还是要重写ListView里面的onScroll方法
而且又是一大堆算法,本人比较懒 换了个简单的。。。
</pre><pre name="code" class="java"><pre name="code" class="java">@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.visibleItemCount = visibleItemCount;
visibleLastIndex = firstVisibleItem + visibleItemCount - 1;
// 当前列表中最后一个可见的Item的Position 大于等于页面可显示的Item个数
if (getLastVisiblePosition() >= visibleItemCount) {
if (showTitleListener != null) {
showTitleListener.onShowTitle();
}
} else {
if (showTitleListener != null) {
showTitleListener.onHideTitle();
}
}
}
public void setOnShowTitleListener(OnShowTitleListener showTitleListener) {
this.showTitleListener = showTitleListener;
}
public interface OnShowTitleListener {
public void onShowTitle();
public void onHideTitle();
}
逻辑都很简单就不废话了,测试下来基本能满足要求了,呼~~~终于可以下班了

最近想了下 换了一个方向 问题基本解决了 代码如下:
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.visibleItemCount = visibleItemCount;
visibleLastIndex = firstVisibleItem + visibleItemCount - 1;
// 当前列表中第一个可见的Item的Position
if (firstVisibleItem > 0) {
if (showTitleListener != null) {
showTitleListener.onShowTitle();
}
} else {
if (showTitleListener != null) {
showTitleListener.onHideTitle();
}
}
}