前面已经介绍了Android UI组件的基本知识,那么再来了解如何使用Android SDK中定义的UI组件进行界面编程。
前面介绍的View组件是Java的类,Android除了提供使用定义Java对象的形式来定义View组件,还可以使用XML布局文件的方式来定义View组件,并且Android也推荐使用XML布局文件。但是无论是使用Java对象,还是使用XML布局文件,控制Android UI组件的行为本质上是一致的,大部分时候UI组件标签的XML属性,在Java类中还存在对应的getter、setter方法。,在工作中,Android推荐使用XML布局文件。
View的常用XML属性及方法说明:
XML属性 | 相关方法 | 说明 |
android:alpha | setAlpha(float) | 设置该组件的透明度 |
android:background | setBackgroundResource(int) | 设置该组件的背景 |
android:clickable | setClickable(boolean) | 设置该组件是否可以响应点击事件 |
android:longClickable | setLongClickable(boolean) | 设置该组件是否可以响应长按事件 |
android:onClick | 为该组件的单击事件绑定监听器 | |
android:focusable | setFocusable(boolean) | 设置该书剑是否可以得到焦点 |
android:id | setId(int) | 设置该组件的唯一标识 |
android:keepScreenOn | setKeepScreenOn(boolean) | 设置该组件是否强制屏幕常亮 |
android:layout_gravity | - | 设置该组件在容器内的权重 |
android:layout_height |
setLayoutParames
(View.Group.LayoutParams) |
设置该组件在其父容器中的高度 |
android:layout_width |
setLayoutParames
(View.Group.LayoutParams) |
设置该组件在其父容器中的宽度 |
android:layout_margin | - | 设置该组件在其父容器中布局时的边距 |
android:minHeight | - | 设置该组件的最小高度 |
android:minWidth | - | 设置该组件的最小宽度 |
android:padding | setPadding | 在组件的四边设置填充区域 |
android:saveEnabled | setSaveEnabled(boolean) | 设置是否在冻结的时候保持组件的状态 |
android:visibility | setVisibility(int) | 设置该组件是否可见 |
表3-1常用XML属性以及方法,可能说明里描述的不是很清晰,在后面介绍详细UI组件的时候,对应的属性也将详细介绍到,这里不再赘述。
定义UI组件后,必须使用Android四大组件之一的Activity对其进行承载,对于Activity的内容,将再后面的章节中讲解到。
Android推荐使用XML资源文件定义UI组件,这样暗合了MVC的原则。MVC全名是Model View Controller,是模型(model)-视图(View)-控制器(Controller)的缩写,它是一种软件设计模式,使用MVC的目的是将模型与视图的实现代码分离,从而使同一个程序可以使用不同的表现形式。Android推荐使用XML布局来定义UI组件的意义,不仅UI组件的结构清晰,简单明了,也把视图和逻辑进行了分离。
XML布局文件必须定义在res/layout目录下,并且文件名只能小写字母构成。当定义好一个XML布局文件之后,R.java会自动收录该布局资源,在Java代码中可以通过Activity.setContentView()方法,指定Activity显示的内容视图。setContentView()方法具有多个重载方法,这里给出使用XML布局文件的方法的完整签名:
public void setContentView(int layoutResID)
当XML布局文件中定义了多个UI组件的时候,可以使用UI组件的android:id属性为其制定资源ID,资源ID是这个XML布局文件中UI组件的唯一标识,当为UI组件定义了ID之后,R.java中会自动收录其ID。这样就可以在Activity中,通过Activity.findViewById()方法找到这个UI组件进行操作,下面是findViewById()方法的完整签名:
public View findViewById(int id)
可以看出,findViewById()方法返回的是所有UI组件的父类:View,要操作具体UI组件,还需要对其进行强制类型转换。一旦获取到UI组件的对象,那么接下来就可以通过Java代码来控制它了。
在使用XML布局资源文件定义UI组件的时候,有两点需要特别注意:
1. 在同一项目的多个XML布局资源文件中定义的UI组件,ID是允许重名的,但是在单个XML布局文件中,ID必须唯一。
2. 因为不同XML布局文件中UI组件ID可以重名,所以在Activity中,使用findViewById()方法查找XML布局文件中定义的UI组件时,必须先调用Activity.setContentView()方法进行指定Activity的内容视图。
示例:使用XML布局文件定义一个UI界面,并且对其进行简单的操作。
代码清单:\codes\03\3.2\XmlFileDefineLayout\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="vertical" tools:context=".MainActivity" > <!-- 定义一个按钮,并指定点击事件名为:btnClick --> <Button android:id="@+id/btn_click" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="btnClick" android:text="Say hello" /> <!-- 定义一个文本显示控件,用于文本 --> <TextView android:id="@+id/tv_show" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
代码清单:\codes\03\3.2\XmlFileDefineLayout\src\com\bookdemo\xmlfiledefinelayout\MainActivity.java
public class MainActivity extends Activity { private TextView tv_show; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 为Activity指定内容视图 setContentView(R.layout.activity_main); // 找到文本显示控件 tv_show=(TextView) findViewById(R.id.tv_show); } /** * 按钮控件响应的点击事件 * @param v 当前触发点击事件的View */ public void btnClick(View v){ tv_show.setText("Hello Android"); } }
在模拟器上调试运行,效果如下:
虽然Android推荐使用XML布局文件来定义UI组件,但是如果需要,除了使用XML布局文件来定义UI组件,还可以使用Java代码来动态定义与控制UI组件。前面介绍到,UI组件在XML布局文件中以XML标签的形式定义,但是大部分标签在Android SDK中均有对应的类,使用Java代码动态定义UI组件即是操作这些类的行为。
定义好的布局对象还需要有Activity来承载显示,所以需要调用Activity.setContentView()方法来为Activity指定显示的布局对象,这里使用的是setContentView()另外一个重载方法,其完整签名如下:
public void setContentView(View view)
示例:通过一个简单的示例演示如何在运行时,完全依赖动态Java代码的形式,进行UI界面布局。
代码清单:\codes\03\3.2\JavaCodeDefineLayout\src\com\bookdemo\javacodedefinelayout\MainActivity.java
public class MainActivity extends Activity { private LinearLayout layout; private Button btnClick; private TextView tvShow; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 不使用XML布局文件定义Activity的内容视图 // setContentView(R.layout.activity_main); // 定义一个线性布局对象 layout=new LinearLayout(this); // 指定线性布局方向为垂直 layout.setOrientation(LinearLayout.VERTICAL); // 指定其为匹配父窗口 layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); // 定义一个按钮对象 btnClick=new Button(this); btnClick.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); // 指定其显示文本 btnClick.setText("Say hello"); // 为按钮添加点击响应监听器 btnClick.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(tvShow!=null){ tvShow.setText("Hello Android"); } } }); // 定义一个文本展示控件 tvShow=new TextView(this); tvShow.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); // 把定义的UI控件添加到布局对象中 layout.addView(btnClick); layout.addView(tvShow); // 指定Activity的内容视图为定义的线性布局对象 setContentView(layout); } }
在模拟器上运行会发现其效果与使用XML布局文件定义UI的示例一样,如下图: