接下来探讨一下安卓基本的布局文件,作为萌新的我表示还可以接受,不算难,但愿很快能把这篇文章写完吧~
这篇文章还是通过搬运官方文档并穿插一些自己遇到的问题和看法来写,因为官方文档和老版本的安卓系统有些不符合,所以我在一些地方加了注释,不影响官方文档本身的阅读。(PS:可以这样区分,中文注释我写的,英文注释官方文档写的)。
主要内容有:布局和控件的基本使用,页面间信息传递
第二课 第一个安卓应用
先回忆一波,就目前学习而言,布局暂时只是用来展现APP的每个界面用的,这次的文章利用基本的布局和控件完成了第一个安卓应用
Android应用的图形界面使用 View 对象和 ViewGroup 对象层次结构而构建。View 对象通常为按钮或文本字段之类的UI
小部件。而 ViewGroup 对象则为不可见的视图容器,它们定义子视图的布局,比如是网格布局还是垂直列表布局。
Android 提供对应于 View 和 ViewGroup 子类的XML
词汇,以便您使用 UI 元素层次结构以 XML 格式定义 UI。
布局是 ViewGroup 的子类。
创建线性布局
1. 在 Android Studio 的 Project 窗口中,打开 app > res >layout > activity_main.xml。
此 XML 文件定义 Activity 的布局。它包含默认的“Hello World”文本视图。
2. 在布局编辑器中,当您打开一个布局文件时,首先显示的是设计编辑器。 在本课中,您将直接使用 XML,因此请点击窗口底部的 Text 标签以切换到文本编辑器。
3. 删除所有内容并插入以下 XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
</LinearLayout>
LinearLayout 是一个视图组(ViewGroup 的子类),它会按照 android:orientation 属性的指定,将子视图设置为垂直或水平方向布局。LinearLayout的每个子视图都会按照它们各自在 XML 中的出现顺序显示在屏幕上。
其他两个属性 android:layout_width 和 android:layout_height 则是所有视图的必备属性,用于指定它们的尺寸。
LinearLayout 是布局中的根视图,因此应将宽度和高度设置为 "match_parent",从而填满可供应用使用的整个屏幕区域。 该值表示视图应扩大其宽度或高度,以匹配父视图的宽度或高度。
添加文本字段
建议以下内容手动输入,练习一下对控件的使用,EditText就是一个控件叫作可编辑文本框
在 activity_main.xml 文件的 <LinearLayout> 元素内,添加以下 <EditText> 元素:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText
android:id="@+id/edit_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/edit_message"/>
</LinearLayout>
无需担心出现 @string/edit_message 错误;通过底下的教程您很快就会修复该错误。
下面说明了您添加的 <EditText> 中的属性:
这会为视图赋予唯一的标识符,您可以使用该标识符从应用代码中引用对象,例如读取和操作对象(下一课中将有介绍)。
从 XML 引用任何资源对象时,都需要使用 @ 符号。 请在该符号后依次输入资源类型(本例中为 id)、斜杠和资源名称 (edit_message)。
资源对象
资源对象是一个唯一的整型名称,它与应用资源(如位图、布局文件或字符串)相关联。
每个资源在您项目的 R.java 文件中都定义有相应的资源对象。您可以使用 R类中的对象名称来引用您的资源,例如当您需要为 android:hint 属性指定字符串值时,就可以这样做。您也可以使用 android:id 属性创建任意与视图相关联的资源 ID,从而可以从其他代码中引用该视图。
SDK 工具会在您每次编译应用时生成 R.java 文件。切勿手动修改该文件。
如需了解详细信息,请阅读提供资源指南。
只有在第一次定义资源 ID 时,才需要在资源类型之前加一个加号 (+)。 当您编译应用时,SDK 工具会使用 ID 名称在项目的 R.java 文件中新建一个引用 EditText 元素的资源 ID。一旦以此方式声明资源 ID,其他对该 ID 的引用皆无需使用加号。 只有在指定新资源 ID 时才必须使用加号,对于字符串或布局等具体资源则不必如此。
android:layout_width 和 android:layout_height
"wrap_content" 值并不规定宽度和高度的具体大小,而是指定根据需要缩放视图,使其适合视图的内容。 如果您要改用 "match_parent",则 EditText 元素将填满屏幕,因为它会匹配父 LinearLayout 的大小。如需了解详细信息,请参阅布局指南。
这是文本字段为空时显示的默认字符串。"@string/edit_message" 并非使用硬编码字符串作为其值,而是引用另一个文件中定义的一个字符串资源。 由于它引用的是一个具体资源(而不仅仅是标识符),因此不需要加号。 不过,由于您尚未定义字符串资源,所以最初会出现编译错误。 在下一节中,您可以通过定义字符串来修正该错误。
注:此字符串资源与元素 ID edit_message 同名。不过,对资源的引用始终都按资源类型(如 id 或 string)确定其作用域,因此使用相同的名称不会引起冲突。
添加字符串资源
默认情况下,您的 Android 项目在 res > values >strings.xml 位置包含一个字符串资源文件。您需要在此处添加两个新字符串。
1. 从 Project 窗口中,打开 res > values >strings.xml。
2. 添加两个字符串,使您的文件如下所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My First App</string>
<string
name="edit_message">Enter a message</string>
<string name="button_send">Send</string>
</resources>
对于用户界面中的文本,务必将每个字符串都指定为资源。 字符串资源允许您在单一位置管理所有 UI 文本,从而简化文本的查找和更新。 此外,将字符串外部化还可让您为每个字符串资源提供替代定义,从而将您的应用本地化为不同的语言。
添加按钮
返回到 activity_main.xml 文件并在 <EditText> 后添加一个按钮。您的文件应如下所示:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/edit_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/edit_message"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send"/>
</LinearLayout>
注:此按钮不需要 android:id 属性,因为不需要从 Activity 代码中引用它。
如图 2 所示,该布局当前设计为根据内容大小调整 EditText 和 Button 小部件的尺寸。
图 2. EditText 小组件和 Button 小部件的宽度均设置为 "wrap_content"。
这对按钮很适合,但不太适合文本字段,因为用户键入的内容可能更长。 最好让文本字段填满未使用的屏幕宽度。 您可以在 LinearLayout 内通过 weight 属性来实现此目的,该属性可使用 android:layout_weight 属性来指定。
Weight 值是一个数字,用于指定每个视图与其他同级视图在剩余空间中的占比。 这有点像饮料配方中各种成分的比例: “2 份苏打、1 份糖浆”是指饮料中三分之二是苏打。例如,如果您将一个视图的 weight 值指定为 2,将另一个视图的 weight 值指定为 1,总和是 3,那么第一个视图将填满剩余空间的 2/3,而第二个视图则填满其余部分。 如果您添加了第三个视图,将其 weight 值指定为 1,那么现在第一个视图(weight 值为 2)将获得 1/2 的剩余空间,其余两个视图则各占 1/4。
所有视图的默认 weight 值都为 0,所以如果您仅将一个视图的 weight 值指定为大于 0,那么等到其他所有视图都获得所需空间后,该视图便会填满所有剩余空间。
使输入框填满屏幕宽度
在 activity_main.xml 中,修改 <EditText> ,使这些属性如下所示:
<EditText
android:id="@+id/edit_message"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/edit_message"/>
将宽度设置为零 (0dp)可提高布局性能,这是因为如果将宽度设置为 "wrap_content",则会要求系统计算宽度,而该计算最终毫无意义,因为 weight值还需要计算另一个宽度,才能填满剩余空间。
图 3. EditText 小部件获得了布局的所有 weight,因此它填满了 LinearLayout 中的剩余空间。
完整的 activity_main.xml 布局文件现在看上去应该像下面这样:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText android:id="@+id/edit_message"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/edit_message"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send"/>
</LinearLayout>
目前来说,用到了最外层的一个布局叫作LinearLayout,里面用了EditText 和 Button 2个控件,安卓中还有许多奇形怪状的控件,下次找个文章再写吧,反正玩控件玩了我几个小时了还没全部玩完,大家自行斟酌。
那么接下来继续,刚才摆了一个Button按钮在那里我总归得用一下吧,接下来是官方文档介绍点击按钮跳转到另外一个Activity(每个活动对应有一个界面)。
响应 Send 按钮
1. 在文件 res > layout >activity_main.xml 中,将 android:onClick 属性添加到 <Button> 元素,如下所示:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send"
android:onClick="sendMessage"/>
每次用户点击按钮时,此属性均会提示系统调用 Activity 中的 sendMessage() 方法。
2. 在文件 java >com.example.myfirstapp > MainActivity.java 中,添加 sendMessage() 方法存根,如下所示:
public
class MainActivity
extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//加载布局文件
}
/*复制底下这一段就行了,上面的原来写过了,如果你要复制别忘记了AppCompat的问题,安卓4.4跑不起,底下还有内容,所以我建议还是手打别复制*/
/** Called when the user clicks the Send button */
public void sendMessage(View view){
// Do something in response to button
}
}
要让系统将此方法与为 android:onClick 指定的方法名称匹配,签名必须与所示内容完全相同。具体而言,该方法必须:
o 是公共方法
o 具有空返回值
o 以 View 作为唯一参数(这将是之前点击的 View)
接下来,您需要填写此方法以读取文本字段的内容,并将该文本传递给另一个 Activity。
构建一个 Intent
Intent 是指在相互独立的组件(如两个 Activity)之间提供运行时绑定功能的对象。Intent 表示一个应用“执行某项操作的 Intent”。 您可以将 Intent 用于各种任务,但在本课程中,Intent 用于启动另一个 Activity。
在 MainActivity.java 中,将如下所示代码添加到 sendMessage():
public
class MainActivity
extends AppCompatActivity
{
public
final static
String EXTRA_MESSAGE =
"com.example.myfirstapp.MESSAGE";
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/** Called when the user clicks the Send button */
public void sendMessage(View view){
//Intent是意图的意思,这里用于跳转
Intent intent
= new Intent(this,DisplayMessageActivity.class);
EditText editText
= (EditText) findViewById(R.id.edit_message);
String message
= editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
}
Android Studio 将显示无法解析符号错误,这是因为此代码引用了未导入的类。 通过按 Alt + Enter(在 Mac 上,则按 Option + Return),您可使用 Android Studio 的“导入类”功能来解决其中一些问题。您的导入应按如下所示结束:
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;//删除了appcompat就没有这个
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
仍出现 DisplayMessageActivity 错误,但没关系,您将在下一部分中修复该错误。
sendMessage() 中会执行许多操作,因此我们来解释下具体会执行哪些操作。
Intent 构造函数采用两个参数:
· Context 是第一个参数(之所以使用 this ,是因为 Activity 类是 Context 的子类)
· 应用组件的 Class,系统应将 Intent(在本例中,为应启动的 Activity)传递至该类。
注:引用 DisplayMessageActivity 会在 Android Studio 中引发错误,因为该类尚不存在。可以暂时忽略该错误,因为您很快要创建该类。
putExtra() 方法将 EditText 的值添加到 Intent。Intent 能够以名为 extra 的键值对形式携带数据类型。您的键是一个公共常量 EXTRA_MESSAGE,因为下一个 Activity 将使用该键来检索文本值。为 Intent extra 定义键时最好使用应用的软件包名称作为前缀。这可以确保在您的应用与其他应用交互过程中这些键始终保持唯一。
startActivity() 方法将启动 Intent 指定的 DisplayMessageActivity 实例。现在,您需要创建类。
创建第二个 Activity
1. 在 Project 窗口中,右键点击 app 文件夹并选择 New > Activity> Empty Activity。
2. 在 Configure Activity 窗口中,为 Activity Name 输入 “DisplayMessageActivity”,然后点击 Finish
Android Studio 自动执行三项操作:
· 使用必需的 onCreate() 方法的实现创建类 DisplayMessageActivity.java。
· 创建对应的布局文件 activity_display_message.xml
· 在 AndroidManifest.xml 中添加必需的 <activity> 元素。
如果运行应用并在第一个 Activity 上点击“Send”按钮,则将启动第二个 Activity,但它为空。这是因为第二个 Activity 使用模板提供的默认空布局。
显示消息
现在,您将修改第二个 Activity,以显示第一个 Activity 传递的消息。如果因为AppcompatActivity导致程序崩溃的萌新图方便的话别直接删除appcompat,因为Appcompat要求appcompat的style,我已经忘记好几次了,崩溃半天找不到原因
1. 在 DisplayMessageActivity.java 中,向 onCreate() 方法添加下列代码:
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_message);
Intent intent = getIntent();
String message
= intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
TextView textView
= new TextView(this);
textView.setTextSize(40);
textView.setText(message);
ViewGroup layout
= (ViewGroup) findViewById(R.id.activity_display_message);
layout.addView(textView);
}
2. 按 Alt + Enter(在 Mac 上,则按 Option + Return)导入缺少的类。 您的导入应按如下所示方式结束:
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.TextView;
此处会执行大量操作,因此我们接着解释:
1. 调用 getIntent() 采集启动 Activity 的 intent。无论用户如何导航到目的地,每个 Activity 都由一个 Intent 调用。 调用 getStringExtra() 将检索第一个 Activity 中的数据。
2. 您可以编程方式创建 TextView 并设置其大小和消息。
3. 您可将 TextView 添加到 R.id.activity_display_message 标识的布局。您可将布局投射到 ViewGroup,因为它是所有布局的超类且包含 addView()方法。
注:早期版本的 Android Studio 生成的 XML 布局可能不包括 android:id 属性。如果布局没有 android:id 属性,则调用 findViewById() 将失败。如果出现这种情况,请打开 activity_display_message.xml 并将属性 android:id="@+id/activity_display_message" 添加到布局元素。
您现在便可运行该应用。当应用打开后,请在文本字段键入消息,然后点击 Send。第二个 Activity 将替换屏幕中的第一个 Activity,并显示您在第一个 Activity 中输入的消息。
就这么简单,您的第一个 Android 应用已成功诞生,并完成了页面间数据传递的操作!
每日一吟:宝剑锋从磨砺出,梅花香自苦寒来。