视图中的布局
布局定义了应用中的界面结构,例如
一
activity。在
是使用层次结构
View
和
ViewGroup
对象的操作。View
通常会绘制用户可见的内容,
互动ViewGroup
是一个不可见的容器,用于定义
View
和其他 ViewGroup
的布局结构
对象,如图 1 所示。
View
对象通常称为微件,可以是
许多子类,如
Button
或
TextView
。通过
ViewGroup
对象通常称为布局,可以是
提供不同布局结构的多种类型,例如
LinearLayout
或
ConstraintLayout
。
您可通过两种方式声明布局:
- 在 XML 中声明界面元素。Android 提供了一个简单的 XML
对应的
View
类和子类的词汇表, 例如 widget 和布局。您还可以使用 Android Studio 的 布局编辑器:用于构建 XML 使用拖放界面来调整布局 - 在运行时实例化布局元素。您的应用可以创建
View
和ViewGroup
对象,并操纵其 以编程方式创建
通过在 XML 中声明界面,您可以将应用呈现方式与 控制其行为的代码使用 XML 文件还可让您更轻松地: 为不同的屏幕尺寸和方向提供不同的布局。这是 本专精课程 支持不同的屏幕 尺寸。
Android 框架可让您灵活地使用 来构建应用界面例如,您可以声明应用的 默认布局,然后在运行时修改布局。
<ph type="x-smartling-placeholder">编写 XML
利用 Android 的 XML 词汇,您可以快速设计界面布局和 它们包含的屏幕元素,方法与使用 HTML 创建网页相同 一系列嵌套元素组成。
每个布局文件都必须只包含一个根元素,该元素必须是
View
或 ViewGroup
对象。定义根
元素,您可以将其他布局对象或微件作为子元素添加到
逐步构建一个用于定义布局的 View
层次结构。对于
例如,这是一个使用垂直 LinearLayout
来
同时持有一个 TextView
和一个 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 中声明布局后,使用
Android 项目的 res/layout/
中的 .xml
扩展程序
以便其正确编译。
如需详细了解布局 XML 文件的语法,请参阅 布局资源。
加载 XML 资源
当您编译应用时,系统会将每个 XML 布局文件编译成 View
资源。在应用的
Activity.onCreate()
回调实现。为此,请调用
setContentView()
,
以如下形式向其传递对布局资源的引用:
R.layout.layout_file_name
。例如,如果您的 XML
保存为 main_layout.xml
,
Activity
:
Kotlin
fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.main_layout) }
Java
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); }
Android 框架调用 onCreate()
回调方法,
在 Activity
启动时,您的 Activity
会同步。有关
有关 activity 生命周期的信息,请参阅
activity。
属性
每个 View
和 ViewGroup
对象都支持自己的
各种 XML 属性某些属性特定于 View
对象。例如,TextView
支持 textSize
属性。不过,任何 View
也会继承这些属性。
用于扩展此类的对象。有些属性是所有View
所共有的
对象,因为它们继承自 View
根类,例如
id
属性。其他属性则被视为版式
参数,这些是用于描述特定布局方向的属性
View
对象的父级元素,由该对象的父级定义
ViewGroup
对象。
ID
任何 View
对象都可以拥有与其关联的整数 ID,
在树中唯一标识 View
。当应用
编译后,此 ID 以整数形式引用,但通常分配有
作为 id
属性中的字符串包含在布局 XML 文件中。这是一个
所有 View
对象通用的 XML 属性,由
View
类。它的使用非常频繁。内部 ID 的语法
XML 标记如下所示:
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,如
示例:
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
- 创建 View 对象的实例并从布局中捕获该实例,
通常位于
onCreate()
方法,如以下示例所示:Kotlin
val myButton: Button = findViewById(R.id.my_button)
Java
Button myButton = (Button) findViewById(R.id.my_button);
在创建
RelativeLayout
。
在相对布局中,同级视图可以定义其相对于另一个视图的布局
同级视图,由唯一 ID 引用。
ID 不必在整个结构树中保持唯一,但必须是唯一的 在您搜索的树状结构部分是唯一的。有时 因此,最好尽可能使其具有唯一性。
布局参数
定义名为 layout_something
的 XML 布局属性
View
的适合
ViewGroup
。
每个 ViewGroup
类都会实现一个嵌套类,该类扩展
ViewGroup.LayoutParams
。
此子类包含的属性类型会定义每个子类的大小和位置。
子视图。如图 2 所示,父级
视图组为每个子视图定义布局参数,包括
视图群组。
每个 LayoutParams
子类都有自己的设置语法
值。每个子元素都必须定义一个 LayoutParams
,该
它的父项,不过它也可能会定义一个不同的
LayoutParams
。
所有视图组均使用 layout_width
包含宽度和高度
和 layout_height
,并且需要每个视图来定义它们。很多
LayoutParams
包含可选的外边距和边框。
您可以指定具有确切尺寸的宽度和高度,但可能不会 经常执行这项操作更常见的情况是,您需要使用其中一个常量来设置 宽度或高度:
wrap_content
:指示您的视图根据 内容所需的尺寸match_parent
:告知视图变得与其父级一样大 视图组允许。
一般情况下,我们不建议使用
绝对单位,例如像素。更好的方法是使用相对测量值,
例如密度无关像素单位 (dp)、wrap_content
或
match_parent
,因为它有助于您的应用在
各种设备屏幕尺寸可接受的衡量类型请参见
布局资源。
布局位置
视图具有矩形几何图形。它包含一个位置,表示为 左和上坐标以及两个维度,以 宽度和高度。位置和尺寸的单位是像素。
您可以通过调用
getLeft()
和
getTop()
。
前者会返回矩形的左侧 (x) 坐标,代表
视图。后者会返回矩形的上 (y) 坐标
代表视图的视图。这些方法会返回视图相对于
其父级。例如,当 getLeft()
返回 20 时,则表示
视图位于
。
此外,您还可以使用一些便捷方法来避免不必要的计算:
也就是
getRight()
和
getBottom()
。
这些方法会返回
代表视图的矩形例如,调用 getRight()
是
类似于以下计算:getLeft() + getWidth()
。
尺寸、内边距和外边距
视图的大小由宽度和高度表示。一个视图有两对 宽度值和高度值的组合
第一对称为“测量宽度”,
测量高度。这些尺寸决定了视图所需的尺寸
父对象中的资源。您可以通过调用
getMeasuredWidth()
和
getMeasuredHeight()
。
第二对称为宽度和高度,有时
绘图宽度和绘图高度。这些维度决定了
绘制时和布局后,视图在屏幕上的实际尺寸。这些
值可能(但不必)与测量宽度和测量高度不同。您
可以通过调用
getWidth()
和
getHeight()
。
为了测量尺寸,视图需将其内边距考虑在内。内边距
以像素表示视图左侧、顶部、右侧和底部各部分的像素。
您可以使用内边距将视图内容偏移特定的
像素。例如,左侧内边距为 2,会将视图的内容推送两个像素
放在左边缘右侧您可以使用
setPadding(int, int, int, int)
方法调用该方法,并通过调用
getPaddingLeft()
,
getPaddingTop()
,
getPaddingRight()
,
和
getPaddingBottom()
。
尽管视图可以定义内边距,但它不支持外边距。不过,
视图组确实支持外边距请参阅
ViewGroup
和
ViewGroup.MarginLayoutParams
。
有关维度的详细信息,请参阅 维度。
除了以编程方式设置外边距和内边距之外,您还可以 ,如以下示例所示:
<?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:layout_margin="16dp" android:padding="8dp" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:paddingBottom="4dp" android:paddingEnd="8dp" android:paddingStart="8dp" android:paddingTop="4dp" android:text="Hello, I am a Button" /> </LinearLayout>
上面的示例展示了应用的外边距和内边距。通过
TextView
四周都应用了统一的外边距和内边距,以及
Button
展示了如何将这些选项单独应用于不同的
边缘。
常见布局
ViewGroup
类的每个子类都提供了一种独特的方法来
显示您嵌套在其中的视图。这是最灵活的布局类型,
是让布局层次结构保持浅层的最佳工具,
ConstraintLayout
。
以下是 Android 中内置的一些常用布局类型 平台。
<ph type="x-smartling-placeholder">构建动态列表
如果布局的内容是动态内容或未预先确定的内容,您可以
使用
RecyclerView
或
是
AdapterView
。
RecyclerView
通常是更好的选择,因为它会使用内存
比 AdapterView
效率更高。
RecyclerView
和
AdapterView
包含以下内容:
RecyclerView
提供了更多可能性
您可以
创建自定义
布局管理器。
使用数据填充适配器视图
您可以填充
AdapterView
例如 ListView
或
GridView
由
将 AdapterView
实例绑定到
Adapter
,
该函数会从外部来源检索数据,并创建 View
,
来代表每个数据条目
Android 提供了一些实用的 Adapter
子类,
用于检索不同类型的数据并构建
AdapterView
。两种最常见的适配器是:
ArrayAdapter
- 请在数据源为数组时使用此适配器。默认情况下
ArrayAdapter
通过调用以下方法来为每个数组项创建一个视图:toString()
并将内容放入TextView
中。例如,如果您想在
ListView
,请使用ArrayAdapter
构造函数来指定每个字符串和字符串数组的布局:Kotlin
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)
Java
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray);
此构造函数的实参如下:
- 您的应用
Context
- 包含
TextView
的布局,对应于 数组 - 字符串数组
然后调用
setAdapter()
在您的ListView
上:Kotlin
val listView: ListView = findViewById(R.id.listview) listView.adapter = adapter
Java
ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter);
要自定义每个项的外观,您可以覆盖
toString()
方法。或者,创建 为每个项目分配一个视图TextView
- 例如,如果您需要ImageView
扩展ArrayAdapter
类和 覆盖getView()
返回您想要为每个项使用的视图类型。 - 您的应用
SimpleCursorAdapter
- 如果您的数据来自
Cursor
。 使用SimpleCursorAdapter
时,请指定要使用的布局Cursor
中的每一行以及Cursor
。 例如,如果您想创建用户姓名和电话号码列表 您可以执行一个返回Cursor
的查询 包含每个人的行,以及姓名和号码的列。您 然后创建一个字符串数组,指定 每个结果的布局中所需的Cursor
值和一个整数 数组,用于指定每列需要的相应视图 地点:Kotlin
val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER) val toViews = intArrayOf(R.id.display_name, R.id.phone_number)
Java
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}; int[] toViews = {R.id.display_name, R.id.phone_number};
当您实例化
SimpleCursorAdapter
时,将 使用的Cursor
布局,其中包含 和以下两个数组:Kotlin
val adapter = SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0) val listView = getListView() listView.adapter = adapter
Java
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
界面。例如:
Kotlin
listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> // Do something in response to the click. }
Java
// Create a message handling object as an anonymous class. private OnItemClickListener messageClickedHandler = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { // Do something in response to the click. } }; listView.setOnItemClickListener(messageClickedHandler);
其他资源
请参阅 向日葵 演示版应用。