zoukankan      html  css  js  c++  java
  • ScrollView ViewPager ListView三者共存的问题

    随喜结佛缘

                    

             


        各位博友。此博文尚存在疏漏之处。仅供借鉴,请从事件的传递机制去思考解决方法,即什么时候某个控件能够滑动,在什么时候禁止其滑动,这样去思考。非常不好意思,此问题当时在做项目时遇到后攻克了问题,但源代码临时无法提供。

                          

    场景描写叙述:

            ScrollView是整个界面的外层滑动控件,嵌套在里面的布局是ViewPager。ViewPager里面当中一个Page是ListView控件。

    问题描写叙述:

           ViewPager中的ListView获取到数据后不能显示,也就是不能展开,外层ScrollView不能滑动.

    解决思路:

           1、让ListView展开。(网上的说法是ScrollView与ListView嵌套不可取,但开发中设计界面如此,不用也不成,闲话少说),想让ListView撑开,仅仅能依靠设置Adapter每一个Item高度,然后计算全部Item占用的总高度。从而得到ListView的高度,又一次设置ListView的高度(工具类都是网上的,我又多说话了还是粘在以下)。

          

    package com.goodwin.finance.util;
    
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ListAdapter;
    import android.widget.ListView;
    
    /**
     * 文件名称: com.goodwin.finance.util.ViewUtil
     * 作者:  熊杰 Wilson
     * 日期: 14-9-30
     * 时间: 14:28
     * 开发工具: IntelliJ IDEA 12.1.1
     * 开发语言: Java,Android
     * 开发框架:
     * 版本号: v0.1
     * <strong>软件中全部与布局相关的工具类</strong>
     * <p></p>
     */
    public class ViewUtil {
        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);
        }
    
        /**
         * 获取Listview的高度,然后设置ViewPager的高度
         * @param listView
         * @return
         */
        public static int setListViewHeightBasedOnChildren1(ListView listView) {
            //获取ListView相应的Adapter
            ListAdapter listAdapter = listView.getAdapter();
            if (listAdapter == null) {
                // pre-condition
                return 0;
            }
    
            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.getDividerHeight()获取子项间分隔符占用的高度
            //params.height最后得到整个ListView完整显示须要的高度
            listView.setLayoutParams(params);
            return params.height;
        }
    }
    

              使用方法是在获取到数据填充ListView适配器后。调用工具类的方法。

                        infoListAdapter = new TheInfoListAdapter(this);
                        infoListAdapter.setInfoList(infoList);
                        lvInfoList.setAdapter(infoListAdapter);
                        infoListAdapter.notifyDataSetChanged();
                        int listViewHeight = ViewUtil.setListViewHeightBasedOnChildren1(lvInfoList);
                        ViewGroup.LayoutParams params = vpImgpager.getLayoutParams();
                        params.height = listViewHeight;
                        vpZifuduo.setLayoutParams(params);


          2、为什么调用的是工具类的第2个方法。是由于第一个方法调用之后,它仅仅影响到ListView的高度,并不影响它外层ViewPager的高度,因此我重载了这种方法。将这个高度给返回,在改变ListView高度的同一时候,也将ViewPager的高度又一次动态设置。这样也就攻克了外层ScrollView不能滑动的问题。

    注意下细节:

            ListView的适配器Item用LinearLayout进行布局,给它指定一个固定高度(这个高度值固定对兼容来说无伤大雅),这样便于计算ListView的高度。

           3、附带的另外一个问题。ViewPager的左右滑动与ScrollView的上下滑动问冲突

            解决方法是自己定义一个ScrollView,然后重写一个onInterceptTouchEvent()方法

            下面是我本例中重写的ScrollView:

    package com.goodwin.finance.common.view;
    
    import android.content.Context;
    import android.os.Handler;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.widget.ScrollView;
    
    public class MyScrollView extends ScrollView {
        private float xDistance, yDistance, xLast, yLast;
    
        private OnScrollListener onScrollListener;
        /**
         * 主要是用在用户手指离开MyScrollView。MyScrollView还在继续滑动,我们用来保存Y的距离。然后做比較
         */
        private int lastScrollY;
    
        public MyScrollView(Context context) {
            this(context, null);
        }
    
        public MyScrollView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public MyScrollView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        /**
         * 设置滚动接口
         * @param onScrollListener
         */
        public void setOnScrollListener(OnScrollListener onScrollListener) {
            this.onScrollListener = onScrollListener;
        }
    
        /**
         * 用于用户手指离开MyScrollView的时候获取MyScrollView滚动的Y距离,然后回调给onScroll方法中
         */
        private Handler handler = new Handler() {
    
            public void handleMessage(android.os.Message msg) {
                int scrollY = MyScrollView.this.getScrollY();
    
                //此时的距离和记录下的距离不相等,在隔5毫秒给handler发送消息
                if(lastScrollY != scrollY){
                    lastScrollY = scrollY;
                    handler.sendMessageDelayed(handler.obtainMessage(), 5);
                }
                if(onScrollListener != null){
                    onScrollListener.onScroll(scrollY);
                }
    
            };
    
        };
    
        /**
         * 重写onTouchEvent, 当用户的手在MyScrollView上面的时候,
         * 直接将MyScrollView滑动的Y方向距离回调给onScroll方法中。当用户抬起手的时候。
         * MyScrollView可能还在滑动。所以当用户抬起手我们隔5毫秒给handler发送消息,在handler处理
         * MyScrollView滑动的距离
         */
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            if(onScrollListener != null){
                onScrollListener.onScroll(lastScrollY = this.getScrollY());
            }
            switch(ev.getAction()){
                case MotionEvent.ACTION_UP:
                    handler.sendMessageDelayed(handler.obtainMessage(), 5);
                    break;
            }
            return super.onTouchEvent(ev);
        }
    
    
        /**
         *
         * 滚动的回调接口
         *
         */
        public interface OnScrollListener{
            /**
             * 回调方法。 返回MyScrollView滑动的Y方向距离
             */
            public void onScroll(int scrollY);
        }
    
        /**
         *解决ViewPager与ScrollView手势冲突的问题
         */
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    xDistance = yDistance = 0f;
                    xLast = ev.getX();
                    yLast = ev.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    final float curX = ev.getX();
                    final float curY = ev.getY();
                    xDistance += Math.abs(curX - xLast);
                    yDistance += Math.abs(curY - yLast);
                    xLast = curX;
                    yLast = curY;
                    if(xDistance > yDistance){
                        return false;
                    }
            }
            return super.onInterceptTouchEvent(ev);
        }
    
    }
    


     

  • 相关阅读:
    用node.js从零开始去写一个简单的爬虫
    如何在手机上查看测试vue-cli构建的项目
    【干货】听说你想成为一名6的飞起的黑客,这些资料怎么能少
    用node.js从零开始去写一个简单的爬虫
    如何在手机上查看测试vue-cli构建的项目
    一个好用的在线微信二维码设计网站
    ES6-----学习系列十五(Iterator)
    js学习总结----js中常用的四种输出方式
    js学习总结----javascript引入到页面的方式和细节
    ES6-----学习系列十四(promise)
  • 原文地址:https://www.cnblogs.com/llguanli/p/7182714.html
Copyright © 2011-2022 走看看