RecyclerView中的item的match_parent属性失效问题解决方案。

解决方案:

    1.  item使用RelativeLayout布局,并且布局中的view至少有一个layout_alignParentRight=true
    2. 在adapte中的onCreateViewHolder,使用
  
   public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//        View view = View.inflate(parent.getContext(), R.layout.item_fra_main2, null);
        View view = mInflater.from(mContext).inflate(R.layout.item_fra_main2, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

至今为止,Google了一轮都没有找到产生这个问题的原因,小编就不自量力一下,挖个秦始皇出来!

原理说明:

     
  代码一、
  View.inflate(parent.getContext(), R.layout.item_fra_main2, parent);
    对应的是:LayoutInflate.inflate(resource , parent, true);//在RecycleView下奔溃
 
  代码二、
  View.inflate(parent.getContext(), R.layout.item_fra_main2, null);
    对应的是:LayoutInflate.inflate(resource , null, false);//match_parent属性失效
 
   代码三、
    mInflater.from(mContext).inflate(R.layout.item_fra_main2, parent, false);    
    对应的是:LayoutInflate.inflate(resource , parent, false);//就需要这种方案

 

分析一:

    先看代码一的奔溃问题,奔溃的内容是 The specified child already has a parent. You must call removeView() on the child's parent first。
    这个问题可以追溯到ListView的原理,RecycleView的基本原理和ListView是一样的,就是布局复用。
   

   
  
   由于Root就是RecycleView,因此,已经有了childView就不应再addView进去了。

分析二、

      现在就看为什么代码二中的match_parent失效问题了,以及代码三的match_parent有效的情况。

     先说代码三,分析原因肯定是跟源码了

   

  

  

 
     从源码中可以看出,传入
 parent 参数,null与非null的分水岭就在于,对childView是否需要setLayoutParams。

     来看看setLayoutParams 里面都做了什么?

     

      

     这里有一段非常的重要,就是childview会去通知parentVIew也去调用这个函数。因此直到最底部的RootView都会被通知调用这个函数。

    

分析三、    

        现在知道分水岭之后。就要看看RecycleView是怎么加载ChildView的了。 

    直接调出RecyclerView.java类,RecycleView中有个mChildHelper变量。  

    


   找到了加载ChildView的入口。继续跟踪到AddView里面(ViewGroup.java)

  

    哈哈!这边又有一个分水岭,从Inflate中的分水岭关于Params的问题,这边就呈现出来了。

   

    如果,Inflate中设置了Parent,那么RecycleView就会使用ChildView配置的params去add ChildView。因此,这时候的match_parent就会生效。

   

分析四、

         那为什么params为null后,addView()函数导致了childview中的match_parent实效呢?导致实际的效果与预想不同,而只是自适应大小。

     再研究下addView的源码:

     里面有句话child.getLayoutParams(),而getLayoutParams方法说明中有句话为:This method may return null if this View is not attached to a parent ViewGroup。意思就是如果没有被添加至父控件时,结果是会返回null的,很显然,到目前的代码跟踪情况来看,vChild还没有被添加至linParent,所以会去调用generateDefaultLayoutParams()方法,而generateDefaultLayoutParams的方法实现如下:

 

protected LayoutParams generateDefaultLayoutParams() { return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); }


 所以就很明显的造成了子布局android:layout_width="match_parent"属性失效。


分析过程有点复杂,但总算对View加载有了更加清楚的认识!

 问题提供者(geolo:http://blog.csdn.net/GEOLO)
   
    

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值