Java 有人可以解释膨胀方法吗?更深入地理解Android视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19862456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 20:48:02  来源:igfitidea点击:

Can someone explain inflate method? Deeper understanding of Android views

javaandroidxmlviewandroid-inflate

提问by rootpanthera

I want deeper understanding of how Android works, and I need someone to explain how Views are actually working "under the hood".

我想更深入地了解 Android 的工作原理,我需要有人解释视图在“幕后”实际上是如何工作的。

In normal procedure we would inflate (is this the correct word?) views from XML in onCreate method of our extended Activity with method "setContentView(R.layout.ourlayoutfile)". Then we would find Views from that XML.

在正常过程中,我们会在扩展活动的 onCreate 方法中使用方法“setContentView(R.layout.ourlayoutfile)”从 XML 中膨胀(这是正确的词吗?)视图。然后我们会从那个 XML 中找到视图。

Quick example: If we need to find a button we need first call "setContentVIew()" and then, "findViewById" on our button. Then we can work with this button / view respectively.

快速示例:如果我们需要找到一个按钮,我们需要先调用“setContentVIew()”,然后在我们的按钮上调用“findViewById”。然后我们可以分别使用这个按钮/视图。

I've started to play with LayoutInflater recently, because I came to the point which I couldn't help myself with "setContentView" method, and on my surprise I found out that my Android knowledge sucks very good. I couldn't even manage LayoutInflater to work. I was embarassed.

我最近开始玩 LayoutInflater,因为我到了无法使用“setContentView”方法的地步,令我惊讶的是,我发现我的 Android 知识非常糟糕。我什至无法管理 LayoutInflater 来工作。我很尴尬。

After a day I manage to inflate views with LayoutInflater. Actually it's not very hard, I was very close already from the start BUT there was one parameter which I didn't know what to pass in. Please look at this code: ( This is all happening in onCreate method of Activity )

一天后,我设法使用 LayoutInflater 来扩充视图。其实这不是很难,我从一开始就已经很接近了,但是有一个参数我不知道要传入什么。请看这段代码:(这都发生在 Activity 的 onCreate 方法中)

View v = getLayoutInflater().inflate(R.layout.activity_main, (ViewGroup) getWindow().getDecorView());



    final Button b = (Button) v.findViewById(R.id.button1);
    final TextView tv = (TextView) v.findViewById(R.id.textView1);

    b.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {


            tv.setText("Just random text");
        }
    });

}

This code works fine, but the problem I was facing was actually this line of code:

这段代码工作正常,但我面临的问题实际上是这行代码:

getLayoutInflater().inflate(R.layout.activity_main, null);

I was always passing "null" parameter, and of course it didn't worked. Even tho in documentation it says that this parameter is OPTIONAL! ( Why ? , if it's needed) ?

我总是传递“null”参数,当然它没有用。即使在文档中它也说这个参数是可选的!(为什么?,如果需要的话)?

I've made simple layout. Please look at it and how it looks with HiearchyViewer:

我做了简单的布局。请使用 HiearchyViewer 查看它以及它的外观:

enter image description here

在此处输入图片说明

What is the second parameter in picture above, and why do we need it in there? Is maybe connecting my layout ( R.layout.activity_main ), with View provided by Android ( First view from left to right - parent view ). If that's the case, WHY doesn't android connect these two automatically?!

上图中的第二个参数是什么,为什么我们需要它?可能将我的布局( R.layout.activity_main )与 Android 提供的视图连接起来(从左到右的第一个视图 - 父视图)。如果是这样,为什么 android 不自动连接这两个?!

enter image description here

在此处输入图片说明

If there is also something useful I need to know regarding Views I will be very glad if someone could tell me ( or post a link ). Additionally would be nice if I could get some links to some websites of How Views work.. etc. Useful stuff.

如果还有一些有用的东西我需要知道关于视图,如果有人能告诉我(或发布链接),我会很高兴。另外,如果我能得到一些链接到一些网站的“视图如何工作”等有用的东西,那就太好了。

If someone will downvote my question, please explain. Thank you very much everyone!

如果有人会否决我的问题,请解释一下。非常感谢大家!

采纳答案by d3m0li5h3r

As you might already know by now that every visible component in Android is a View. That includes Button, Spinner, TextView, EditTextand the likes. You are also right about the way we access the Views that are defined in a xml file in our program, by inflating it and then finding the view by using it's id. The usual way to do this is by using setContentView()method.

正如您现在可能已经知道的那样,Android 中的每个可见组件都是一个View. 这包括ButtonSpinnerTextViewEditText和喜欢。您对我们访问在我们程序的 xml 文件中定义的视图的方式也是正确的,通过膨胀它然后使用它的 id 查找视图。通常的方法是使用setContentView()方法。

But there is this pretty useful class called LayoutInflaterthat can be used to "inflate" a layout. Now consider the scenario where you have a ListViewin your xml file that you inflated using setContentView()method. In this ListView you want the items to contain an ImageViewand a TextView. The default list-item just have a TextView. So you decided to write up a custom adapter in which you'll be using a new listitems.xml in which you have a TextViewand ImageViewdefined. Now you can't use setContentView()in this case as it will inflate this layout on the whole activity which obviously you don't want. So you use LayoutInflaterin this case to help you out. You temporarily inflate a layout using inflate()method. The first argument takes the layout file which is needed to be inflated. The second argument is the root of this newly inflated layout. In our case it can be set to the ListViewin which the layout is going to be actually inflated.

