欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

可能会被忽略的ViewGroup默认generateDefaultLayoutParams

程序员文章站 2022-03-29 09:13:44
...

1. 引入思考问题的场景

先看一段listview adapter中getView的代码

 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        ViewHolder viewHolder = null;
        if (view == null || !(view.getTag() instanceof ViewHolder)) {

            view = new MyRelativeLayout(mContext);
            viewHolder = new ViewHolder(view);
            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }
//后面代码忽略不计
复制代码

解释一下MyRelativeLayout是我自定义的RelativeLayout
MyRelativeLayout 代码如下

public class MyRelativeLayout extends RelativeLayout {
    public MyRelativeLayout(Context context) {
        super(context);
        LayoutInflater.from(getContext()).inflate(R.layout.list_item, this);
    }

    public MyRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(getContext()).inflate(R.layout.list_item, this);
    }
//后面代码忽略不计
复制代码

R.layout.list_item xml内容如下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:orientation="vertical">


    <ImageView
        android:id="@+id/image"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@mipmap/ic_launcher_round"/>

    <TextView
        android:id="@+id/tx"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/image"
        android:gravity="center"
        android:text="@string/app_name"
        android:textSize="40dp"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_below="@id/tx"
        android:background="@color/colorPrimary"
        />
</RelativeLayout>
复制代码

布局很简单也就长这样

2. 发现问题与思考问题

好,演员都就位了,接下来,问MyRelativeLayout 的LayoutParams是啥,或者这么问吧 MyRelativeLayout 占宽高是多少?

额,我也是很懵逼的,一开始我以为宽高不就是R.layout.list_item xml的根节点的宽高吗? 结果发现并不是。 看现象吧

还有这个Log

最后发现 MyRelativeLayout 的LayoutParams 是 AbsListView类中generateDefaultLayoutParams方法定义的

@Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT, 0);
    }
复制代码

即MyRelativeLayout 真正的宽是填充父窗体的,高度是包裹内容,而不是上图红色部分。 就是说如果一个view 是new出来的 你在add进它父viewgroup的时候忘记设置LayoutParams时候,你的这个view 的LayoutParams 是由父类generateDefaultLayoutParams 补全的。这里ListView是默认补全 宽:MATCH_PARENT,高:WRAP_CONTENT,而不代表别的ViewGroup的子类都是这样默认补全的。所以读者还是赶紧看看各个ViewGroup以及其子孙类默认补全吧,知己知彼才能百战不殆(才能在自定义view中少出问题)

3. 总结

以下简单列举一下常见的布局吧 ViewGroup类

protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }
复制代码

FrameLayout类

 protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }
复制代码

RelativeLayout类

protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }
复制代码

LinearLayout类 (分横竖排列情况)

 protected LayoutParams generateDefaultLayoutParams() {
        if (mOrientation == HORIZONTAL) {
            return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        } else if (mOrientation == VERTICAL) {
            return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        }
        return null;
    }
复制代码

AbsListView (也就是GridView和ListView的爸爸,GridView和ListView generateDefaultLayoutParams用的是AbsListView 爸爸的)

 protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT, 0);
    }
复制代码

ViewPager类

 protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams();
    }

 public LayoutParams() {
            super(MATCH_PARENT, MATCH_PARENT);
        }
复制代码

最屌布局 AbsoluteLayout

 protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0, 0);
    }
复制代码

GridLayout

 protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams();
    }
public LayoutParams() {
            this(Spec.UNDEFINED, Spec.UNDEFINED);
        }
复制代码

AbsSpinner(Gallery和Spinner两个儿子和爸爸都一样)

protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
    }
复制代码

RedioGroup

 @Override
    protected LinearLayout.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }
复制代码

TableLayout

  protected LinearLayout.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams();
    }
 public LayoutParams() {
            super(MATCH_PARENT, WRAP_CONTENT);
        }
复制代码

SlidingPaneLayout

protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams();
    }
 public LayoutParams() {
            super(MATCH_PARENT, MATCH_PARENT);
        }
复制代码

ConstraintLayout(以下-2 是WRAP_CONTENT的意思,貌似源码没下)

 protected ConstraintLayout.LayoutParams generateDefaultLayoutParams() {
        return new ConstraintLayout.LayoutParams(-2, -2);
    }
复制代码

DrawerLayout

protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }
复制代码

好啦,应该涵盖主流ViewGroup控件啦,至于怎么记忆,其实查查源码就好,我这里列出来就是为以后查阅图个方便。