pAdTy_-9 构建一个简单的用户界面和活动(Activity)

来源:互联网 发布:算法导论有什么用 编辑:程序博客网 时间:2024/06/01 09:42

2015.10.19-10.21
个人英文阅读练习笔记(低水准)。原文地址:http://developer.android.com/training/basics/firstapp/building-ui.html

2015.10.19
基于上一次的工程学习。
此标题描述的在XML布局文件中添加文本框和按钮,当按钮被按下时程序的响应是将文本框的内容发送给另外一个活动(activity)。

1. 用户接口

Android应用的图形用户接口是用层层的View和ViewGroup对象创建的。View对象是一些常用的诸如按钮或文本框的UI小窗体部件。ViewGroup是定义子视图(view)如何被布局的不可见容器对象,如栅格或垂直的表格。

Android提供XML来供定义View和ViewGroup的子类,所以用户可以在XML中分层定义UI元素。

布局是ViewGroup的子类。在本标题描述的练习中,咱们将构建一个线性布局。
这里写图片描述
图1.ViewGroup对象在布局中分支和包含View对象的形式

(1) 构建线性布局

[1]. 在AS中,打开res/layout下的activity_main.xml文件。
创建工程时所选的模板中包含了activity_main.xml文件,此文件包含了一个RelativeLayout的视图(view)根节点,以及一个TextView的子视图(view)
[2]. 在预览(Preview)窗格中点击隐藏图标关闭预览窗格。
在AS中,当打开一个布局文件时,预览窗体将会默认显示。在预览窗格中点击对应的元素将会弹出设计模式下的WYSIWYG工具。现在只操作XML的文本模式。
[3]. 删除 标签。
[4]. 将标签改为标签。
[5]. 天假Android:orientation属性并将其值设为”horizontal”。
[6]. 删除Android:padding和tools:context属性。

修改后的activity_main.xml文件内容如下:

//res/layout/activity_main.xml<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属性能让子视图以垂直或者水平方向布局。LinearLaout中的每个子元素按照在XML中的定义顺序出现。

XML文件中的另外两个属性android:layout_width和android:layout_height,它们用来指定视图的尺寸。

因为LinearLayout是整个布局的根节点,它的高度和宽度都应该设置为“match_parent”以让线性布局填充整个屏幕。match_parent值声明视图应该扩展它的高度和宽度至父视图的宽度和高度。

参见Layout手册获取更多的布局属性。

(2) 添加文本框

对每个View对象,必须定义确切的XML属性来指定EditText对象的特性。

[1]. 在activity_my.xml文件的标签中,定义一个id属性值为@+id/edit_message的标签。
[2]. 定义EditText的layout_width和layout_height属性的值为wap_content。
[3]. 定义edit_message字符串对象的hint属性。

添加的文本框XML代码如下:

//res/layout/activity_main.xml//……    <EditText android:id="@+id/edit_message"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:hint="@string/edit_message"/></LinearLayout>

以下是刚为添加的属性的含义:
android:id
为一个视图提供一个唯一的标识符,通过这个id可以在程序代码中引用这个id关联的对象,如读或操作这个对象。

若要引用XML中的资源对象,则需要@符号,其后跟随资源类型(这种情况是id),然后再是一个反斜杠,最后是资源对象的名字。

只有当定义资源ID的情况才需要在资源类型前面加加号(+)。当编译整个app后,SDK工具会利用ID名称创建一个跟EditText相关的新的资源ID到gen/R.java文件中。只要通过这种方式声明过一次资源ID,其它任何对此ID的引用都可以不再用加号(+)。只有当定义一个新的资源ID并且不需要具体的资源如字符串或布局加号(+)的使用才是必须的。参考以下对“资源对象”的文字描述获取更多关于资源对象的信息。

资源对象
一个资源对象是一个独一无二的整数名字,这个名称跟应用程序的资源相关联,比如位图、布局文件或者字符串。

每个资源在gen/R.java文件里都有一个与之关联的资源对象。可以在R类中用对象的名字来访问资源,如当指定一个字符串的android:hint属性值。你也可以随意的创建资源IDs来与用android:id属性关联的资源关联,在其它程序代码中也可以通过IDs访问到这些资源。

