13

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

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

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

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

一天后,我设法用 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");
        }
    });

}

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

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

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

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

在此处输入图像描述

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

在此处输入图像描述

如果我还需要了解有关 Views 的有用信息,如果有人能告诉我(或发布链接),我将非常高兴。另外,如果我能获得一些关于 Views 工作原理的网站的链接,那就太好了。等等。有用的东西。

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

4

2 回答 2

14

您现在可能已经知道,Android 中的每个可见组件都是View. 这包括Button, Spinner, TextView,EditText等等。您对我们访问在我们程序中的 xml 文件中定义的视图的方式也是正确的,方法是膨胀它,然后使用它的 id 找到视图。通常的方法是使用setContentView()方法。

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

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

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

于 2013-11-08T15:36:00.733 回答
10

请看这段代码

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

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

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

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

那是因为参数是可选的。

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

它不是必需的。

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

它是PhoneWindow$DecorView.

为什么我们需要它?

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

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

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

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

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

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

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

  • 对于 an 的孩子AdapterView(例如, a 中的行ListView
  • 对于片段的内容(即,inflated in onCreateView()
于 2013-11-08T15:49:11.787 回答