最近做的几个功能都需要实现三层嵌套,所以先记录下来,方便以后使用。以下代码是从项目中摘取出来的,大体实现思路如下:
首先是重写ListView的onmeasure方法替代ListView,这个网上相关内容很多,具体代码如下:
public class CustomListView extends ListView {
public CustomListView(Context context) {
super(context);
}
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomListView(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);
}
}
主布局文件主要包括ScrollView与CustomListView,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/bg_common">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<com.example.xh.CustomListView
android:id="@+id/search_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="@color/transparent"
android:listSelector="@color/transparent"
android:scrollbars="none"
android:layout_marginTop="20dp"
android:dividerHeight="10dp"
android:divider="@color/bg_common_activity" />
</ScrollView>
</LinearLayout>
searchList的item项布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/white">
<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"
android:orientation="vertical" >
<com.example.xh.CustomListView
android:id="@+id/sub_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="@color/transparent"
android:listSelector="@color/transparent"
android:scrollbars="none"
android:dividerHeight="10dp"
android:divider="@color/white" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_station_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/metro_black_text_color"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_price"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/metro_black_text_color"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/metro_black_text_color"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
如子布局文件所示,searchList的item项中的ListView也使用CustomListView。
在searchList的Adapter的getView方法中,为subList设置Adapter后再重新计算subList的高度即可,searchList的getView方法如下所示:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder=null;
if(convertView==null){
convertView=inflater.inflate(R.layout.layout_list_item, null);
holder=new ViewHolder();
holder.subList=(CustomListView) convertView.findViewById(R.id.sub_list);
holder.standCountTxt=(TextView) convertView.findViewById(R.id.tv_count);
holder.priceTxt=(TextView) convertView.findViewById(R.id.tv_price);
holder.timeTxt=(TextView) convertView.findViewById(R.id.tv_time);
convertView.setTag(holder);
}else{
holder=(ViewHolder) convertView.getTag();
}
SubAdapter subAdapter=new SubAdapter(context, stationList.get(position).getTransferList());
holder.subList.setAdapter(subAdapter);
new Utility().setListViewHeightBasedOnChildren(holder.subList);
holder.standCountTxt.setText(stationList.get(position).getStandCount());
holder.priceTxt.setText(stationList.get(position).getPrice());
holder.timeTxt.setText(stationList.get(position).getTime());
}
其中setListViewHeightBasedOnChildren方法也会重新计算子list的高度,该方法实现如下:
public void setListViewHeightBasedOnChildren(ListView listView) {
// 获取ListView对应的Adapter
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0, len = listAdapter.getCount(); i < len; i++) { // listAdapter.getCount()返回数据项的数目
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0); // 计算子项View 的宽高
totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}