每编译一次应用程序,SDK工具会重新生成R.java文件,不应该手动更改这个文件。

android:layout_width和android:layout_height
wrap_content值指定整个视图尺寸跟视图内容的尺寸一样。如果用match_parent,那么EditText框将会填充整个屏幕,因为它将匹配父元素LinearLayout的尺寸。

android:hint
当文本输入框的内容为空时将会有一个默认的字符串作为文本框的内容。用“@string/edit_message”的值代替用一个硬编码的字符串作为文本框的默认内容,“@string/edit_message”的值在一个独立的文件中。因为这个引用涉及到juice的资源(不仅仅是一个标识符),所以在资源类型前不需要使用加号。当然,现在还没有定义这个资源,如果此时编译应用程序将会得到编译器的错误提示。接下来就来定义这个字符串。

注:字符串资源需要和ID后的edit_message保持一样的命名。引用资源时会检查资源类型(id 还是 string),所以用相同的命名不会引起冲突。

(3) 添加字符串

默认情况下,android工程会包含一个资源文件res/values/strings.xml。在这个文件中添加一个名为”edit_message”的字符串并将其值设置为”Enter a message”。

[1]. 在AS中,打开res/values下的strings.xml。
[2]. 在strings.xml中添加一个名为”edit_message”值为”Enter a message”的字符串。
[3]. 在strings.xml中添加一个名为”button_send”值为”send”的字符串。(这个字符串将会作为接下来所创建的按钮的文本使用)
[4]. 删除”hello lcc!”行代码。

修改后的strings.xml如下:

//res/values/stirngs.xml<resources>    <string name="app_name">Hlcc</string>    <string name="action_settings">menu</string>    <string name="edit_message">Enter a message</string>    <string name="button_send">Send</string></resources>

对于文本形式的用户界面,通常指定字符串作为一个资源。在每个位置,字符串资源都允许你操作所有的UI文本,这就是的文本的更意更新和查找。通过提供定义字符串资源的方式可以让你的程序显示各种不同的语言的文字。

(4) 添加按钮

[1]. 在AS中,打开在res/layout目录下的activity_main.xml文件。
[2]. 在元素中,紧随元素后定义元素。
[3]. 设置按钮的宽度和高度属性的值为”wrap_content”,这样按钮就能够保持和其内的文本一样的尺寸大小。
[4]. 用android:text属性定义按钮的文本,将其值(text)设置为之前定义的button_sen字符串资源。

修改后的activity_main.xml文件内容如下:

//res/layout/activity_main.xml<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"/>    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/button_send"/></LinearLayout>

注:此按钮不需要android:id属性,因为activity组件中的程序代码不会应用此按钮。

现在的activity_main.xml布局文件中包含了EditTextHE Button窗体部件的定义,它们的尺寸大小跟其内容一样大,见图2.
这里写图片描述
图2. EditText和Button窗体部件宽度的wrap_content值

这样的设置对于Button来说有效,但对文本框有可能无效,因为无法保证用户不会输入比文本框更长的内容。用文本框来填充剩余的屏幕空间是一种较好的选择。这可以在LinearLayout内用重量属性来实现,即指定android:layout_weight属性。

重量属性值是一个数字,这个数字用来指定视图及其同类的视图将要消耗的剩余屏幕空间的尺度。这种机制有点像一个混合菜谱:“2部分为苏打,1部分为糖”即表示饮料的2/3为苏打。举例来说,如果你给某个视图的重量为2而给另一个视图的重量为1,那就表示总量为3,所以第一个视图占剩余空间的2/3而另一个视图占1/3。如果你添加第3个视图并给其重量属性值为1,那么第一个视图就占剩余空间的1/2.其余的各占1/4。

视图默认的重量值为0,所以当你为某个视图指定任意一个大于0的重量值时,这个视图将会占据除去其它视图应占据的空间之外的所有空间。

(5) 让输入框填充屏幕剩余的所有宽度

