当前位置:

首页 > 系统应用 > 10.8 LayoutInflater(布局服务)

10.8 LayoutInflater(布局服务)

本节引言: 本节接着来看 Android 系统服务里的 LayoutInflater(布局服务)。一提到“布局”,很多人脑子里第一反应通常都是:先写好一个布局 xml,再通过 Activity 的 setContentView() 把它加载进来,最后显示到屏幕上。这个理解没错,不过再往底层看一层,会

本文目录

    本节引言:

     本节接着来看 Android 系统服务里的 LayoutInflater(布局服务)。一提到“布局”,很多人脑子里第一反应通常都是:先写好一个布局 xml,再通过 Activity 的 setContentView() 把它加载进来,最后显示到屏幕上。这个理解没错,不过再往底层看一层,会发现背后真正干活的,其实还是 LayoutInflater,它依赖的是 Android 内置的 Pull 解析器来完成布局解析。平时在 Android 开发里,只要涉及动态加载布局,或者运行时添加控件,LayoutInflater 都会频繁出现。接下来,就顺着实际开发场景,把它的常见用法捋一遍。

    官方API文档:LayoutInflater

    1.LayoutInflater的相关介绍

    1)Layout是什么鬼?

    答:一个用于加载布局的系统服务,就是实例化与Layout XML文件对应的View对象,不能直接使用, 需要通过getLayoutInflater( )方法或getSystemService( )方法来获得与当前Context绑定的 LayoutInflater实例!

    2)LayoutInflater的用法

    ①获取LayoutInflater实例的三种方法:

    LayoutInflater inflater1 = LayoutInflater.from(this);  
    LayoutInflater inflater2 = getLayoutInflater();  
    LayoutInflater inflater3 = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); 

    PS:后面两个其实底层走的都是第一种方法~

    ②加载布局的方法:

    public View inflate (int resource, ViewGroup root, boolean attachToRoot) 该方法的三个参数依次为:

    ①要加载的布局对应的资源id

    ②为该布局的外部再嵌套一层父布局,如果不需要的话,写null就可以了!

    ③这个参数说白了,就是在判断:加载出来的布局文件,最外层要不要再包一层root布局。要是不手动设置这个参数,那么当root不为null时,默认就是true;但如果root本身就是null,那attachToRoot其实也就不起作用了。进一步看,root不为null且attachToRoot为true时,加载的布局文件最外层会再嵌套一层root布局;如果是false,那root基本就等于没参与。简单理解就是:是否为加载的布局添加一个root的外层容器~!

    ③通过LayoutInflater.LayoutParams来设置相关的属性:

    比如RelativeLayout还可以通过addRule方法添加规则,就是设置位置:是参考父容器呢? 还是参考子控件?又或者设置margin等等,这个由你决定~

    2.纯Ja va代码加载布局

    我们早已习惯了使用XML生成我们需要的布局,但是在一些特定的情况下,我们 需要使用Ja va代码往我们的布局中动态的添加组件或者布局!

    但是不建议大家完全地使用Ja va代码来编写Android页面布局,首先一点就是代码会多, 一多久容易乱,而且不利于业务的分离,我们还是建议使用xml来完成布局,然后通过 Ja va代码对里面的组件进行修改,当然有些时候可能需要使用Ja va动态的来添加组件!

    纯Ja va代码加载布局的流程:

    ——Step 1:

    ①创建容器:LinearLayout ly = new LinearLayout(this);

    ②创建组件:Button btnOne = new Button(this);

    ——Step 2:

    可以为容器或者组件设置相关属性: 比如:LinearLayout,我们可以设置组件的排列方向:ly.setOrientation(LinearLayout.VERTICAL); 而组件也可以:比如Button:btnOne.setText("按钮1"); 关于设置属性的方法可参见Android 的API,通常xml设置的属性只需在前面添加:set即可,比如 setPadding(左,上,右,下);

    ——Step 3:

    将组件或容器添加到容器中,这个时候我们可能需要设置下组件的添加位置,或者设置他的大小: 我们需要用到一个类:LayoutParams,我们可以把它看成布局容器的一个信息包!封装位置与大小 等信息的一个类!先演示下设置大小的方法:(前面的LinearLayout可以根据不同容器进行更改)

    LinearLayout.LayoutParams lp1 = new LinearLayout.LayoutParams(  
            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 

    很简单,接着就到这个设置位置了,设置位置的话,通常我们考虑的只是RelativeLayout! 这个时候用到LayoutParams的addRule( )方法!可以添加多个addRule( )哦! 设置组件在父容器中的位置,

    比如设置组件的对其方式:

    RelativeLayout rly = new RelativeLayout(this);  
    RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(  
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
    lp2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);  
    Button btnOne = new Button(this);  
    rly.addView(btnOne, lp2);

    参照其他组件的对其方式: (有个缺点,就是要为参考组件手动设置一个id,是手动!!!!) 比如:设置btnOne居中后,让BtnTwo位于btnOne的下方以及父容器的右边!

    public class MainActivity extends Activity {  
        @Override  
        protected void onCreate(Bundle sa vedInstanceState) {  
            super.onCreate(sa vedInstanceState);  
            RelativeLayout rly = new RelativeLayout(this);  
            Button btnOne = new Button(this);  
            btnOne.setText("按钮1");  
            Button btnTwo = new Button(this);  
            btnTwo.setText("按钮2");  
            // 为按钮1设置一个id值  
            btnOne.setId(123);  
            // 设置按钮1的位置,在父容器中居中  
            RelativeLayout.LayoutParams rlp1 = new RelativeLayout.LayoutParams(  
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
            rlp1.addRule(RelativeLayout.CENTER_IN_PARENT);  
            // 设置按钮2的位置,在按钮1的下方,并且对齐父容器右面  
            RelativeLayout.LayoutParams rlp2 = new RelativeLayout.LayoutParams(  
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
            rlp2.addRule(RelativeLayout.BELOW, 123);  
            rlp2.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);  
            // 将组件添加到外部容器中  
            rly.addView(btnTwo, rlp2);  
            rly.addView(btnOne, rlp1);  
            // 设置当前视图加载的View即rly  
            setContentView(rly);  
        }  
    }  

    ——step 4:

    调用setContentView( )方法加载布局对象即可! 另外,如果你想移除某个容器中的View,可以调用容器.removeView(要移除的组件);

    运行截图:

    3.Ja va代码动态添加控件或xml布局

    第二点我们讲解了使用纯Ja va代码来加载布局,实际当中用得并不多,更多的时候是动态 的添加View控件以及动态的加载XML布局!

    1)Ja va代码动态增加View

    动态添加组件的写法有两种,区别在于是否需要先setContentView(R.layout.activity_main); 下面演示下两种不同写法添加一个Button的例子:

    先写个布局文件先:activity_main.xml:

      
      
      

    第一种不需要setContentView()加载布局文件先:

    public class MainActivity extends Activity {  
        @Override  
        protected void onCreate(Bundle sa vedInstanceState) {  
            super.onCreate(sa vedInstanceState);  
            Button btnOne = new Button(this);  
            btnOne.setText("我是动态添加的按钮");  
            RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(    
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);    
            lp2.addRule(RelativeLayout.CENTER_IN_PARENT);    
            LayoutInflater inflater = LayoutInflater.from(this);  
            RelativeLayout rly = (RelativeLayout) inflater.inflate(  
                    R.layout.activity_main, null)  
                    .findViewById(R.id.RelativeLayout1);  
            rly.addView(btnOne,lp2);  
            setContentView(rly);  
        }  
    } 

    第二种不需要setContentView()加载布局文件先:

    public class MainActivity extends Activity {  
        @Override  
        protected void onCreate(Bundle sa vedInstanceState) {  
            super.onCreate(sa vedInstanceState);  
            setContentView(R.layout.activity_main);  
            Button btnOne = new Button(this);  
            btnOne.setText("我是动态添加的按钮");  
            RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(    
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);    
            lp2.addRule(RelativeLayout.CENTER_IN_PARENT);    
            RelativeLayout rly = (RelativeLayout) findViewById(R.id.RelativeLayout1);  
            rly.addView(btnOne,lp2);  
        }  
    } 

    分析总结:

    代码很简单,创建按钮后,我们又创建了一个LayoutParams对象,用来设置Button的大小, 又通过addRule()方法设置了Button的位置!

    第一种方法:通过LayoutInflate的inflate()方法加载了activity_main布局,获得了外层容器, 接着addView添加按钮进容器,最后setContentView();

    第二种方法:因为我们已经通过setContetView()方法加载了布局,此时我们就可以通过 findViewById找到这个外层容器,接着addView,最后setContentView()即可!

    另外,关于这个setContentView( )他设置的视图节点是整个XML的根节点!

    2)Ja va代码动态加载xml布局

    接下来的话,我们换一个,这次加载的是xml文件!动态地添加xml文件! 先写下主布局文件和动态加载的布局文件:

    activity_main.xml:

    
        

    inflate.xml:

      
      
      
    

    接着到我们的MainActivity.ja va在这里动态加载xml布局:

    public class MainActivity extends Activity {  
        @Override  
        protected void onCreate(Bundle sa vedInstanceState) {  
            super.onCreate(sa vedInstanceState);  
            setContentView(R.layout.activity_main);  
            //获得LayoutInflater对象;  
            final LayoutInflater inflater = LayoutInflater.from(this);    
            //获得外部容器对象  
            final RelativeLayout rly = (RelativeLayout) findViewById(R.id.RelativeLayout1);  
            Button btnLoad = (Button) findViewById(R.id.btnLoad);  
            btnLoad.setOnClickListener(new OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    //加载要添加的布局对象  
                    LinearLayout ly = (LinearLayout) inflater.inflate(  
                            R.layout.inflate, null, false).findViewById(  
                            R.id.ly_inflate);  
                    //设置加载布局的大小与位置  
                    RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(    
                            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);    
                    lp.addRule(RelativeLayout.CENTER_IN_PARENT);    
                    rly.addView(ly,lp);  
                }  
            });  
        }  
    } 

    运行截图:

    代码分析:

    ①获取容器对象:

    final RelativeLayout rly = (RelativeLayout) findViewById(R.id.RelativeLayout1);

    ②获得Inflater对象,同时加载被添加的布局的xml,通过findViewById找到最外层的根节点

    final LayoutInflater inflater = LayoutInflater.from(this);
    LinearLayout ly = (LinearLayout) inflater.inflate(R.layout.inflate, null, false)
       .findViewById(R.id.ly_inflate);

    ③为这个容器设置大小与位置信息:

    RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(  
                   LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
           lp.addRule(RelativeLayout.CENTER_IN_PARENT); 

    ④添加到外层容器中:

    rly.addView(ly,lp);

    4.LayoutInflater的inflate()方法源码

    最后提供下LayoutInflater的inflate()方法的源码吧,有兴趣的可以看看~,其实就是Pull解析而已~

    public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {    
        synchronized (mConstructorArgs) {    
            final AttributeSet attrs = Xml.asAttributeSet(parser);    
            mConstructorArgs[0] = mContext;    
            View result = root;    
            try {    
                int type;    
                while ((type = parser.next()) != XmlPullParser.START_TAG &&    
                        type != XmlPullParser.END_DOCUMENT) {    
                }    
                if (type != XmlPullParser.START_TAG) {    
                    throw new InflateException(parser.getPositionDescription()    
                            + ": No start tag found!");    
                }    
                final String name = parser.getName();    
                if (TAG_MERGE.equals(name)) {    
                    if (root == null || !attachToRoot) {    
                        throw new InflateException("merge can be used only with a valid "    
                                + "ViewGroup root and attachToRoot=true");    
                    }    
                    rInflate(parser, root, attrs);    
                } else {    
                    View temp = createViewFromTag(name, attrs);    
                    ViewGroup.LayoutParams params = null;    
                    if (root != null) {    
                        params = root.generateLayoutParams(attrs);    
                        if (!attachToRoot) {    
                            temp.setLayoutParams(params);    
                        }    
                    }    
                    rInflate(parser, temp, attrs);    
                    if (root != null && attachToRoot) {    
                        root.addView(temp, params);    
                    }    
                    if (root == null || !attachToRoot) {    
                        result = temp;    
                    }    
                }    
            } catch (XmlPullParserException e) {    
                InflateException ex = new InflateException(e.getMessage());    
                ex.initCause(e);    
                throw ex;    
            } catch (IOException e) {    
                InflateException ex = new InflateException(    
                        parser.getPositionDescription()    
                        + ": " + e.getMessage());    
                ex.initCause(e);    
                throw ex;    
            }    
            return result;    
        }    
    } 

    本节小结:

    本节给大家讲解了一下Android中的LayoutInflater(布局服务),以及动态加载View和控件 相关的东西,相信对初学控件的朋友带来帮助~好的,就说这么多,谢谢~

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    系统应用 浏览器
    相关文章 更多
    漫蛙manwa2在线阅读入口
    漫蛙manwa2在线阅读入口

    漫蛙manwa2官方在线入口与功能全解析 不少读者都在寻找一个稳定、免费的漫画在线阅读平台。今天就为大家详细拆解一下“漫蛙manwa2”。其官方在线入口与核心功能究竟如何?以下内容或许能给你答案。 直接说入口:漫蛙manwa2的官方网页版可以直接通过 https://www.manwamh.top 访问。这个入口

    漫蛙manwa2官方稳定链接
    漫蛙manwa2官方稳定链接

    漫蛙漫画:一个属于漫画爱好者的纯净阅读宇宙 聊起在线看漫画,总绕不过几个关键词:资源全、更新快、画质好、没广告。如果一个平台能把这些都做到位,那它想不吸引人都难。今天要说的漫蛙漫画(manwa2),正是这样一个集合了所有“理想型”特质的平台。它不玩虚的,就靠庞大的资源库、与官方同步的更新速度以及极度

    免费漫蛙manwa官网入口
    免费漫蛙manwa官网入口

    漫蛙(Manwa):一个漫画爱好者的宝藏阅读平台 说起在线阅读漫画,漫蛙(Manwa)这个名字,在爱好者圈子里可谓是颇有分量。它能在众多同类平台里迅速占据一席之地,靠的可不是运气。海量的资源库和以用户为中心的设计,让它成功吸引了从新手到资深漫迷的广泛群体。无论是当下最火的日韩新番,还是那些承载着回忆

    漫蛙漫画最新网址链接进入
    漫蛙漫画最新网址链接进入

    漫蛙漫画官网全解析:资源、体验与稳定性深度评测 “漫蛙漫画最新网址是什么?”“官方的在线观看入口在哪里?”——最近,这类问题在漫画爱好者圈子里可谓不绝于耳。别急,2025年最新、最稳的官方访问途径,这就为你一一道来。 官网入口直通车:https://www.manwamh.top 平台资源覆盖广度

    百度浏览器无法打开本地HTML文件怎么办
    百度浏览器无法打开本地HTML文件怎么办

    百度浏览器无法打开本地HTML文件时,可设为默认程序、通过菜单栏手动打开或拖拽加载。若路径含中文需移至纯英文路径。视频播放需添加type属性,或使用命令行参数,或通过Python启动HTTP服务器绕过限制。

    360浏览器怎么截图网页长图
    360浏览器怎么截图网页长图

    使用360浏览器截取网页长图有四种方法 想把整个网页,包括那些需要滚动才能看到的部分,完整地保存为一张长图?这事儿在360浏览器里其实并不复杂。核心就一句话:你得借助浏览器自带或者能兼容的截图功能。下面这几种方法,总有一款能解决你的问题。 一、使用360浏览器内置“网页长截图”功能 最直接高效的路径

    谷歌浏览器网页快捷方式怎么创建?Chrome发送到桌面【指南】_果粉控
    谷歌浏览器网页快捷方式怎么创建?Chrome发送到桌面【指南】_果粉控

    通过Chrome内置功能创建网页快捷方式 想要把常用网站变成桌面一键直达的入口?Chrome浏览器内置的快捷方式创建功能就能轻松实现。无论是生成独立应用窗口,还是传统桌面图标,下面这四种方法总有一款适合你。 一、通过地址栏创建桌面快捷方式 这个方法最实用——它能生成一个独立的桌面图标,双击后直接以应

    麒麟OS如何安装火狐浏览器_银河麒麟Firefox安装教程
    麒麟OS如何安装火狐浏览器_银河麒麟Firefox安装教程

    银河麒麟系统安装新版火狐浏览器:五种方法全解析 在银河麒麟操作系统里,如果软件商店里找不到新版的火狐浏览器,这事儿其实挺常见。原因不外乎几个:你的系统架构可能比较特殊,比如龙芯的MIPS、飞腾的ARM64,或者海光、Intel的x86,官方源未必能完全覆盖;又或者,系统预装的还是那个年代久远的Fir

    怎样彻底注销并清除绑定在百度浏览器上的账号信息?
    怎样彻底注销并清除绑定在百度浏览器上的账号信息?

    想彻底注销百度浏览器上的账号,光点个退出登录可远远不够。你得完成两个核心动作:账号主体注销和本地服务痕迹清除,缺一不可。光退出登录或清个浏览数据,账号和设备的绑定关系还在,下次打开照样自动同步历史记录和收藏夹。 具体操作是这样的:先在“我的→设置→账号管理”里找到“账号注销”,验证手机号或人脸后确认

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。