一.ScrollView嵌套ListView,只显示一行问题解决
要让ListView
显示完整,需要在ListView
的数据源赋值后,获取ListView
的Item
的数量,既可以得到ListView
所需的实际高度,然后重新给ListView
分配高度即可。此方案可以完美解决显示一行的问题,而且不需要自定义控件即可实现。
/*
* 根据列表项个数动态设置ListView高度,解决ScrollView嵌套ListView只显示一行问题
*/
private void setListViewHeightByItemCount(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int allItemsHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
//获取所有Items的高度和
allItemsHeight += listItem.getMeasuredHeight();
}
//获取ListView中的所有分割线高度和,如果没有则为0
int alldevideLineHeight = (listView.getDividerHeight() * (listAdapter.getCount() - 1));
//给ListView设置高度
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = allItemsHeight +alldevideLineHeight;
listView.setLayoutParams(params);
}
注:如果ListView
的数据量很大,需要新起一个线程调用此方法,并用Handler同步,这样可加快页面渲染速度
二.仅保留ScrollView的滚动效果,禁用ListView的滚动
1.在ListView上滑动,也触发父类ScrollView的滑动效果方式
应用场景:下拉ListView缩放父类ScrollView中的顶部图片。
要想让ScrollView
滚动,只需要让ScrollView
子布局高度超出ScrollView
的高度即可。如果内容多,超出父类即可实现了,可如果子类布局的高度不足超出父类的ScrollView
,该怎么办?提供一个方案,将ScrollView
子布局最底部的控件的android:layout_marginBottom="25dp"
属性值,调整到一个恰当大的值,即可让ScrollView
触发滚动。ListView的高度可以用第一步
中提供的方法解决。
2.在ListView滑动,父类ScrollView不会滚动的方式
这种效果,可以让页面保持单屏,但ListView的滑动效果就被终结了,只能触发ScrollView的滚动事件。实现方式就是重写ListView。
package com.today.ui.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
/**
* 自定义NoScrollListview
*
* @see 防止Listview下滑事件和ScrollView的下滑事件冲突
*/
public class NoScrollListview extends ListView {
public NoScrollListview(Context context) {
super(context);
}
public NoScrollListview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NoScrollListview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 重设高度
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
三.让被嵌套的ListView滑动到顶端,ScrollView才能滚动
1.自定义ListView,支持滑动到顶部时,ScrollView获取滑动权
这种情况可能出现在下拉刷新中,下拉刷新中的自带的ScrollView
嵌套LInearLayout
再嵌套一个ListView
和其他布局的时候,这时候需要对ListView
的高度进行计算。
首先要自定义一个支持下拉刷新的ListView,实现当滑动到顶部时候,滑动权交给父类;当ListView
的第一项不在顶部的时候,滑动权在ListView
手上。
package com.today.ui.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;
/**
* 自定义PullRefreshListView
* @see 防止Listview下滑事件和下拉刷新的下滑事件冲突,重写onInterceptTouchEvent事件
*/
public class PullToRefreshListView extends ListView {
public PullToRefreshListView(Context context) {
super(context);
}
public PullToRefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// 判断是否滑动到顶部了
if (getFirstVisiblePosition() == 0 && getChildAt(0).getTop() == 0) {
// 滑动到顶部,父类获取到触摸事件,开始下拉刷新;
getParent().requestDisallowInterceptTouchEvent(false);
} else {
// 没有滑动到头部,父类拦截触摸事件,不会触发下拉刷新
getParent().requestDisallowInterceptTouchEvent(true);
}
return super.onInterceptTouchEvent(ev);
}
}
2.设置ListView的高度为ScrollView的剩余高度
这时候不能通过ListView
中的Items数量来设置高度了,而要通过计算下拉刷洗的ScrollView
的高度,将此高度设为ListView
的高度,这样ListView
中的Item
数量所需的高度,超过ScrollView
的高度的时候,就可以实现ListView
滚动,而ScrollView
不滚动的效果。
这个需要根据自己嵌套的布局个数计算,展示一个例子:一个下拉刷洗中嵌套了多个控件,计算ListView可以使用的高度
/**
* 将页面剩余高度设置为ListView的高度
*
* @param listView
*/
private void setRestHeightToListView(ListView listView) {
// 下拉刷新控件的高度,即顶级容器高度
int ptrHeight = mPullRefreshView.getMeasuredHeight();
// 下拉框高度(嵌套了一个下拉框)
int spinnerbarHeight = spinner_city.getMeasuredHeight();
// 标题栏高度(嵌套了一个文本框)
int deviceBarHeight = deviceBar.getMeasuredHeight();
// 分割线高度(嵌套了一个View)
int devideLineHeight = devide_line.getMeasuredHeight();
// ListView可用的剩余高度,即下拉刷新减去下拉框、分割线、标题栏的高度(实际高度计算)
int restHeight = ptrHeight - spinnerbarHeight - devideLineHeight - deviceBarHeight;
// 获取ListView的参数
ViewGroup.LayoutParams params = listView.getLayoutParams();
// 组装参数
params.height = restHeight;
// 设置ListView的高度
listView.setLayoutParams(params);
// ListView代理视图也设置为此高度,即可实现居中显示
listView.getEmptyView().setLayoutParams(params);
}
这一步主要是保证,ListView
的高度刚好填满ScrollView
,ListView
就可以滚动了。否则ScrollView
就会优先滚动,而ListView
就会失去了滑动权。所以高度一定要算对,里面的任何一条细线都不要漏掉,只要ScrollView
能滚动,而ListView
是固定不动的,这就有可能是你的高度算错了,检查下。