ListView与ScrollView冲突的4种接近方案

jopen 10年前

众所周知ListView与ScrollView都具有滚动能力,对于这样的View控件,当ScrollView与ListView相互嵌套会成为一种问题:

 问题一:ScrollView与ListView嵌套导致ListView显示不全面

 问题二:ScrollView不能正常滑动


解决方式一:

ScrollView+LinearLayout+ListView可以换成ScrollView+LinearLayout+LinearLayout,对于开发中,ScrollView所能滚动的样式形式各异,另外的话,ScrollView所显示的内容肯定不会太多,因此这种方案是合理而且可选的


解决方式二:

同样是替换:ListView具有HeaderView与FooterView2部分,因此,在非下拉刷新,上拉加载的需求中,完全可以使用ListView来代替ScrollView,因此是合理可选的方案


解决方式三:

主动计算和设置ListView的高度,这样的结果最终得出类似解决方案一效果,具体来说缺点是大材小用,但也是合理的解决办法。

    public class Utility {          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);          }      }

解决方式四:

复写ScrollView,从事件方向进行处理,缺点是灵活性不够好

public class ListScrollView extends ScrollView {   private List list = new ArrayList();   private int scrollPaddingTop; // scrollview的顶部内边距   private int scrollPaddingLeft;// scrollview的左侧内边距   private int[] scrollLoaction = new int[2]; // scrollview在窗口中的位置   private final static int UPGLIDE = 0;   private final static int DOWNGLIDE = 1;   private int glideState;   public ListScrollView(Context context, AttributeSet attrs) {    super(context, attrs);   }   private int downY = 0;   private int moveY = 0;      @Override   public boolean dispatchTouchEvent(MotionEvent ev) {    switch (ev.getAction()) {    case MotionEvent.ACTION_DOWN:     downY = (int) ev.getY();     //System.out.println("actiondown" + ev.getY());     break;    case MotionEvent.ACTION_MOVE:     moveY= (int) ev.getY();     //System.out.println("move" + moveY + "down" + downY);     if((moveY - downY) >= 0) {      //System.out.println("'''''''''DOWNGLIDE'''''''''''");      glideState = DOWNGLIDE;     } else {      //System.out.println("'''''''''UPGLIDE'''''''''''");      glideState = UPGLIDE;     }     break;    case MotionEvent.ACTION_UP:    default:     break;    }    return super.dispatchTouchEvent(ev);   }   @Override   public boolean onInterceptTouchEvent(MotionEvent ev) {    // 该事件的xy是以scrollview的左上角为00点而不是以窗口为00点    int x = (int) ev.getX() + scrollLoaction[0];    int y = (int) ev.getY() + scrollLoaction[1];    for (int i = 0; i < list.size(); i++) {     ListView listView = list.get(i);     int[] location = new int[2];     listView.getLocationInWindow(location);     int width = listView.getWidth();     int height = listView.getHeight();     // 在listview的位置之内则可以滑动     if (x >= location[0] + scrollPaddingLeft       && x <= location[0] + scrollPaddingLeft + width       && y >= location[1] + scrollPaddingTop       && y <= location[1] + scrollPaddingTop + height) {      //System.out.println(glideState);      if(( (listView.getLastVisiblePosition() == (listView.getCount()-1)) && (glideState == UPGLIDE) ) ) {       //System.out.println("up");       break;      }      if(( (listView.getFirstVisiblePosition() == 0) && (glideState == DOWNGLIDE))) {       //System.out.println("down");       break;      }      return false; //让子控件直接处理     }    }    return super.onInterceptTouchEvent(ev);   }   @Override   public boolean onTouchEvent(MotionEvent ev) {    return super.onTouchEvent(ev);   }         private void findAllListView(View view) {    if (view instanceof ViewGroup) {     int count = ((ViewGroup) view).getChildCount();     for (int i = 0; i < count; i++) {      if (!(view instanceof ListView)) {       findAllListView(((ViewGroup) view).getChildAt(i));      }     }     if (view instanceof ListView) {      list.add((ListView) view);     }    }   }   @Override   protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    scrollPaddingTop = getTop();    scrollPaddingLeft = getLeft();    getLocationInWindow(scrollLoaction);   }   @Override   protected void onLayout(boolean changed, int l, int t, int r, int b) {    super.onLayout(changed, l, t, r, b);    if (this.getChildCount() != 1) {     try {      throw new ScrollException();     } catch (ScrollException e) {      e.printStackTrace();     }    }    list.clear();    findAllListView(this.getChildAt(0));   }  }