按照以下步骤让EditText占据屏幕剩余的所有空间:
[1]. 在activity_main.xml文件中,为标签的layout_weight属性赋值1。
[2]. 将标签的layout_width属性赋值为0dp。

添加的内容如下:

//res/layout/activity_main.xml//……<EditText android:id="@+id/edit_message"    android:layout_weight="1"    android:layout_width="0dp"    …/>

当指定视图的重量时,为了提高布局的效率,你应该改变EditText的宽度属性为0dp。将宽度设置为0将提高布局性能,因为wrap_content值会让系统计算。

图3显示了修改代码后窗体不见的视图:
这里写图片描述
图3.EditText窗体部件的weight属性视图

(6) 运行程序

activity_main.xml被默认的Activity类加载,这个类在创建工程时由SDK工具产生。运行应用程序看运行结果:
在AS中点击运行按钮;在命令行下,将目录更改到android工程目录下用以下命令执行:
ant debug
adb install bin/Hlcc-debug.apk

2. 另一个Activity

此时的应用程序展示了一个活动(单个屏幕),包含一个文本框和按钮。现在会添加一些代码到MainActivity中,当点击Send按钮时开启一个新的活动(activity)。

(1) 按钮的响应

[1]. 在AS中,打开res/layout目录下的activity_main.xml文件。
[2]. 为元素添加android:onCLick属性。

在activity_main.xml文件中的内容如下:

//res/layout/activity_main.xml//……<Button    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="@string/button_send"    android:onClick="sendMessage"/>

android:onClick的属性值”sendMessage”是在你activity内中的一个方法,当用户点击按钮时此方法将会被调用。

[3]. 打开main/java/com.example.lxr.hw目录下的MainActivity.java文件。
[4]. 在MainActivity类中,添加sendMessage()方法,框架如下:

//main/java/com.example.lxr.hw/MainActivity.java//....../**Called when the user clicks the Send button*/public void sendMessage(View view){    //Do something inresponse to button}//......

为了匹配系统方法属性android:onClick名字预示含义,格式必须要明确。此方法必须:

  • **要为public属性。
  • 返回值要为void。
  • 要有一个唯一的View参数(表明是一个视图将会被点击)。**
    接下来,将为这个方法编写内容去读文本框的内容并将内容传给另外一个活动(activity)。

(2) 构建目的(Intent)

[1]. 在MainActivity.java文件中,在sendMessage方法内创建一个Intent去开启一个名叫DisplayMessageActivity的活动,对应代码如下:

//main/java/com.example.lxr.hw/MainActivity.java//……/**CalledwhentheuserclickstheSendbutton*/public void sendMessage(View view){    //Dosomething in response to button    Intent intent = new Intent(this,DisplayMessageActivity.class);}//……

:此时在诸如AS的IDE中引用DisplayMessageActivity将会发生错误,因为此类还没有定义。先忽略这个错误,因为接下来就会创建这个类。
Intents:一个Intent对象在运行时绑定独立的组件(如绑定两个活动)。Intent代表应用程序”打算去做某事“,用Intents能够完成很多方面的任务,它们最常被用于启动另外一个活动。

Intent的构造函数用两个参数:
一个Context上下文参数(this被用是因为Activity类是Context的子类)。
将会被系统传送(这里是启动活动)的组件类。

在AS中必须引进(import)Intent类。

[2]. 在MainActivity.java文件的顶部,引进Intent的类:

//main/java/com.example.lxr.hw/MainActivity.javaimport android.content.Intent;

提示:在AS中,Alt + Enter(Mac上的快捷键为option + return)将会引进缺失的类。

[3]. 在sendMessage方法内,用findViewById()获取EditText元素。

/main/java/com.example.lxr.hw/MainActivity.java//….../**Called when the user clicks the Send button*/public void sendMessage(Viewview){    //Do something in respon set button    Intent intent=new Intent(this,DisplayMessageActivity.class);    EditText editText=(EditText)findViewById(R.id.edit_message);}//......

[4]. 在MainActivity.java文件的顶部,引进EditText的类:
Alt + Enter

