本节引言:

本节继续带来的是Android系统服务中的LayoutInflater(布局服务),说到布局,大家第一时间 可能想起的是写完一个布局的xml,然后调用Activity的setContentView()加载布局,然后把他显示 到屏幕上是吧~其实这个底层走的还是这个LayoutInflater,用的Android内置的Pull解析器来解析 布局。一般在Android动态加载布局或者添加控件用得较多,本节我们就来学习下他在实际开发中 的一些用法~

1.LayoutInflater的相关介绍

1)Layout是什么鬼?

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

2)LayoutInflater的用法

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

LayoutInflaterinflater1 =LayoutInflater.from(this);LayoutInflaterinflater2 =getLayoutInflater();LayoutInflaterinflater3 =(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.纯Java代码加载布局

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

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

纯Java代码加载布局的流程:

——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.LayoutParamslp1 =newLinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

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

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

RelativeLayoutrly =newRelativeLayout(this);RelativeLayout.LayoutParamslp2 =newRelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);lp2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);ButtonbtnOne =newButton(this);rly.addView(btnOne,lp2);

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

publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);RelativeLayoutrly =newRelativeLayout(this);ButtonbtnOne =newButton(this);btnOne.setText("按钮1");ButtonbtnTwo =newButton(this);btnTwo.setText("按钮2");// 为按钮1设置一个id值 btnOne.setId(123);// 设置按钮1的位置,在父容器中居中 RelativeLayout.LayoutParamsrlp1 =newRelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);rlp1.addRule(RelativeLayout.CENTER_IN_PARENT);// 设置按钮2的位置,在按钮1的下方,并且对齐父容器右面 RelativeLayout.LayoutParamsrlp2 =newRelativeLayout.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.Java代码动态添加控件或xml布局

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

1)Java代码动态增加View

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

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

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

publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);ButtonbtnOne =newButton(this);btnOne.setText("我是动态添加的按钮");RelativeLayout.LayoutParamslp2 =newRelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);lp2.addRule(RelativeLayout.CENTER_IN_PARENT);LayoutInflaterinflater =LayoutInflater.from(this);RelativeLayoutrly =(RelativeLayout)inflater.inflate(R.layout.activity_main,null).findViewById(R.id.RelativeLayout1);rly.addView(btnOne,lp2);setContentView(rly);}}

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

publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButtonbtnOne =newButton(this);btnOne.setText("我是动态添加的按钮");RelativeLayout.LayoutParamslp2 =newRelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);lp2.addRule(RelativeLayout.CENTER_IN_PARENT);RelativeLayoutrly =(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)Java代码动态加载xml布局

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

activity_main.xml:

inflate.xml:

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

publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//获得LayoutInflater对象; finalLayoutInflaterinflater =LayoutInflater.from(this);//获得外部容器对象 finalRelativeLayoutrly =(RelativeLayout)findViewById(R.id.RelativeLayout1);ButtonbtnLoad =(Button)findViewById(R.id.btnLoad);btnLoad.setOnClickListener(newOnClickListener(){@OverridepublicvoidonClick(Viewv){//加载要添加的布局对象 LinearLayoutly =(LinearLayout)inflater.inflate(R.layout.inflate,null,false).findViewById(R.id.ly_inflate);//设置加载布局的大小与位置 RelativeLayout.LayoutParamslp =newRelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);lp.addRule(RelativeLayout.CENTER_IN_PARENT);rly.addView(ly,lp);}});}}

运行截图:

代码分析:

①获取容器对象:

finalRelativeLayoutrly =(RelativeLayout)findViewById(R.id.RelativeLayout1);

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

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

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

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

④添加到外层容器中:

rly.addView(ly,lp);

4.LayoutInflater的inflate()方法源码

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

