Android用户界面学习.doc_第1页
Android用户界面学习.doc_第2页
Android用户界面学习.doc_第3页
Android用户界面学习.doc_第4页
Android用户界面学习.doc_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Android用户界面设计学习之旅/(在读本文之前,会缺省的认为你已经知道如何创建一个Android项目,并知道如何在模拟器中运行这个项目。并且,期望你已经有一点HTML或者其他GUI的开发经验。)在我的理解中,对开发者来说,写J2SE的程序和J2ME的程序相比,最大的区别不是他们API或者是其他一些规则、限制等的不同,更多的是两者程序界面(或者说UI)方面的区别。我们写任何一段程序,都是需要有UI的,因为我们的程序最终是给用户去用的,即使我们写了一个工具,没有任何显式IO,我们也还是需要暴露必要的方法来提供别人使用,在此情景下,这些方法似乎也可以看作是UI。对J2SE来说,一般都不会需要GUI,因为我们很少去写SWING、SWT程序,即使Sun力推的JavaFX,好像涉及的也不多,而对于 J2ME来说,最大的困难可以就是那些GUI的实现,以及如何将程序的功能绑定到那些界面上,从界面中接收用户的输入,或者是用合适、合理的方式向界面输 出,无论是通过文本,或是曲线、图形。同理,如果你有J2EE的经验,服务后台的代码往往是相对易读、易懂、系统并且内聚的,这些代码看起来是如此的和谐、整洁、干净。而如果涉及到界 面,就会陡然复杂的多,即使各种各样的framework试图要解决View与Model、Control的协作问题,结果却让大家更加的迷惑于各种配置 之间。总是有GUI的程序都会看起来有些凌乱和繁芜。似乎有些跑题 打住:)。咳咳,同样,对于Android开发来说,用户界面的实现应该是比较重要的和复杂的一环。好消息是,到目前为止,“神仙”们也没有发现其他更 好的用户界面实现方式,所以说如果有HTML设计经验,或者说有Swing,Flash等图形设计经验,那么理解Android的UI设计,会容易的多, 甚至会有似曾相识的感觉。Android的用户界面可以有两种实现方式:使用XML或者是使用Java代码。通过直接书写代码的方式来实现界面是比较恐怖的事情。举个例子来 说,如果你有DHTML的经验,那么这两者的区别可以比喻为:用XML来实现用户界面就像直接写HTML代码,而用 Java代码来实现用户界面就像用Javascript创建DOM对象来拼接页面。所以,使用XML来布局界面应该是首选。Android使用一个XML文件来定义用户界面。为了方便理解,你可以直接把它理解为一个HTML文件。事实上,它也确实比较像一个HTML文件。这个XML文件的格式为:+(0 or 1 per layout file, assigned to any element)这里面有一个比较重要的类叫ViewGroup,这个XML的root节点必须是一个ViewGroup,或者是一个单一的Widget(整个XML只有一个元素)。Android几乎所有的UI似乎都和ViewGroup有或多或少的关系。但是它只是一个abstract class,并不能直接使用,我们能用的,是它的一些子类,例如: AbsoluteLayout FrameLayout LinearLayout RelativeLayout TableLayout 其他还有很多,以后用到的时候再说,一次性把这些东西都弄明白既不客观也不现实。从上述这几个类从名字就可看的出来,他们是Layout,也就是布局,如果用过Swing的话,这些东西和Swing的那套东西一致,如果没有用过 Swing,希望你用过HTML,那么每一个Layout,可以理解为有了特定排版样式的DIV。在DIV的内部,可以放置其他的DIV,当然也可以放置 最底层的元素,比如说文本、文本框、单选按钮、图片等等。这里面所说的最底层的元素,它们有一个超类叫做View,这个超类非常的超,连 ViewGroup都是它的子类。ViewGroup就是能容纳其他View的View。常用的View有很多,可以参考这里,后文再介绍。关于XML布局,可以总结一下:1. 这个XML文件是由许多View嵌套组成的2. 如果布局中有多个元素,那么最顶层必须是ViewGroup(一个ViewGroup对象同时也是一个View对象),不可以是View,如果整个布局只有一个元素,那么最顶层元素就是这个唯一的元素。3. 在ViewGroup可以内部嵌套View(既然可以嵌套View,就更以嵌套ViewGroup了)4. 在View中,不可嵌套其他东西了,要不然它就是ViewGroup了,就是这么定义的。用一个结构图表示:上面提到的几个ViewGroup,稍微详细点介绍一下: AbsoluteLayout,绝对定位的布局方式,在它内部嵌套的元素必须指定具体的位置。 FrameLayout, 帧布局方式,说帧不太容易理解,可以说成是层布局方式,也就是说,在它内部的元素,是一层一层的叠加在一起的。如果用过Photoshop,或者 Flash,这里面的层的概念是和他们一致的。如果最上层的元素是不透明的,并且比下面的元素尺寸要大,那么将看不到下面的元素,只能看到顶层元素。这些 层的顺序是:最新声明的放到最前面。可以这样理解,Android按文件的书写顺序来组织这个布局,先声明的放在第一层,再声明的放到第二层,最后声 明的放在最顶层。 LinearLayout,线性布局方式(真不知道这该怎么翻译,其实很多技术名词还是不翻译的好),这种布局比较常用,也比较简单,就是每个元素占一行,当然也可能声明为横向排放,也就是每个元素占一列。 RelativeLayout, 相对定位的布局方式,这个比较好玩,在元素的位置的时候,使用相对位置,可以相对其他元素,也可以相对这个布局,就像我说:我现在站在pawa和 tempest的中间;或者说,我站在队伍的中间。前者就是相对其他元素来定义位置,后者是相对整个布局来定义位置。(注:pawa和tempest是 Android历史上很著名的两位人物,具体请参阅 R)。 TableLayout,表格的布局方式,我真的不忍心翻译Table这个词,翻译成表格,似乎少了一些神韵,这里面的Table和HTML中的Table非常像,就连写法都非常像。其实,说了这么一大堆,还是不如一个具体的实例看的痛快:详细解释一下: 首先,定义了一个LinearLayout,前面中说过,这个布局要么将子元素水平排列,要么将它们竖直排列。o android:orientation=”vertical”声明此布局中的子元素要竖直排列,这样如果在这个布局中有两个子元素的话,那么这两个将分别各占一行,如果将这个值设置为”horizontal”,就变 成了水平排列,那么两个子元素将分别各占一列,但是在这个示例中,只声明了一个子元素,你可以再为它添加一个子元素来观察效果。o android:layout_width=”fill_parent”声明此布局的宽度为:填满parent,这里面的parent也不好翻译,意思就是,如果它是嵌套在其他ViewGroup之中,那么那个ViewGroup的宽度就是它的宽度,如果它是顶层的元素,那么就填满屏幕。o android:layout_height=”fill_parent”声明此布局的高度为:填满parent。 然后,定义了一个TextView,一个TextView,就是一块区域,用来显示文本,用这个View定义的元素只能用来显示,是不可以编辑的,如果想要可编辑的文本块,那么应该使用它的子类EditText,这个等后面遇到再说。o android:layout_width=”fill_parent”同上。o android:layout_height=”wrap_content”wrap_content的意思是:够用即可,那如果说填满整个parent都不够用呢?那就只能显示那么多了,空间不够的只能被隐藏掉了,所以必要的时候得使用ScrollView,后面再说。o android:text=”string/hello”用来定义这个文本框中显示的内容,你可以直接将字符串写在这里:android:text=”hello, R”,也可以像本例中的那样,将所有的字符串放到一个资源文件中,然后在这里直接引用那个资源文件中的定义。在这里就是使用资源文件中的 hello变量,在Android的缺省设置中,这个资源文件是:res/values/strings.xml。在这里你可能会问为什么声明一 下”string/hello”就知道使用这个文件中定义的字符串呢,这个也留在后面详述,关于res目录下的东西还有很多,可以参考一下这里或者这里。每一种元素可以定义属性有很多,并且这些属性都可以和HTML的css中的属性来类比,遇到的时候再叙或者是翻一下相关文档。通过上一篇文章,大概了解了Android用户界面的设计方式,以及如何通过XML来设计界面。并且完成了一个非常简单的示例。在上一篇文章中,涉及到了一些资源文件,直观点说,就是res目录下的那些目录和文件,常用的有: res/drawable/ 用来存放图片文件 res/layout/ 用来存放布局定义文件 res/values/ 用来存放一些变量、参数等文件这些资源文件都是独立于代码而存在的,那么在代码中又是如何访问到这些资源的呢?在 Android的代码中,有一个文件比较奇怪,第一次接触到Android代码的人都应该迷惑过,这个文件就是R.java,在R.java的注释部分, 有这样一段话:“AUTO-GENERATE FILE. DO NOT MODIFY”,这个文件是自动生成的,不要修改。 这个文件就是Java代码和独立于Java代码的资源文件之间的访问窗口,Java程序可以通过R.java来访问那些资源文件。 这个文件是在程序编译过程中由aapt(Android Asset Packaging Tool) 自动生成 这个文件中的属性都是public static final的,所以可以直接在Java代码中引用,每个属性都代表一个资源,看起来就像为每个资源都定义了一个ID,然后通过这个ID来访问资源 所有的资源文件都被编译进最后生成的二进制包中,这样能够带来很高的性能和效率按照前面的示例,那么在R.java中会存在像这样一段代码:publicfinalclassR publicstaticfinalclassattr publicstaticfinalclassdrawable publicstaticfinalinticon=0x7f020000;publicstaticfinalclasslayout publicstaticfinalintmain=0x7f030000;publicstaticfinalclassstring publicstaticfinalintapp_name=0x7f040001;publicstaticfinalinthello=0x7f040000;这里面的main就是由res/layout/main.xml生成的,其他两个常量是由res/drawable/下icon.png和res/values/strings.xml生成的。接下来在看一下,如何在Java代码中使用这个R.java,创建一个文件Adventure.java :(开始快乐的学习旅程_)packagecom.penguin.adventure;importandroid.app.Activity;importandroid.os.Bundle;publicclassAdventureextendsActivity /* Called when the activity is first created. */OverridepublicvoidonCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);setContentView(R.layout.main);注意这其中的R.layout.main,通过setContextView(),被Java程序调用。这段代码中引入了另外一个非常重要的概念:Activity,到目前为止,已经介绍的另外两个比较重要的概念是 ViewGroup和View。如果套用时髦的MVC来理解的话:ViewGroup和View属于View领域的东西,Activity可以理解为 Control领域的东西,虽然可以这么类比着来理解,但是Activity其实做了更多的事情,由它将View和一些数据、操作等结合在一起,完成一个相对完整的行为、活动。所以,任何 View要被显示,必须通过Activity来进行。这样每个Activity都会包含特定的行为,多个Activity互相合作,最终组成一个完整的 Android程序。在示例的Activity中,有一个onCreate()方法,这个方法会在此Activity被创建的时刻调用。在方法内部,设置此 Activity的视图为R.layout.main中定义的视图,也就是res/layout/main.xml中定义的视图 (视图、布局、GUI、UI在这里已经混合使用了,并且他们意义相同,后文统一用View表示)。Activity所包含的内容很多,会用单独的一篇文章来详细介绍。说到此处,我们应该知道如何创建一个View,并通过Activity将其显示在屏幕上。接下来事情,就是用户如何和这个Activity交互。通过上一篇文章,知道了如何创建一个应用程序来显示一个静态的View。然而,在大多数情况下仅仅显示是不够的,应该还需要与用户的交互行为。现在完成一个简单的和用户交互的示例。这个小程序的需求是:画面上有三行元素:1. 第一行是一个TextView,用来显示文字2. 第二行是一个EditText,用户将在此输入文字3. 第三行是一个Button4. 用户点击Button之后,会在第一行的TextView中显示:Hello,(用户在第二行中输入的文字)。比如说用户在输入框中输入:“R”,那么点击Button之后,会在显示区域显示:“Hello, R”。要完成这个程序,大概需要用5步:第1步,先完成UI的设计,修改上次项目在res/layout/目录下main.xml的文件:如果已经过前两站的学习的话,这个文件还是比较容易懂的,不需要太多的解释了,只解释一下这几个语句: android:id=”+id/textview_display”这个是用来为当前的View声明一个ID,这样,在Java程序中就可以通过这个ID来找到这个元素,进而能够操作这个元素。 android:textSize=”20px”声明字体大小为20px,对于每种View,都会有一系列的可以设置的属性,具体的需要参考每个View的说明文档。第2步,创建好这个布局文件之后,再把这个文件需要的android:text=”string/sayhello”在res/values/strings.xml中补充声明一下:Hello, welcome to get aboard Android adventure!AdventureHi第3步,基于上一站UI设计的基础上修改Adventure.java,为UI添加交互动作,添加完毕之后:packagecom.penguin.adventure;importandroid.app.Activity;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;importandroid.widget.EditText;importandroid.widget.TextView;publicclassAdventureextendsActivity /* Called when the activity is first created. */OverridepublicvoidonCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);setContentView(R.layout.main);Button btn = (Button) findViewById(R.id.button_hi);btn.setOnClickListener(newView.OnClickListener() publicvoidonClick(View v) / TODO Auto-generated method stubEditText edt = (EditText) findViewById(R.id.edittext_content);TextView txv = (TextView) findViewById(R.id.textview_display);String hi = getResources().getString(R.string.sayhi);txv.setText(hi +, + edt.getText(););这里面有些语句需要解释: Button btn = (Button) findViewById(R.id.button_sayhello)这个语句中的findViewById()s是一个比较简单、重要、常用并且是一直用的语句,他的功能就是在当前的ContentView中按ID来找到 对应的View。例如这里,通过R.id.button_sayhello,就能找到第1步提到的Button了。这个用法和javascript中 的:document.getElementById()有异曲同工之妙。那这里面的R.id.button_sayhello又是怎么出来的呢?前文中 说过,在Build的时候,aapt会自动生成R.java,对资源文件中的 android:id=”+id/textview_display”,就会在R.java中向对应的生成一个ID。 btn.setOnClickListener(new View.OnClickListener()现在的GUI程序,好像都喜欢事件驱动的模型,有人这样描述过GUI系统本质: 在事件驱动下动态地展现数据模型的图形系统。在这个语句中,setOnClickListener就是为btn添加一个事件监听,监听OnClick事 件,也就是说,如果一旦触发btn的OnClick事件,就会执行后面定义的功能。第5步,运行程序,欣赏这部作品吧. Done. OMG, its so easy, isnt it? :)前面的文章已经讲到了如何在一个Activity中与用户进行交互。这篇文章将解释如何创建多个Activity的用户界面。这个多Activity的示例程序的功能大概是这样的:1. 在主页面上有三个元素:一个文本输入框,两个按钮。用户可以在文本框中输入一些字符,如This is PalmCity2. 点击第一个按钮,将弹出一个对话框形式的Activity,显示”Hi, welcome to get aboard Android adventure!+回车+你输入的内容”3. 如果点击的是第二个按钮,将显示另一个全屏的Activity,显示”Hi, welcome to get aboard Android adventure!+回车+你输入的内容”OK,按照前面的规矩,分成几步:第1步,先完成UI的设计,创建布局。从程序来看,似乎有三个Activity,但是第二个和第三个几乎是相同的,于是,只创建两个布局:res/layout/main.xmlres/layout/dialog.xml第2步,然后呢,需要把上面提到的字符变量声明一下:res/values/strings.xmlHi, welcome to get aboard Android adventure!AdventureHi(Dialog)Hi(Activity)第3步,创建Activity,这里和第一步一样,虽然有三个Activity,但是看起来用两个其实就够了。 然而事实并非如此,具体原因后续,我们需要定义三个Activity:分别将他们定义为:Adventure(用来显示主画面)、 AlertDialog(用来显示对话框)和AlertActivity(用来显示那个全屏的Activity)。主Activity(Adventure.java):packagecom.penguin.adventure;importandroid.app.Activity;importandroid.content.Intent;importandroid.os.Bundle;importandroid.util.Log;importandroid.view.View;importandroid.widget.Button;importandroid.widget.EditText;publicclassAdventureextendsActivity privatestaticfinalString TAG =Main Activity;/* Called when the activity is first created. */OverridepublicvoidonCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);Log.d(TAG,onCreate .);setContentView(R.layout.main);finalEditText edt = (EditText) findViewById(R.id.textview_input);/ try to display a dialogButton btnDialog = (Button) findViewById(R.id.button_hi_dialog);btnDialog.setOnClickListener(newView.OnClickListener() publicvoidonClick(View v) / TODO Auto-generated method stubIntent intent =newIntent();intent.putExtra(str, edt.getText().toString();intent.setClass(Adventure.this, AlertDialog.class);startActivity(intent););/ try to call and display a new activityButton btnActivity = (Button) findViewById(R.id.button_hi_activity);btnActivity.setOnClickListener(newView.OnClickListener() publicvoidonClick(View v) / TODO Auto-generated method stubIntent intent =newIntent();intent.putExtra(str, edt.getText().toString();intent.setAction(com.penguin.action.Main);startActivity(intent););OverridepublicvoidonStart() super.onStart();Log.d(TAG,onStart .);OverridepublicvoidonResume()super.onResume();Log.d(TAG,onResume .);OverridepublicvoidonPause()super.onPause();Log.d(TAG,onPause .);OverridepublicvoidonStop()super.onStop();Log.d(TAG,onStop .);OverridepublicvoidonDestroy()super.onDestroy();Log.d(TAG,onDestroy .);OverridepublicvoidonRestart()super.onRestart();Log.d(TAG,onRestart .);在这里面:以下语句,前文都提到过: final EditText edt = (EditText) findViewById(R.id.textview_input) btn_Dialog.setOnClickListener(new OnClickListener()主要说一下这些: Log.d(TAG, “onStart ”);这是Android中日志的处理方式,用法于Log4j类似,但是要比Log4j简单的多,因为用的几乎都是static的方法。分别是Log.v 、 Log.d 、 log.i、 log.w、 log.e。使用Log打印的日志通过LogCat可以看到。方法中的第一个属性一般用来标识一下日志是谁打印出来的,便于查找。 Intent intent = new Intent();对UI来说,这里面的Intent是一个非常重要的概念。并且要理解它会比理解View、Activity什么的要困难一些,在这里,只需要知道:通过它,可以找到下一个要显示的Activity,并为这个Activity携带了一些数据。也就是说 它有两个重要的使命:定位下一个Activity;并捎带一些数据。所以在Android的文档中,称Intent为Activity之间的双面胶。 startActivity(intent);通过startActivity(intent)可以启动并显示另外一个Activity。第2个Activity(AlertDialog.java):packagecom.penguin.adventure;importandroid.app.Activity;importandroid.content.Intent;importandroid.os.Bundle;importandroid.widget.TextView;publicclassAlertDialogextendsActivity OverridepublicvoidonCreate(Bundle savedInstanceState)super.onCreate(savedInstanceState);setContentView(R.layout.dialog);Intent intent = getIntent();String str = (String) intent.getExtras().get(str);TextView txv = (TextView) findViewById(R.id.textview_hi);if(null!= str)String hi = getResources().getString(R.string.hi);txv.setText(hi +n+str);在这个Activity里面,只有一个语句需要解释一下: String name = (String) intent.getExtras().get(”str”);用来获得前面Activity的intent.putExtra(str, edt.getText().toString();捎带过来的数据第3个Activity(AlertActivity.java):packagecom.penguin.adventure;importandroid.app.Activity;importandroid.content.Intent;importandroid.os.Bundle;importandroid.widget.TextView;publicclassAlertActivityextendsActivity OverridepublicvoidonCreate(Bundle savedInstanceState)super.onCreate(savedInstanceState);setContentView(R.layout.dialog);Intent intent = getIntent();String str = (String) intent.getExtras().get(str);TextView txv = (TextView) findViewById(R.id.textview_hi);if(null!= str)String hi = getResources().getString(R.string.hi);txv.setText(hi +n+ str);到这一步,所有的事情似乎都已经完成了,可以运行了,如果在这时你等不及而去运行程序,将会得到一些 ActivityNotFoundException 之类的异常。这里还需要一步,如果以前写的程序都是单Activity的,那么Eclipse的Android插件会自动完成这一步,如果是多 Activity的,或者需要对Activity作更仔细的控制,那么就要这一步了。第4步,编辑AndroidManifest.xml这个文件像一个户口簿一样记录每一个Activity的信息,Android系统会通过这个文件得到:执行这个程序的时候,启动的是那个Activity 等信息。不仅如此,这个还包括Intent、Provider等其他一些信息。如果你用过一些Web MVC框架的话,这个文件的功能就像是那个MVC的配置文件。注意这里面的第二个和

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论