zoukankan      html  css  js  c++  java
  • 安卓RecylerView嵌套和事件处理

    最近遇到了一个需求:RecylerView的某一项为listView,即listView嵌套,且要求内部ListView可以滑动,高度固定。

    如果直接简单的写完,会发现有两个问题:

    1.内部listView高度显示一行

    2.内部listview无法进行滑动

    以上两个问题可以用以下方法加以解决:

    针对问题1:

    解决方法1:在Adapter里面的onCreateViewHolder()方法里面加入以下方法,动态的设置该Item的高度。

        private void setListViewHeightBasedOnChildren(ListView listview){
            int totalHeight=0;
            for(int i=0,len=myListAdapter.getCount();i<len;i++){
                    View listItem=myListAdapter.getView(i,null,listview);
                    listItem.measure(0,0);
                    totalHeight += listItem.getMeasuredHeight();
            }
            ViewGroup.LayoutParams params=listview.getLayoutParams();
            params.height=totalHeight + listview.getDividerHeight() * myListAdapter.getCount();
            listview.setLayoutParams(params);
        }

    上面代码设置内部ListView的高度为其实际高度,如果有需求高度固定,则可以修改代码,将totalHeight改为固定值即可,此处可以很灵活的设置。

    解决方法2:方法1可以解决大部分问题,但是在我的项目中有个特殊的问题,即内部listview的item为textView,其中的文字个数是变化的,行数不定,在这种情况下,用getMeasuredHeight是无法获得多行情况下的textview实际高度的。这种情况下可以采用方法2,即:让内部listView继承自自定义ViewAutoHeightListView,具体代码如下:

    public class AutoHeightListView extends ListView {
    
        public AutoHeightListView(Context context) {
            super(context);
        }
    
        public AutoHeightListView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public AutoHeightListView(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);
        }
    }

    关键代码为复写onMeasure方法,将HeightMeasureSpec修改一下。原理墙裂推荐 http://www.cnblogs.com/xyhuangjinfu/p/5435201.html    原理简单概括以下就是,父类传递给Listview的高度测量模式默认为unSpecified,且在该模式下其计算自身高度为第一个子view的高度。上面代码将其修改为at_most模式,在该模式下其自身高度的计算为计算所有子View高度和。 

    针对问题2:

    原因在于ListView类似于ScrollView,两个嵌套的情况下,外部ListView会把用户的操作消费掉,无法传递分发给内部ListView,解决方法就从此处入手:将外部ListView改成自定义View,继承ListView并重写onIntercept()方法,将其返回值改为false,即外部listview不拦截触摸事件。

    public class ParentRecylerView extends RecyclerView {
        public ParentRecylerView(Context context) {
            super(context);
        }
        public ParentRecylerView(Context context, AttributeSet attrs, int defStyle){
            super(context,attrs,defStyle);
        }
        public ParentRecylerView(Context context, AttributeSet attrs){
            super(context,attrs);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            return false;
        }
    }

    经过以上两个设置,就可以实现本文提出的需求了。

  • 相关阅读:
    Android使用SharedPreferences
    Flex程序基本结构顺序结构程序设计
    FLEX程序设计函数
    FLEX程序设计XML(2)
    FLEX程序设计事件和事件机制鼠标事件
    FLEX字符串
    FLEX程序基本结构循环结构程序设计
    Enum 作为一个数据源绑定(收藏)
    FLEX程序设计数字处理
    flex程序设计面向对象基础
  • 原文地址:https://www.cnblogs.com/jymblog/p/6812609.html
Copyright © 2011-2022 走看看