【Interface&navigation】布局概要(2)

布局定义应用中用户界面的结构,例如在活动中。布局中的所有元素都是使用层次结构View和 ViewGroup对象构建的。一个View通常绘制的东西,用户可以看到并与之交互。而a ViewGroup是一个不可见的容器,它定义了View其他 ViewGroup对象的布局结构,如图1所示
【Interface&navigation】布局概要(2)

图1.定义UI布局的视图层次结构图

这些View对象通常称为“小部件”,可以是许多子类中的一个,例如Button或TextView。这些 ViewGroup对象通常称为“布局”,可以是提供不同布局结构的多种类型之一,例如LinearLayout或 ConstraintLayout 。
用XML声明UI元素。Android提供了一个与View类和子类相对应的简单XML词汇表,例如widget和layouts。
您还可以使用Android Studio的布局编辑器 通过拖放界面构建XML布局。

在运行时实例化布局元素。您的应用程序可以编程方式创建View和ViewGroup对象(并操作其属性)。
用XML声明你的UI允许你将你的应用程序的表示与控制其行为的代码分开。使用XML文件还可以轻松地为不同的屏幕尺寸和方向提供不同的布局(在支持不同的屏幕尺寸中进一步讨论)。

Android框架使您可以灵活地使用这两种方法中的任何一种或两种来构建应用的UI。例如,您可以用XML声明应用程序的默认布局,然后在运行时修改布局。

提示:要在运行时调试布局,请使用 布局检查器工具。

编写XML


使用Android的XML词汇表,您可以使用一系列嵌套元素快速设计UI布局及其包含的屏幕元素,就像您使用HTML创建网页一样。

每个布局文件必须包含一个根元素,该元素必须是View或ViewGroup对象。一旦定义了根元素,就可以将其他布局对象或小部件添加为子元素,以逐步构建定义布局的View层次结构。例如,以下是使用垂直方向LinearLayout 来保存a TextView和a 的XML布局Button:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>

在用XML声明布局之后,将.xml扩展名的文件保存在Android项目的res/layout/目录中,以便它能够正确编译。

有关布局XML文件语法的更多信息,请参阅布局资源文档。

加载XML资源


当你编译你的应用程序时,每个XML布局文件都被编译成一个 View资源。您应该在您的Activity.onCreate()回调实现中从应用程序代码加载布局资源 。通过调用setContentView(),通过以下形式传递对布局资源的引用: 。例如,如果您的XML布局保存为,则可以像这样为您的活动加载它:R.layout.layout_file_namemain_layout.xml

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}

onCreate()您的Activity中的回调方法在您的Activity启动时由Android框架调用(请参阅Activities 文档中有关生命周期的讨论 )。

属性


每个View和ViewGroup对象都支持各自的XML属性。一些属性是特定于View对象的(例如,TextView支持textSize 属性),但这些属性也可以由任何可以扩展此类的View对象继承。一些对于所有View对象都是通用的,因为它们是从根View类继承的(如id属性)。而且,其他属性被视为“布局参数”,这些属性描述View对象的某些布局方向,如该对象的父ViewGroup对象所定义。

ID

任何View对象都可以有一个与其关联的整数ID,以唯一地标识树中的View。编译应用程序时,此ID将作为整数引用,但ID通常在id属性中以布局XML文件中的字符串形式进行分配。这是所有View对象(由View类定义)共有的XML属性,您将经常使用它。XML标签内的ID的语法是:

android:id="@+id/my_button"

字符串开始处的at符号(@)表示XML解析器应解析并展开ID字符串的其余部分,并将其标识为ID资源。加号(+)表示这是一个新的资源名称,必须创建并添加到我们的资源(在R.java文件中)。Android框架提供了许多其他ID资源。引用Android资源ID时,您不需要加号,但必须添加android包名称空间,如下所示:

android:id="@android:id/empty"

使用android包命名空间后,我们现在引用来自android.R 资源类的ID ,而不是本地资源类。

为了创建视图并从应用中引用它们,一种常见模式是:
在布局文件中定义一个视图/小部件并为其分配唯一的ID:

<Button android:id="@+id/my_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/my_button_text"/>

然后创建视图对象的实例并从布局(通常在onCreate()方法中)捕获它:

Button myButton = (Button) findViewById(R.id.my_button);

在创建视图对象时定义视图对象的ID很重要RelativeLayout。在相对布局中,同级视图可以定义其相对于由唯一ID引用的另一个同级视图的布局。

一个ID在整个树中不必是唯一的,但它在你正在搜索的树的部分内应该是唯一的(它通常可能是整棵树,所以最好在可能的情况下是完全唯一的)。

布局参数

命名的XML布局属性为View定义布局参数,这些布局参数适用于它所在的ViewGroup。layout_something

每个ViewGroup类都实现了一个扩展的嵌套类ViewGroup.LayoutParams。此子类包含用于定义每个子视图的大小和位置的属性类型,以适合视图组。如图2所示,父视图组为每个子视图(包括子视图组)定义布局参数。
【Interface&navigation】布局概要(2)
图2.使用与每个视图关联的布局参数的视图层次结构的可视化

请注意,每个LayoutParams子类都有自己的语法来设置值。每个子元素都必须定义适合其父级的LayoutParams,尽管它也可以为其子级定义不同的LayoutParams。

所有视图组都包含宽度和高度(layout_width和 layout_height),并且每个视图都需要定义它们。许多LayoutParams还包含可选边距和边框。

你可以用精确的测量来指定宽度和高度,尽管你可能不会经常这样做。更经常地,您将使用这些常量中的一个来设置宽度或高度:

wrap_content会告诉您的视图根据其内容所需的尺寸进行调整。
match_parent 告诉你的视图变得和它的父视图组一样大。

通常,不建议使用绝对单位(如像素)指定布局宽度和高度。相反,使用诸如密度无关像素单位(dp),wrap_content或 match_parent之类的相对测量方法是一种更好的方法,因为它有助于确保您的应用能够在各种设备屏幕尺寸上正确显示。 可用资源文档中定义了接受的测量类型 。

布局位置


视图的几何图形是矩形的几何图形。视图有一个位置,表示为一对左和顶坐标,以及两个维度,表示为宽度和高度。位置和尺寸的单位是像素。

它可以通过调用方法来检索视图的位置 getLeft()和getTop()。前者返回表示视图的矩形的左边或X坐标。后者返回表示视图的矩形的顶部或Y坐标。这些方法都返回视图相对于其父项的位置。例如,当getLeft()返回20时,这意味着该视图位于其直接父级左边缘右侧20个像素处。

此外,还提供了一些便利方法来避免不必要的计算,即getRight()和getBottom()。这些方法返回代表视图的矩形右边和底边的坐标。例如,调用getRight() 类似于下面的计算:getLeft() + getWidth()。

大小,填充和边距


视图的大小用宽度和高度表示。一个视图实际上拥有两对宽度和高度值。

第一对称为测量宽度和 测量高度。这些维度定义了视图想要在其父代中有多大。测量的尺寸可以通过调用getMeasuredWidth() 和getMeasuredHeight()。

第二对简单地称为宽度和高度,或者有时绘制宽度和绘图高度。这些尺寸定义了屏幕上的视图的实际尺寸,在绘制时和布局之后。这些值可能但不一定与测量的宽度和高度不同。宽度和高度可以通过调用 getWidth()和getHeight()。

为了测量其尺寸,视图考虑了其填充。填充用视图左侧,顶部,右侧和底部的像素表示。填充可用于将视图的内容偏移特定数量的像素。例如,左边距2会将视图的内容向左边缘的右侧推动2个像素。填充可以通过设置 setPadding(int, int, int, int)方法调用和查询 getPaddingLeft(),getPaddingTop(), getPaddingRight()和getPaddingBottom()。

尽管视图可以定义填充,但它不提供对边距的支持。但是,查看组提供了这样的支持。参考 ViewGroup并 ViewGroup.MarginLayoutParams获取更多信息。

有关维度的更多信息,请参阅 维度值

常见布局