[5]. 将文本分配到本地变量message中,再用putExtra()方法将文本值加到intent中。

/**CalledwhentheuserclickstheSendbutton*/public void sendMessage(View view){    //Do something inresponse to button    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);}

Intent通过调用extras能够携带数据类型为关键字-值 类型的数据对。putExtra()方法将关键字名放在第一个参数内,将值放在第二个参数中。

[6]. 在MAinActivity类的顶部,定义EXTRA_MESSAGE

public class MainActivity extends AppCompatActivity{    Public final static String EXTRA_MESSAGE="com.example.lxr.hw.MESSAGE";    //……}

因为另外一个活动(activity)要查询附加的数据,还应该用一个公用常量为intent的附件数据定义关键字。用应用程序名作为intent附件数据的前缀通常是一个好方法。这就会确保关键字的唯一性,避免应用程序和其它应用程序交互的情况。

[7]. 在sendMessage方法中,调用startActivity()方法,将Intent对象传递给它,完成Intent。

/**CalledwhentheuserclickstheSendbutton*/public void sendMessage(View view){    //Dosomethinginresponsetobutton    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);}

系统运行这个函数后就会启动Intent指定的Activity。现在需要创建DisplayMessageActivity类。

(3) 创建第二个Activity

所有的Activity子类都必须实现onCreate()方法。这个方法是活动(activity)接收带有信息的目的(Intent)并渲染信息的方法。同时,同时,onCreate()和setContentView()方法必须定义活动的布局。这就是活动运行活动组件的初始设置的地方。

[1] 用AS工具创建Activity
当创建一个新的活动时,AS包含了onCreate()方法的固定模式。
{1}在AS中,在java目录下,选择package.com.example.lxr.hw,右键,然后选择新建 >> 活动 >>空白活动。

在选择窗体中,填写关于活动的细节。
活动名:DisplayMessageActivity
布局名称:activity_display_message
题目:My Message
父层:com.example.lxr.hw.MainActivity
包名:com.example.lxr.hw

点击完成。

{2}打开DisplayMessageActivity.java文件。
这个类已经包含了所需的onCreate()方法的实现。稍后将更新此方法的内容。其内还包含了onOptionsItemSelected()方法的实现,此方法处理bar’s Up的行为。暂时保持这两个函数的内容。

{3} 删除onCreateOptiosMemu()方法。
这个应用程序不需要这个方法。

如果你是在用AS做开发,你现在就可以运行这个程序了,但不会发生太多。当点击发送按钮时启动另外一个活动时,程序显示字符串“Hello world!”(所创建活动默认内容)。接下来会将更新新的activity的显示。

运行程序。
这里写图片描述

点击Sen按钮之前Mactivity活动对应的界面。
这里写图片描述
点击Send按钮之后DisplayMessageActivity对应的界面。

2015.10.21
[2] 不用AS工具创建activity
如果你使用的是其他IDE或者命令行工具,那么就按照下面的步骤来创建activity:
[1]. 在与MainActivity同目录下新建一个名为DisplayMessageActivity.java的文件,

[2]. 在DisplayMessageActivity.java文件中添加如下代码

public class DisplayMessageActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_display_message);        if (savedInstanceState == null) {            getSupportFragmentManager().beginTransaction()                .add(R.id.container, new PlaceholderFragment()).commit();        }    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        // Handle app bar item clicks here. The app bar        // automatically handles clicks on the Home/Up button, so long        // as you specify a parent activity in AndroidManifest.xml.        int id = item.getItemId();        if (id == R.id.action_settings) {            return true;        }        return super.onOptionsItemSelected(item);    }    /**     * A placeholder fragment containing a simple view.     */    public static class PlaceholderFragment extends Fragment {        public PlaceholderFragment() { }        @Override        public View onCreateView(LayoutInflater inflater, ViewGroup container,                  Bundle savedInstanceState) {              View rootView = inflater.inflate(R.layout.fragment_display_message,                      container, false);              return rootView;        }    }}

注:如果您使用的不是AS这样的IDE,工程里面就没有setContentView()函数锁要求的activity_display_message这样的布局文件。这是没关系的,因为您即将更新这个方法并且也不再使用这个布局文件。

[3]. 在strings.xml文件中,添加新活动的标题

<resources>    ...    <string name="title_activity_display_message">My Message</string></resources>

[4]. 在AndroidManifest.xml的Application元素下,添加新活动类

<application ... >    ...    <activity        android:name="com.example.lxr.hw.DisplayMessageActivity"        android:label="@string/title_activity_display_message"        android:parentActivityName="com.example.lxr.hw.MyActivity" >        <meta-data            android:name="android.support.PARENT_ACTIVITY"            android:value="com.example.lxr.hw.MyActivity" />    </activity></application>

android:parentActivityName属性描述了此活动的父活动。Android 4.1(API级 16)系统用这个值实现活动的默认导航。您也可以用通过使用Suppot Libray并且增加元素的方式实现在较老的版本中实现相同的导航。

注:您的Android SDK应该在安装“增加SDK包”这一步中已经包含了最新的的Android Support Library,当在AS中使用这些模板时,这些支持库会被自动的添加到应用工程中(您可以在Android Dependencies下看到所列的库文件的JAR文件)。如果您用的并不是AS,您也可以通过手动的方式将这些库添加到工程中。

如果您不是使用的AS IDE,不要担心工程还未编译。您即将更新活动去展示一个自定义的文本视图。

(4) 接收目的(Intent)

不管用户是怎么导向到活动的界面的,每个Activity都是被Intent调用(唤醒)的。您可以通过调用getIntent()获取Intent来启动您的活动并接收包含在Intent中的数据。
[1]. 打开DisplayMessageActivity.java文件
[2]. 在onCreate()方法中删除以下语句:
setContentView(R.layout.activity_display_message);

[3]. 获取目的并把它赋给当地的变量
Intentintent=getIntent();

[4]. 在文件顶部引入Intent的类(Alt + Enter)
importandroid.content.Intent;

[5]. 调用getStringExtra()方法提取MainActivity传递过来的信息
String message = intent.getStringExtra(MyActivity.EXTRA_MESSAGE);

(5) 显示信息

[1]. 在onCreate()方法中,创建一个TexView对象。

//DisplayMessageActivity.javaTextView textView = new TextView(this);//......

[2]. 通过调用setText()方法来设置TextView的属性和信息

//DisplayMessageActivity.javatextView.setTextSize(40);textView.setText(message);//......

[3].通过将TextView传递给setContentView()方法的方式将TextView设置为活动的根视图

//DisplayMessageActivity.javasetContentView(textView);//......

[4]. 在DisplayMessageActivity.java文件顶部引入TextView的类。
import android.widget.TextView;

完成(4)、(5)两个操作后,onCreate()中的代码对应如下:

@Overrideprotected void onCreate(Bundle savedInstanceState){    super.onCreate(savedInstanceState);    Intent intent=getIntent();    String message=intent.getStringExtra(MainActivity.EXTRA_MESSAGE);    TextView textView=new TextView(this);    textView.setTextSize(40);    textView.setText(message);    setContentView(textView);}

现在可以再次运行应用程序了。当在android手机上打开这个程序时,在文本框中输入一串信息,然后点击发送按钮,文本输入框中的信息将会出现在第二个活动中。

3. 活动之间跳转小结

在主活动MainActivity中设置了一个发送按钮,此按钮的onClick属性值为sendMessage,只要点击此发送按钮就会运行sendMessage函数。

在sendMessage函数中,通过另一个活动的名字来定义一个Intent,并将要传递给另外一个活动的信息准备在EXTRA_MESSAGE中(public final static)中,启动刚定义的intent即进入另外一个活动中。

在另外一个活动中,获取Intent并获取MainActivity中传递过来的信息,然后显示在自定义布局中。
以上内容的具体代码实现参看MainActivity中的senMessage()方法以及DisplayMessageActivity.java中的onCreate()方法。

在应用程序中点击返回按钮时,从当前活动返回到上一个活动中。

[2015.11.10-23:18]

0 0
原创粉丝点击