一、ScrollView中嵌套ListView/GridView:

方法一:计算ListView的高度

public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
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);
}

处理方式:在将楼上这个方法拷贝到工具类中,在ListVIew.setAdapter 的下方调用这个方法即可,如下所示:

apprAdapter = new ApprovedPersonAdapter(mContext, mListAped);
mListView.setAdapter(apprAdapter);
ListHeightUtils.setListViewHeightBasedOnChildren(mListView);

方法二:重写ListView/GridView

重写ListView:

public class MyScrollVListView extends ListView {

public MyScrollVListView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}

public MyScrollVListView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public MyScrollVListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}

}

重写GridView:

public class MyScrollGridView extends GridView {
private boolean haveScrollbar = false;
public MyScrollGridView(Context context) {
super(context);
}
public MyScrollGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyScrollGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 设置是否有ScrollBar,当要在ScollView中显示时,应当设置为false。 默认为 true
*
* @param haveScrollbars
*/
public void setHaveScrollbar(boolean haveScrollbar) {
this.haveScrollbar = haveScrollbar;
}

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}

}

处理方式:和正常的布局ListView/GridView一样,只是这里需要用全路径,即可解决,如下所示:

<com.derek.views.MyScrollVListView
android:id="@+id/mListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</com.derek.views.MyScrollVListView>

方法三:LinerLayout代替ListView/GridView

1、先在需要布局ListView/GridView的地方布局上一个LinerLayout,如下所示:

<LinearLayout

android:id="@+id/mLinearLayout"

android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:adjustViewBounds="true"
android:background="#85808c"
android:orientation="vertical" >
</LinearLayout>

2、在FindViewById该对象,如下所示:

mLinearLayout= (LinearLayout) findViewById(R.id.mLinearLayout);

3、初始化数据

/**
* 动态添加数据
* @param jSONArrayOps
*/
private void initGridView(JSONArray jSONArrayOps) {
mLinearLayout.removeAllViews();

ArrayList<HashMap<String, Object>> lstItem = getOptionData();
SimpleAdapter saImageAdapter = new SimpleAdapter(mContext,
lstItem,// 数据源
R.layout.item_gridview_button,// 显示布局
new String[] {"itemText" },
new int[] { R.id.mBtnItemText });

mGridViewButton = new SquareGridView(mContext);
mGridViewButton.setAdapter(saImageAdapter);
int size = JSONArrayOps.length();
int numColumns = 0;
if (size%2 == 0) {
numColumns = 2;
}else if(size%3 == 0){
numColumns = 3;
}else{
numColumns = 2;
}
mGridViewButton.setNumColumns(numColumns);
//mGridViewButton.setColumnWidth(120);
mGridViewButton.setGravity(Gravity.CENTER);
mGridViewButton.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
//去掉点击效果的背景
mGridViewButton.setSelector(new ColorDrawable(Color.TRANSPARENT));
mGridViewButton.setVerticalSpacing(DensitydiUtil
.dip2px(mContext, 3));
int heigth = (int) getResources().getDimension(R.dimen.height_26_80);
if (size <= 2) {
mGridViewButton.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, heigth/2));
} else {
mGridViewButton.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, heigth));
}
/**监听事件**/
mGridViewButton.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String data = edtContent.getText().toString();
//***赋值的目的是为了点击拒绝时能促发后台修改数据**//*
if (TextUtils.isEmpty(data)) {
data = mContext.getResources().getString(R.string.strAppApproval);
}
try {
String mName = JSONArrayOps.getString(position);
requestApprovalData( mName,data);
Tools.printInfo(mName);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
// new LayoutParam(LayoutParam.FILL_PARENT, LayoutParam.FILL_PARENT)
mLinearLayout.addView(mGridViewButton);
}

如此将数据组装好后,该问题也基本解决了,mLinearLayout.removeAllViews();
表示先清空所有的View,便于每次添加进去的都是新的View。此方法在很多动态添加数据中都会用上,ListView的方法与此一样。


二、ScrollView嵌套ListView时,嵌套的布局是A布局+ListView+B布局的形式,当A布局中的内容超过一屏时,ListView的最后一个Item总是显示不全?

解决方案: (1)ListView不能用自定义的,必须用原生的ListView;

(2)ListView的宽高都用match_parent或fill_parent;

(3)用计算高度的方式去实现setListViewHeightBasedOnChildren(ListView);

(4)adapter的item的根布局必须为LinearLayout布局,不然计算高度时会有问题;

(5)ScrollView中添加属性android:fillViewport="true"

利用以上的5点,基本可以解决问题,我是这样解决,如果有没有解决的,请注意布局上看看有什么问题,把多余的功能去掉,从最基本的只显示ListView开始调节,一个功能一个功能的加上去,看看是哪里出问题,就逐步排除并解决。


ListView中嵌套ListView的处理在后续的文章中单独讲解,其实这三种方法网上也基本有的,只是便于android的学习记录一下这个过程。