ViewGroup该类的每个子类都提供了一种显示嵌套在其中的视图的独特方式。以下是Android平台内置的一些更常见的布局类型。

注意:尽管您可以在另一个布局中嵌套一个或多个布局以实现您的UI设计,但您应该努力保持布局层次结构尽可能浅。如果嵌套布局较少,则布局绘制得更快(宽视图层次比深层视图层次更好)。

线性布局
【Interface&navigation】布局概要(2)
将其子女组织为单个水平或垂直行的布局。如果窗口的长度超过屏幕的长度,它会创建一个滚动条。

相对布局
【Interface&navigation】布局概要(2)
使您能够指定子对象相对于彼此(子B左侧的子A)或父对象(与父对象顶部对齐)的位置。

Web视图
【Interface&navigation】布局概要(2)
显示网页。

使用适配器构建布局


如果布局的内容是动态的或者不是预先确定的,那么可以使用一个布局,该子AdapterView布局在运行时用视图填充布局。AdapterView该类的一个子类使用一个Adapter将数据绑定到其布局。将Adapter表现为在数据源和所述的中间人AdapterView布局的Adapter 检索数据(从源诸如数组或数据库查询),并转换的每个条目为可被添加到一个视图AdapterView布局。

适配器支持的常见布局包括:
列表显示
【Interface&navigation】布局概要(2)
显示滚动单列列表

网格视图
【Interface&navigation】布局概要(2)
显示列和行的滚动网格。

用数据填充适配器视图

您可以填充AdapterView诸如ListView或 GridView通过将AdapterView实例绑定到Adapter从外部源检索数据并创建View代表每个数据条目的数据的实例 。

Android提供了几个子类,Adapter对于检索不同种类的数据和构建视图非常有用AdapterView。两种最常见的适配器是:

ArrayAdapter
当你的数据源是一个数组时,使用这个适配器。默认情况下,ArrayAdapter通过调用toString()每个项目并将内容置于a中来为每个数组项目创建一个视图TextView。
例如,如果您想要在a中显示一个字符串数组,请使用构造函数为每个字符串和字符串数组指定布局来ListView初始化一个新ArrayAdapter的字符串:

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
        android.R.layout.simple_list_item_1, myStringArray);

这个构造函数的参数是:

你的应用 Context
包含TextView数组中每个字符串的布局
字符串数组
然后只需打电话 setAdapter()给你的ListView:

ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);

要自定义每个项目的外观,您可以重写toString()数组中对象的方法。或者,要为每个项目创建一个视图,而不是某个项目TextView(例如,如果您想 ImageView为每个数组项目添加一个项目),请扩展ArrayAdapter该类并覆盖getView()以返回每个项目所需的视图类型。

SimpleCursorAdapter
当您的数据来自a Cursor。时,请使用此适配器。在使用时SimpleCursorAdapter,您必须指定一个布局,用于布局中的每一行Cursor以及Cursor 应将哪些列插入到布局的哪些视图中。例如,如果您想创建人员姓名和电话号码列表,则可以执行一个查询,该查询返回一个Cursor包含每个人的行和名称和数字的列的查询。然后创建一个字符串数组,指定Cursor布局中的每个结果所需的列以及指定应放置每个列的相应视图的整数数组:

String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
                        ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};

当您实例化时SimpleCursorAdapter,传递布局以用于每个结果,Cursor包含结果和这两个数组:

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
        R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);

在SimpleCursorAdapter随后创建在对于每一行的视图 Cursor通过将每个使用所提供的布局fromColumns项目成相应的toViews视图。

如果在应用程序的生命周期中更改适配器读取的基础数据,则应该调用notifyDataSetChanged()。这将通知附加的视图,数据已被更改,它应该刷新自己。

处理点击事件

AdapterView通过实现AdapterView.OnItemClickListener界面,您可以对每个项目中的点击事件做出响应。例如:

// Create a message handling object as an anonymous class.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
    public void onItemClick(AdapterView parent, View v, int position, long id) {
        // Do something in response to the click
    }
};

listView.setOnItemClickListener(mMessageClickedHandler);

猜你喜欢

转载自blog.51cto.com/4789781/2131579