当ListView放在ScrollView中的时候,无论你设置高度为 match_parent(填充父窗体)和wrap_content(包裹内容)都只显示一行,这是你把ListView放在LinearLayout 中,再给listview一个具体的高度,就可以显示多行了。

如:

<ScrollView android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <LinearLayout 
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical">
 <ListView 
 android:layout_width="fill_parent"
 android:layout_height="400dp"
 android:id="@+id/lv"></ListView>
 </LinearLayout> 
 </ScrollView>

 

 

-----------------------------------

1、手动设置ListView高度
    经过测试发现,在xml中直接指定ListView的高度,是可以解决这个问题的,但是ListView中的数据是可变的,实际高度还需要实际测量。于是手动代码设置ListView高度的方法就诞生了。

 

//第一种方法    将空件传过来调用下面的方法
 // setListViewHeightBasedOnChildren(lv);  
  
 //第一种方法
 public static void setListViewHeightBasedOnChildren(ListView listView){
 if (listView==null) return;
 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的高度了,在为ListView设置了Adapter之后使用,就可以解决问题了。
    但是这个方法有个两个细节需要注意:
        一是Adapter中getView方法返回的View的必须由LinearLayout组成,因为只有LinearLayout才有 measure()方法,如果使用其他的布局如RelativeLayout,在调用listItem.measure(0, 0);时就会抛异常,因为除LinearLayout外的其他布局的这个方法就是直接抛异常的,没理由…。我最初使用的就是这个方法,但是因为子控件的顶 层布局是RelativeLayout,所以一直报错,不得不放弃这个方法。
        二是需要手动把ScrollView滚动至最顶端,因为使用这个方法的话,默认在ScrollView顶端的项是ListView,具体原因不了解

//---------------------第二种方法---------------------------------------------------------------------------
 自定义可适应ScrollView的ListView
  
 //创建一个类继承ListView
 import android.content.Context;
 import android.util.AttributeSet;
 import android.widget.ListView;

 public class ListViewForScrollView extends ListView{  
 public ListViewForScrollView(Context context, AttributeSet attrs,
 int defStyle) {
 super(context, attrs, defStyle);
 // TODO Auto-generated constructor stub
 }  
 public ListViewForScrollView(Context context, AttributeSet attrs) {
 super(context, attrs);
 // TODO Auto-generated constructor stub
 }  
 public ListViewForScrollView(Context context) {
 super(context);
 // TODO Auto-generated constructor stub
 }
 /**
 * 重写该方法,达到使ListView适应ScrollView的效果
 */
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
 MeasureSpec.AT_MOST);
 super.onMeasure(widthMeasureSpec, expandSpec);
 }  
 }

 

这个方法只要重写onMeasure方法就行了,

在xml布局中和Activty中使用的ListView改成这个自定义ListView就行了

这个方法和方法1有一个同样的毛病,就是默认显示的首项是ListView,需要手动把ScrollView滚动至最顶端。

    • sv = (ScrollView) findViewById(R.id.act_solution_4_sv);
    • sv.smoothScrollTo(0, 0);
      //----------------使Listview和ScrollView滑动不冲突----------------------------------
     //设置ListView的滚动监听
     ll.setOnScrollListener(new OnScrollListener() {
    
     @Override
     public void onScrollStateChanged(AbsListView view, int scrollState) {
    
    
     }
    
     @Override
     public void onScroll(AbsListView view, int firstVisibleItem,
     int visibleItemCount, int totalItemCount) {
    
     if ((news.size()-1)==ll.getLastVisiblePosition()) {
     sv_scrollView.requestDisallowInterceptTouchEvent(false);
     }else{
     sv_scrollView.requestDisallowInterceptTouchEvent(true);
     }
     }
     });  
      
     
     //设置Listview的触摸监听事件
     ll.setOnTouchListener(new OnTouchListener() {
    
     @Override
     public boolean onTouch(View v, MotionEvent event) {
     if (event.getAction()==MotionEvent.ACTION_DOWN&&event.getAction()==MotionEvent.ACTION_MOVE) {
     sv_scrollView.requestDisallowInterceptTouchEvent(false);
     }else{
     sv_scrollView.requestDisallowInterceptTouchEvent(true);
     }
     return false;
     }
     });  
     ------------------------//注意:--在下面这个方法中--------应该给一个具体值   如:400-------
     /**
     * 重写该方法,达到使ListView适应ScrollView的效果
     */
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     //int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
    
     int expandSpec = MeasureSpec.makeMeasureSpec(400,MeasureSpec.AT_MOST);
    
     super.onMeasure(widthMeasureSpec, expandSpec);
     }