1.手动设置ListView高度
经过测试发现,在xml中直接指定ListView的高度,是可以解决这个问题的,但是ListView中的数据是可变的,实际高度还需要实际测量。于是手动代码设置ListView高度,在为ListView设置了Adapter之后使用,就可以解决问题了。
同时:mListview.setSelection(position);方法失效
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
public static void setGridViewHeightBasedOnChildren(GridView gridView) {
// 获取GridView对应的Adapter
ListAdapter listAdapter = gridView.getAdapter();
if (listAdapter == null) {
return;
}
int rows;
int columns = 0;
int horizontalBorderHeight = 0;
Class<?> clazz = gridView.getClass();
try {
// 利用反射,取得每行显示的个数
Field column = clazz.getDeclaredField("mRequestedNumColumns");
column.setAccessible(true);
columns = (Integer) column.get(gridView);
// 利用反射,取得横向分割线高度
Field horizontalSpacing = clazz
.getDeclaredField("mRequestedHorizontalSpacing");
horizontalSpacing.setAccessible(true);
horizontalBorderHeight = (Integer) horizontalSpacing.get(gridView);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
// 判断数据总数除以每行个数是否整除。不能整除代表有多余,需要加一行
if (listAdapter.getCount() % columns > 0) {
rows = listAdapter.getCount() / columns + 1;
} else {
rows = listAdapter.getCount() / columns;
}
int totalHeight = 0;
for (int i = 0; i < rows; i++) { // 只计算每项高度*行数
View listItem = listAdapter.getView(i, null, gridView);
listItem.measure(0, 0); // 计算子项View 的宽高
totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度
}
ViewGroup.LayoutParams params = gridView.getLayoutParams();
params.height = totalHeight + horizontalBorderHeight * (rows - 1);// 最后加上分割线总高度
gridView.setLayoutParams(params);
}
2.使用单个ListView取代ScrollView中所有内容
public View getView(int position, View convertView, ViewGroup parent) {
switch (position) {
case 1:
break;
default:
break;
}
return convertView;
}
3.自定义可适应ScrollView的ListView和gridview
public class NotRollListView extends ListView
{
public NotRollListView(android.content.Context context,
android.util.AttributeSet attrs)
{
super(context, attrs);
}
/**
* 重新计算高度
*/
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
public class NotRollGridView extends GridView
{
public NotRollGridView(android.content.Context context,
android.util.AttributeSet attrs)
{
super(context, attrs);
}
/**
* 重新计算高度
*/
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
4.采用添加HeaderView的方式
mCityLocalView = mLayoutInflater.inflate(R.layout.select_city_item_local, mLvCitylist,false);
mListview.addHeaderView(mCityLocalView);
注意:
1有点影响效率,3目前有不明问题,在有A~Z通讯录view的情况下,加载很慢
方法1和方法3会有一个问题:加载时默认显示的首项是ListView
2,4目前没什么问题,就是比较麻烦
解决方案:
1.手动滚动到顶端 mScrollView.smoothScrollTo(0, 0);
2.设置listview失去焦点 mListView.setFocusable(false);
注意:在xml布局里面设置android:focusable=“false”不生效
推荐方法2,4
1,3在加载多个item的时候会出现卡顿现象(因为每次渲染item都要计算在scrollview中的高度)
recycleview同样适用,数据不多的时候可以使用,数据多的话不建议
package com.jgw.supercode.ui.widget;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
/**
* Created by zx on 2016/7/26.
*/
public class NotRollRecyclerView extends RecyclerView {
public NotRollRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}