但是有一个非常有用的类被称为LayoutInflater可用于“膨胀”布局。现在考虑ListView您的 xml 文件中有一个使用setContentView()方法膨胀的场景。在此 ListView 中,您希望项目包含ImageViewTextView。默认列表项只有一个TextView. 因此,您决定编写一个自定义适配器,您将在其中使用一个新的 listitems.xml,您在其中定义了TextViewImageView。现在你不能setContentView()在这种情况下使用它,因为它会在整个活动中夸大这个布局,这显然是你不想要的。所以你LayoutInflater在这种情况下使用来帮助你。您暂时使用inflate()方法。第一个参数采用需要膨胀的布局文件。第二个参数是这个新膨胀的布局的根。在我们的例子中,它可以设置为ListView布局实际膨胀的位置。

So when you use this inflate()method, a Viewis returned containing the views that are inside the inflated xml. Now with this returned view instance you can call findViewById()to get the contained views to set text to the TextViewand image source to the ImageView.

因此,当您使用此inflate()方法时,将View返回包含膨胀的 xml 中的视图的a 。现在有了这个返回的视图实例,您可以调用findViewById()以获取包含的视图以将文本设置为TextView并将图像源设置为ImageView

More often than not, you'll end up using LayoutInflateras it's use cases are wider than the scope of this discussion.

通常LayoutInflater情况下,您最终会使用它,因为它的用例比本讨论的范围更广。

回答by CommonsWare

Please look at this code

请看这段代码

That is a rather unusual use of LayoutInflater. In particular, I would expect it to seriously mess up your use of action bars and related "chrome" outside the main content area.

这是一个相当不寻常的用法LayoutInflater。特别是,我希望它会严重扰乱您对主要内容区域之外的操作栏和相关“chrome”的使用。

I was always passing "null" parameter, and of course it didn't worked

我总是传递“null”参数,当然它没有用

nullis a perfectly reasonable value for the second parameter of the two-parameter inflate()method. Doing so implies that you will add the inflated Viewhierarchy to your UI yourself at some point (e.g., via a call to addView()on the desired parent).

null是双参数inflate()方法的第二个参数的完全合理的值。这样做意味着您将View在某个时候自己将膨胀的层次结构添加到您的 UI 中(例如,通过addView()对所需父级的调用)。

Even tho in documentation it says that this parameter is OPTIONAL!

即使在文档中它也说这个参数是可选的!

That is because the parameter is optional.

那是因为参数是可选的。

( Why ? , if it's needed) ?

(为什么?,如果需要的话)?

It is not needed.

不需要。

What is the second parameter in picture above

上图中的第二个参数是什么

It is the PhoneWindow$DecorView.

它是PhoneWindow$DecorView.

and why do we need it in there?

为什么我们需要它在那里?

You do not need it in there, and your choice of the getDecorView()is atypical, to say the least.

你不需要它在那里,你的选择getDecorView()是非典型的,至少可以说。

Is maybe connecting my layout ( R.layout.activity_main ), with View provided by Android ( First view from left to right - parent view ).

可能将我的布局( R.layout.activity_main )与 Android 提供的视图连接起来(从左到右的第一个视图 - 父视图)。

Yes. Quoting the documentation, the second parameter to the two-parameter inflate()is the "Optional view to be the parent of the generated hierarchy".

是的。引用文档,双参数的第二个参数inflate()是“可选视图是生成的层次结构的父级”。

If that's the case, WHY doesn't android connect these two automatically?!

如果是这样,为什么 android 不自动连接这两个?!

Why would it? After all, there are five total views beyond the three that you inflated, as you can tell by counting the bubbles in your Hierarchy View screenshot. Why would it randomly choose that one, rather than one of the others? Furthermore, for all Android knows, the parent you want to use does not even exist yet, because you will be creating it in a later step.

为什么会呢?毕竟,除了您膨胀的三个视图之外,还有五个总视图,您可以通过计算层次视图屏幕截图中的气泡来判断。为什么它会随机选择一个,而不是其他的一个?此外,所有 Android 都知道,您要使用的父级甚至还不存在,因为您将在稍后的步骤中创建它。

So, either pass in your desired parent as the second parameter to inflate()(in which case, Android will add the inflated layout as children to that parent), or pass in null(in which case, adding the child to the parent is your job to do yourself at some suitable point).

因此,要么将您想要的父项作为第二个参数传递给inflate()(在这种情况下,Android 会将膨胀的布局作为子项添加到该父项),要么传入null(在这种情况下,将子项添加到父项是您要做的工作)自己在某个合适的点)。

Note that having Android notautomatically add the child to the parent is the norm for the two primary uses of LayoutInflater:

请注意,Android不会自动将子项添加到父项是以下两种主要用途的规范LayoutInflater

  • for children of an AdapterView(e.g., rows in a ListView)
  • for the contents of fragments (i.e., inflated in onCreateView())
  • 对于 a 的孩子AdapterView(例如, a 中的行ListView
  • 对于片段的内容(即在 中膨胀onCreateView()