android LayoutInflater、setContentView、findviewbyid 区分解析

原创 2016年05月31日 15:41:15

一、LayoutInflater.inflate(layoutId, root, boolen)中三个参数的意义及作用

(这点可以参考鸿洋前辈博客地址:http://blog.csdn.net/lmj623565791/article/details/38171465


主要知识点其实很少,如下:

若temp为layoutId所代表的布局,inflate的三种方法区分如下:

View view=LayoutInflater.Inflate(layoutId, null )只创建temp ,temp.LayoutParams=null,返回temp
View view=LayoutInflater.Inflate(layoutId, root, false )创建temp,temp.LayoutParams=root.LayoutParams;返回temp
View view=LayoutInflater.Inflate(layoutId, root, true ) 创建temp,然后执行root.addView(temp, params);最后返回root


关于点三条可能难以理解,此处笔者自己写了一个例子:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/main_layout"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Main Text View"/>

</LinearLayout>
button_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

MainActivity.java

package com.example.double2.layoutinflatertest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    private LinearLayout mainLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mainLayout = (LinearLayout) findViewById(R.id.main_layout);
        LayoutInflater layoutInflater = LayoutInflater.from(this);

        View buttonLayout = layoutInflater.inflate(R.layout.button_layout, null);
        mainLayout.addView(buttonLayout);

//        View buttonLayout = layoutInflater.inflate(R.layout.button_layout, mainLayout,true);
    }
}


当执行如下两句时,布局如下:

        View buttonLayout = layoutInflater.inflate(R.layout.button_layout, null);
        mainLayout.addView(buttonLayout);


当执行如下一句时,布局如下:

        View buttonLayout = layoutInflater.inflate(R.layout.button_layout, mainLayout,true);



二、又上图可知,两种方式都是可以给activity_main中加入button布局了,但是让人奇怪的是,为什么两者是同一个button,显示的却会有差别呢?第二个问题就自然出来了。


解决办法:我们给button_layout中的button加上一个RelativeLayout,如下:

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

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"/>
</RelativeLayout>
然后我们可以发现,两种方式都只会有一种效果了,如下:



可以发现,这往往就是我们最想要的效果,就是这个button本来多大,就给它。这样我们修改这个button的时候才比较方便。

那么是什么导致在第一个问题中,button无法显示原来的大小的呢?

        View buttonLayout = layoutInflater.inflate(R.layout.button_layout, null);
        mainLayout.addView(buttonLayout);

当我们执行如上代码时,root为null,我们获得的buttonLayout的LayoutParams为null。当我们在viewgroup中使用addView(View child)方法,添加一个没有LayoutParams属性的子view。在viewgroup方法内部,它会调用generateDefaultLayoutParams()生成一个LayoutParams赋值个给子view。


LayoutParams有什么用呢?

简单来说,当一个view的LayoutParams存在时,该布局的宽高设置才会有效。而一个view需要存在LayoutParams,就必须存在父布局。

关于LayoutParams,可以参考这篇博客:http://blog.csdn.net/double2hao/article/details/51438798

        View buttonLayout = layoutInflater.inflate(R.layout.button_layout, mainLayout,true);
而当我们执行这行代码的时候,我们最终返回的是root,而root即为activity_main中的LinearLayout。也就和button本身并没有什么关系了。



三、那么activity_main中的LinearLayout也为空,为什么我们经常使用setContentView(R.id.XXX)的时候却不会造成LayoutParams的缺失而导致布局无法准确显示的问题呢?


如此,我们就需要去了解setContentView()和layoutInflater.inflate()的区别了。

setContentView()设置布局的时候,Android会自动在布局文件的最外层再嵌套一个FrameLayout,所以设置的布局是存在LayoutParams的,也因此可以正常显示。


关于问题二和三,如果还有兴趣的读者,可以参考一下郭霖前辈的博客:

http://blog.csdn.net/guolin_blog/article/details/12921889


四,findviewbyid()和LayoutInflater.Inflate()有什么区别呢?

findViewById():从setContentView()已经设置的layout中获取到某个控件。

Inflate():把某个layout从xml文件中实例化成一个对象。

版权声明:本文为博主许佳佳原创文章,转载请务必注明出处。

setContentView、findViewById 和 inflate 的区别?

通俗的说,inflate就相当于将一个xml中定义的布局找出来. 因为在一个Activity里如果直接用findViewById()的话,对应的是setConentView()的那个layout里的...
  • dylgsy
  • dylgsy
  • 2014年03月27日 20:25
  • 4009

Android应用setContentView与LayoutInflater加载解析机制源码分析

【工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果】1 背景其实之所以要说这个话题有几个原因: 理解xml等控件是咋被显示的原理,通常大家写代码都...
  • yanbober
  • yanbober
  • 2015年05月26日 23:16
  • 40183

Android setContentView、LayoutInflater、findViewById

setContentView(R.layout.main)在Android里面,这句话是什么意思? R.layout.main是个布局文件即控件都是如何摆放如何显示的,setContentView就...
  • lan120576664
  • lan120576664
  • 2014年06月25日 10:01
  • 654

Android UI 详解之LayoutInflater和setContentView

Android UI 详解之LayoutInflater 1、LayoutInflater           LayoutInflater作用是将layout的xml布局文件实例化为View类对象...
  • UStory
  • UStory
  • 2015年01月06日 12:02
  • 950

使用LayoutInflater装载布局或者setContentView装载布局的时候出现OOM(内存溢出)的解决办法

起因:今天写一个视频图片信息展示页面的时候,在recyclerView中添加条目中,使用View view = LayoutInflater.from(parent.getContext()).inf...
  • qq_21265915
  • qq_21265915
  • 2016年12月10日 23:01
  • 884

setContentView() 究竟都做了什么?

转载请注明出处:http://blog.csdn.net/crazy1235/article/details/51471280这个函数是在常见不过的了!setContentView(R.layout....
  • crazy1235
  • crazy1235
  • 2017年05月15日 21:31
  • 1258

"The method findViewById(int) is undefined for ..."

转自http://www.anddev.org/-und-quotthe_method_findviewbyidint_is_undefined_for_-und-quot-t11806.html ...
  • BeBeMo
  • BeBeMo
  • 2015年06月11日 17:17
  • 877

getLayoutInflater() 以及findViewById(R.id.outerlayout)区别

mainLayout = (LinearLayout) getLayoutInflater().inflate(                 R.layout.calendar_main, nu...
  • u010509143
  • u010509143
  • 2014年02月27日 13:28
  • 1537

关于android之LayoutInflater的inflate()方法和findViewById()方法

在开发中经常用到这两个方法,如何选择这两个方法,如果是activity并且已经用到了setContentView()方法来显示布局文件,那么可以直接用findViewById()方法来找到该布局上面的...
  • u012400222
  • u012400222
  • 2015年04月13日 16:31
  • 332

显示百度地图要注意的:试用setContentView前初始化BMapManager对象,否则会报错

在MyMapActivity中定义成员变量: 源码复制打印关于 BMapManager mBMapMan = null;   MapView mMapView = nul...
  • chenaini119
  • chenaini119
  • 2014年03月07日 15:07
  • 1233
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android LayoutInflater、setContentView、findviewbyid 区分解析
举报原因:
原因补充:

(最多只允许输入30个字)