ListView与ScrollView冲突的4种解决方案

来源:互联网 发布:淘宝怎么装修店铺 编辑:程序博客网 时间:2024/05/18 00:40

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

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

 问题二:ScrollView不能正常滑动

问题三:Scrollview和Webview嵌套也会引起卡顿

解决方式一:

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(00);                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 = 0private final static int DOWNGLIDE = 1private int glideState; public ListScrollView(Context context, AttributeSet attrs) {  super(context, attrs); } private int downY = 0private 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)); }}
五。将Listview的滑动取消

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

六,设置Webview的不可滑动

public class MyWebview extends WebView{public MyWebview(Context context) {super(context);}public MyWebview(Context context, AttributeSet attrs) {super(context, attrs);}public MyWebview(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {                //首先DOWN事件,无论怎样都会传递到WebView中,这时                //可以调用requestDisallowInterceptTouchEvent,让Scroll                //View不拦截MOVE事件        case MotionEvent.ACTION_DOWN:                getParent().getParent().requestDisallowInterceptTouchEvent(true);            break;        case MotionEvent.ACTION_MOVE:        //在MOVE事件中,我们确定两种情况Scroll是需要ScrollView来执行        //如果WebView中的内容滑到顶部,这时就由ScrollView来执行        //Scroll动作。如果WebView中的内容滑到底部,这时就由        //ScrollView来执行Scroll动作。其他情况Scroll动作都由WebView        //来执行。                boolean scroll = true;                if (isTop()) {     //是否滑到顶部                    scroll = false;                } else if (isBottom()){    //是否滑到底部                    scroll = false;                }                getParent().getParent().requestDisallowInterceptTouchEvent(scroll);            break;        case MotionEvent.ACTION_UP:             getParent().getParent().requestDisallowInterceptTouchEvent(false);        }        return super.onTouchEvent(event);    }    private boolean isBottom() {        float htmlHeight = getContentHeight() * getScale();        float measuredHeight = getMeasuredHeight();        float currentheight = getHeight() + getScrollY();        Log.d("zhsy", htmlHeight + ", " + measuredHeight + ", " + getHeight() + ", " + getScrollY());        return htmlHeight == currentheight;    }    private boolean isTop() {        return getScrollY() == 0;    }}


0 0
原创粉丝点击