實習中遇到了ScrollView裏放置一個ListView的情況,照常書寫代碼測試的時候出現這種情況:
就是隻顯示一個item的高度。上網搜索了之後才知道是ScrollView嵌套ListView會無法正確計算高度,導致只顯示一個item的高度。
網上解決的思路也有很多,一種是不要在ScrollView裏放置ListView,換成其他的佈局方式比如ScrollView+LinearLayout或者直接用ListView在其headview裏完成需要的複雜佈局等等。第二種思路就是既然無法計算正確高度就重寫高度測量的方法來達到解決問題的目的。
就第二種思路又有多種方法,以下是我測試過的方法均可以解決這個問題。
第一種方法:寫一個方法重新測量高度並設置給listview即可。
public static void setListViewHeightBasedOnChildren(ListView listView) {
//獲得adapter
MyAdapter adapter = (MyAdapter) listView.getAdapter();
if (adapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0; i < adapter.getCount(); i++) {
View listItem = adapter.getView(i, null, listView);
listItem.measure(0, 0);
//計算總高度
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
//計算分割線高度
params.height = totalHeight + (listView.getDividerHeight() * (adapter.getCount() - 1));
//給listview設置高度
listView.setLayoutParams(params);
}
在設置完adapter後調用下這個方法即可。
MyAdapter adapter = new MyAdapter();
listview.setAdapter(adapter);
setListViewHeightBasedOnChildren(listview);
顯示效果如下:
但是這個方法也有個缺點,就是ScrollView裏面必須是LinearLayout,如果不是就沒有效果。
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"></ListView>
</LinearLayout>
</ScrollView>
第二種方法:就是自定義一個ListView重寫onMeasure方法
package com.sy.mylistview;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
/**
* Created by SY on 2016/6/15.
*/
public class MyListView extends ListView {
public MyListView(Context context) {
super(context);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//重新設置高度
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);這個方法就是根據傳入的大小和模式生成一個MeasureSpec類型的32位int值。用兩位來表示模式,剩下30位表示大小。 所以傳入的Integer.MAX_VALUE >> 2就是30位的最大值,模式是MeasureSpec.AT_MOST即表示子視圖最多隻能是specSize中指定的大小,最大不超過這個大小。關於onMeasure方法的詳解可以看http://blog.csdn.net/guolin_blog/article/details/16330267來理解。
最後只要把原來的ListView換成自定義的ListView就可以了,一樣可以正常顯示了。
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.sy.mylistview.MyListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"></com.sy.mylistview.MyListView>
</ScrollView>