CardView的layout_margin属性不起作用

使用CardView作为适配器的Item布局的根View,在RecyclerView.Adapter中的onCreateViewHolder中加载Item布局的时候,如果使用的LayoutInflater.from(Context).inflate(layoutId,null)这个方法来加载布局的话,那么Item布局中的CardView中的有些属性是无法起作用的,比如:android:layout_margin="xxdp",就算设置了这个属性,但是在5.1系统是不能显示为卡片式的,但是在4.4系统是可以显示为卡片式的。

如果要在5.1系统中也能显示为卡片式布局,那么需要更换inflate加载布局的方法,更换为LayoutInflater.from(Context).inflate(layoutId,parent,false),

使用这个方法,就能在5.1系统显示卡片式布局,同时在4.4系统同样能够显示卡片式。


从源码层面查看两个方法的区别:

调用这两个方法都会执行到LayoutInflater的inflate方法中:

  public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
     final Resources res = getContext().getResources();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                    + Integer.toHexString(resource) + ")");
        }

        final XmlResourceParser parser = res.getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
}
两个方法的区别:

1、LayoutInflater.from(Context).inflate(layoutId,null)

会先调用方法

 public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
        return inflate(resource, root, root != null);
    }

最终调用inflate方法时,三个参数分别是 inflate(layoutId,null,false)。

2、LayoutInflater.from(Context).inflate(layoutId,parent,false)

这个方法会直接执行上面的方法,此时参数分别是inflate(layoutId,parent,false),在这个例子中parent为RecyclerView的实例。

这里采用加载布局的方法不同,其实最终是传入inflate的参数不同,那么参数不同会导致什么结果呢?

进入下面的方法查看:

inflate(parser, root, attachToRoot)  
 public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
     //省略其他代码,直接看相关的代码
      if (root != null) {//第二种方法
          final View temp = createViewFromTag(root, name, attrs, false);//temp就是CardView

            // Create layout params that match root, if supplied
           params = root.generateLayoutParams(attrs);
           if (!attachToRoot) {
             // Set the layout params for temp if we are not
             // attaching. (If we are, we use addView, below)
            temp.setLayoutParams(params);//给temp设置ViewGroup.LayoutParams的属性(在本例中是GridLayoutManager)
           }
        }

       // 这个方法会将temp下的所有子控件全部加载进来。
       rInflate(parser, temp, attrs, true, true);

       if (root != null && attachToRoot) {//第二种方法会执行
             root.addView(temp, params);
          }

       if (root == null || !attachToRoot) {
            result = temp;//最终会返回这个result
          }
}
第一种方法是进入上面的方法后,加载完子控件后直接返回CardView,没有添加到root中,所以layout_margin属性不起作用,因为layout_margin属性是需要一个父控件作为参照物的,没有添加到root就没有参照物了。

第二种方法是加载完所有子控件并且添加到root后,再返回CardView,CardView已经有参照物父控件root,所以属性能起到作用。

在做的时候,因为采用的是第一种方法,一直android:layout_margin="xx"的值,但是一直都没起任何作用。在更换为第二种方法后,才显示正常。


写在最后的话:

本来想着能实现了就行了,但是作为一个有追求(...)的程序猿,必须得知道为什么会这样才行,所以才想看看源码,看能不能找到原因,看了这一点点源码后,就把自己的理解写出来了,正确与否还有待验证哈。

第一次涉及源码的解读分析,才发现还是看源码看得少,虽然是个简单的分析,但还是有收获的。


遗留问题:

还有一个问题是,为什么第一种方法在4.4系统时就可以显示想要的效果,在5.1系统就不能显示那种效果呢。

如果有人知道,能够知会一声就更好了。



 

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值