publicViewinflate(XmlPullParserparser,ViewGrouproot,booleanattachToRoot){synchronized(mConstructorArgs){finalAttributeSetattrs =Xml.asAttributeSet(parser);mConstructorArgs[0]=mContext;Viewresult =root;try{inttype;while((type =parser.next())!=XmlPullParser.START_TAG &&type !=XmlPullParser.END_DOCUMENT){}if(type !=XmlPullParser.START_TAG){thrownewInflateException(parser.getPositionDescription()+": No start tag found!");}finalStringname =parser.getName();if(TAG_MERGE.equals(name)){if(root ==null||!attachToRoot){thrownewInflateException("merge can be used only with a valid "+"ViewGroup root and attachToRoot=true");}rInflate(parser,root,attrs);}else{Viewtemp =createViewFromTag(name,attrs);ViewGroup.LayoutParamsparams=null;if(root !=null){params=root.generateLayoutParams(attrs);if(!attachToRoot){temp.setLayoutParams(params);

java layoutinflater_LayoutInflater(布局服务)相关推荐

  1. 面试1:Java、微服务、架构常见面试题(持续更新中)

    Java.微服务.架构常见面试题(持续更新中) 文章目录 Java.微服务.架构常见面试题(持续更新中) ==**Java**== 1.Java概述 (1)JVM.JRE和JDK (2)Java特点 ...

  2. JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)

    摘要:本节主要来讲解Android10.0 JAVA层HIDL服务的获取原理 阅读本文大约需要花费19分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的 ...

  3. JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)

    摘要:本节主要来讲解Android10.0 JAVA层HIDL服务的注册原理 阅读本文大约需要花费22分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的 ...

  4. Java:socket服务端,socket服务端支持多连接,socket客户端,socket客户端支持发送和接受

    一.Java之socket服务端 新建一个Java工程 命名 给他先创建一个类 在类里面我们做一个main 这里面也需要,创建套接字,IP号,端口号 但是java中有一个类         Serve ...

  5. java 通信层_Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务

    有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...

  6. Java基于socket服务实现UDP协议的方法

    转载自 Java基于socket服务实现UDP协议的方法 这篇文章主要介绍了Java基于socket服务实现UDP协议的方法,通过两个简单实例分析了java通过socket实现UDP发送与接收的技巧, ...

  7. (2.1)HarmonyOS鸿蒙Ability创建,XML和Java页面布局UI

    鸿蒙UI中,提供了两种编写布局的方式: ①在XML中声明UI布局 ②在Ability代码中直接通过Java创建布局 这两种方式创建出的布局没有本质差别,但是XML方式较为方便简单. 在XML文件中布局 ...

  8. java~springcloud微服务目录索引

    回到占占推荐博客索引 最近写了不过关于java,spring,微服务的相关文章,今天把它整理一下,方便大家学习与参考. java~springcloud微服务~目录索引 springcloud~服务注 ...

  9. java solr_通过Java访问Solr服务实例及相关配置

    一.通过Java访问Solr服务(手动创建索引库) 1.创建项目,配置环境(导包及相关文件) 1.SolrJ核心包 /solr-4.10.3/dist/solr-solrj-4.10.3.jar 2. ...

最新文章

  1. 大数据中用到的新的数据类型bigint、decimal、smallint、tinyint
  2. gan只用来生成是浪费
  3. Unity3D中使用KiiCloud总结一
  4. c语言写贪吃蛇什么水平_学了一些C语言,也不知道自己学到什么程度,自己想写个贪吃蛇但是写不出来,想看懂下面这个程序,求解释...
  5. 27.4. /etc/bandwidthd.conf
  6. UE4学习-AI导航网格的创建及修改
  7. Android view变形,android仿变形金刚效果实现MatchView
  8. MySQL表名后接t_mysql表名忽略大小写
  9. Thinkpad SL400安装黑苹果10.8.4全纪录
  10. vue 修改文件怎么启动_Jupyter Notebook如何修改启动时的默认文件路径(Windows系统)...
  11. 关于是否存在免费的SAP服务器用作练习的提问
  12. 使用insightface进行人脸识别批量下载图片
  13. 论语读后感--论语与管理
  14. 编写一段李志坤喜欢杨静,杨静不喜欢李志坤的世纪虐恋
  15. [思语]_我心中的大师
  16. 大数据----数据仓库设计基础(实列演示)
  17. 计算机打印机提示无法打印,为什么电脑连的打印机没法打印状态一直错误
  18. javascript怎么隐藏显示div
  19. 汇编中参数的传递和堆栈修正
  20. 125.在CM中使用SNMP

热门文章

  1. 用Python爬取42年数据,告诉你高考有多难!
  2. 做项目经理到底有多爽?
  3. python中yield的认识与学习|生成器
  4. Traceback (most recent call last): File AttributeError: 'NoneType' object has no attribute 'group'
  5. Python翻转字典,以及解决IndentationError: expected an indented block报错!
  6. AI技术在图像水印处理中的应用
  7. 打造属于自己的underscore系列(五)- 偏函数和函数柯里化
  8. Flutter——设置appBar的高度
  9. 和我一起打造个简单搜索之SpringDataElasticSearch入门
  10. 整理一下自己手撸的博客