【前言】

本文由ChrisBlunt发表在smashingmagazine,bill学习之后,觉得与国内众多Android入门教程相比,此文堪称经典,鉴于有些朋友对Android非常感兴趣却迟迟找不到好的入门文章,在此特向大家推荐这篇博文。

http://coding.smashingmagazine.com/2010/10/25/get-started-developing-for-android-with-eclipse/

希望ChrisBlunt的这篇文章能够带领更多的人进入Android的开发世界。

为了与一些对英文不太感冒的Android爱好者一起学习,同时也为了提高一下自己的语言表达、组织能力,特将文翻译过来供大家学习参考。

译文bill已字字斟酌,但限于本人学识有限,译文中可能出现术语或者习语翻译不当甚或有错,希望读者积极指出,bill会非常高兴收到你们的反馈,在此谢过。

文-下】

建立你的第一个Android应用

这个测试应用程序倒是工作的蛮不错,但你总得建立自己的真正的应用吧?基于此,我们将通过一个简单的应用设计,带领你一步一步地学会开发Android应用并使它在Android设备上运行。

如你所知,许多开发者(包括我在内)都喜欢在工作之余泡上一杯好茶(或者咖啡)。在接下来的小节中,我将带领你创建一个简单的teacounter应用,用于记录目前为止这个用户一共冲泡了几杯茶,并允许他们为自己的冲泡设置一个倒计时提醒。

你可以在GitHub.中下载到这个应用的源码。

设计用户界面

在建立任何Android应用之前,我们总需要先设计并建立用户界面。

下面是这个应用界面的一个预览:

用户可以通过“+”,“-”按钮设置冲泡时间(以分为单位)。当他们点击“Start”按钮,冲泡倒计时便开始啦。

除非用户再次点击该按钮以取消倒计时,那么当倒计时完成时,冲泡的杯数就会自动加1。

创建用户界面

Android的用户界面(或者说用XML文档描述的layouts)被保存于项目中的res/layouts文件夹。在之前的示例应用中那个显示“HelloWorld”的简单界面由Eclipse自动生成并保存于res/layouts/main.xml中。

Eclipse也提供了图形化界面设计器,它允许你对这些界面元素进行拖拽编排。尽管如此,我还是觉得在XML文档中手动编写界面,然后在图形化界面设计器中预览我编写的界面更简单易行。

现在,让我们修改main.xml文档以便使其展现出我们刚才设计的那个界面。

①在Eclipse的项目浏览器中,双击打开res/layouts/main.xml文档

②选择main.xml的XML视图标签

现在,将XML文档中的内容修改如下【bill注:最好自己手动写一遍】

        
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"android:layout_width="fill_parent"
  4. android:layout_height="fill_parent">
  5. <LinearLayoutandroid:orientation="horizontal"
  6. android:layout_width="fill_parent"android:layout_height="wrap_content"
  7. android:padding="10dip">
  8. <TextViewandroid:layout_width="wrap_content"
  9. android:layout_height="wrap_content"android:textSize="20dip"
  10. android:text="Brews:"/>
  11. <TextViewandroid:layout_width="fill_parent"
  12. android:layout_height="wrap_content"android:text="None"
  13. android:gravity="right"android:textSize="20dip"android:id="@+id/brew_count_label"/>
  14. </LinearLayout>
  15. <LinearLayoutandroid:orientation="horizontal"
  16. android:layout_width="fill_parent"android:layout_height="wrap_content"
  17. android:layout_weight="1"android:gravity="center"android:padding="10dip">
  18. <Buttonandroid:id="@+id/brew_time_down"android:layout_width="wrap_content"
  19. android:layout_height="wrap_content"android:text="-"
  20. android:textSize="40dip"/>
  21. <TextViewandroid:id="@+id/brew_time"android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"android:text="0:00"
  23. android:textSize="40dip"android:padding="10dip"/>
  24. <Buttonandroid:id="@+id/brew_time_up"android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"android:text="+"
  26. android:textSize="40dip"/>
  27. </LinearLayout>
  28. <Buttonandroid:id="@+id/brew_start"android:layout_width="fill_parent"
  29. android:layout_height="wrap_content"android:layout_gravity="bottom"
  30. android:text="Start"/>
  31. </LinearLayout>

正如你所见,Android的XML布局文件非常冗余,但却能够帮助你掌控屏幕上几乎所有的视觉因素。

在Android布局文件中一个重要的布局元素是——布局容器(布局方式),比如这个例子中的线性布局(LinearLayout)。这种布局对用户是不可见的,只作为那些可见的,诸如按钮、文本框等视觉元素的容器。

还有其他许多种布局方式,每一种方式都提供了一种不同的布局效果。比如线性布局(LinearLayout)、绝对布局(AbsoluteLayout),还有基于网格的表格布局(TableLayout)等等,你可以在CommonLayoutObjects中找到更多有关布局方式的描述。

编写代码链接你的布局元素

当你完成布局文件的编写之后,再次运行这个应用,你会发现界面已经不是刚才那个简单的“helloworld”了,取而代之的是我们为这个应用设计的用户界面。

如果你现在点击界面中的按钮,你会发现他们会表现得和你预期的一样——高亮显示,但是,他们不会为你做任何事情。

下面让我们来编写代码,使得点击界面按钮时有适当的事情发生。

        
  1. #/src/com/example/brewclock/BrewClockActivity.java
  2. ...
  3. importandroid.widget.Button;
  4. importandroid.widget.TextView;
  5. publicclassBrewClockActivityextendsActivity{
  6. /**Properties**/
  7. protectedButtonbrewAddTime;
  8. protectedButtonbrewDecreaseTime;
  9. protectedButtonstartBrew;
  10. protectedTextViewbrewCountLabel;
  11. protectedTextViewbrewTimeLabel;
  12. ...
  13. }

接着,我们将改变源代码中的onCreate()的实现。这是一个回调函数,只要Android系统启动你的应用,这个方法就会被调用。在Eclipse自动生成的onCreate()实现中,将我们的应用布局设置成了R.layout.main。正是这一行代码告诉Android系统将我们的layout布局文件译码并展现给用户。

资源对象TheResourceObject

Android中,R类是一个特殊的资源类,允许你在自己的java代码中通过它访问项目资源(布局layouts,字符串strings,菜单menus,图标icons等等)。每一个资源都被赋予了一个ID,在上面的res/layouts/main.xml布局文件中,通过“@+id”这一属性实现。我们将利用这一属性将布局文件中的按钮或者文本;连接到我们的JAVA实现代码中。

        
  1. #/src/com/example/brewclock/BrewClockActivity.java
  2. ...
  3. publicclassBrewClockActivityextendsActivity{
  4. ...
  5. publicvoidonCreate(BundlesavedInstanceState){
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.main);
  8. //Connectinterfaceelementstoproperties
  9. brewAddTime=(Button)findViewById(R.id.brew_time_up);
  10. brewDecreaseTime=(Button)findViewById(R.id.brew_time_down);
  11. startBrew=(Button)findViewById(R.id.brew_start);
  12. brewCountLabel=(TextView)findViewById(R.id.brew_count_label);
  13. brewTimeLabel=(TextView)findViewById(R.id.brew_time);
  14. }
  15. }

监听事件ListeningForEvents

为了能够得知用户在何时点击了我们的按钮,我们必须实现一个监听器。你可能会觉得这很像其他拥有事件驱动的平台的listemers或者callbacks,就像Javascript/JQuery的events或者Rail的callbacks。

Android通过监听器接口向我们提供了一个类似的机制。比如OnClickListener接口定义了一个当某事件发生时会被触发的方法。为了让我们的应用程序知道用户点击了屏幕上的哪一个按钮,我们需要实现OnClickListener接口并将其绑定到某个按钮上。这样,当用户点击该按钮时,OnClickListener就会通知我们的应用。

        
  1. #/src/com/example/brewclock/BrewClockActivity.java
  2. ...
  3. //Besurenottoimport
  4. //`android.content.dialoginterface.OnClickListener`.
  5. importandroid.view.View.OnClickListener;
  6. publicclassBrewClockActivityextendsActivity
  7. implementsOnClickListener{
  8. ...
  9. publicvoidonCreate(BundlesavedInstanceState){
  10. ...
  11. //SetupClickListeners
  12. brewAddTime.setOnClickListener(this);
  13. brewDecreaseTime.setOnClickListener(this);
  14. startBrew.setOnClickListener(this);
  15. }
  16. ...
  17. publicvoidonClick(Viewv){
  18. //TODO:Addcodetohandlebuttontaps
  19. }

接下来,我们要添加能够处理这些点击事件的代码。我们还向自己的Activity添加了4个新的属性——冲泡时间、冲泡倒计时、已经完成杯数以及倒计时是否正在进行的标记。

        
  1. #/src/com/example/brewclock/BrewClockActivity.java
  2. ...
  3. publicclassBrewClockActivityextendsActivity
  4. implementsOnClickListener{
  5. ...
  6. protectedintbrewTime=3;
  7. protectedCountDownTimerbrewCountDownTimer;
  8. protectedintbrewCount=0;
  9. protectedbooleanisBrewing=false;
  10. ...
  11. publicvoidonClick(Viewv){
  12. if(v==brewAddTime)
  13. setBrewTime(brewTime+1);
  14. elseif(v==brewDecreaseTime)
  15. setBrewTime(brewTime-1);
  16. elseif(v==startBrew){
  17. if(isBrewing)
  18. stopBrew();
  19. else
  20. startBrew();
  21. }
  22. }
  23. }

注意,我们用到了Android系统提供的CountDownTimer(倒数计时器)。它将使你能够轻松地创建一个见到的倒数计时器,并在其运行期间定期通知某些事件。你将在接下来的startBrew方法中使用到这个计时器。

下面的这些方法将实现——设置冲泡时间、开始或终止冲泡以及记录成功冲泡的杯数。我们还将在onCreate方法中添加对“冲泡时间”和“成功冲泡杯数”这两个属性的初始化操作。

在工程实践中,推荐将下面这些方法单独地列写于各个模块类中,这里只是为了简单起见才把他们全部写在BrewClockActivity这一个类中

        
  1. #/src/com/example/brewclock/BrewClockActivity.java
  2. ...
  3. publicclassBrewClockActivityextendsActivity
  4. implementsOnClickListener{
  5. ...
  6. publicvoidonCreate(BundlesavedInstanceState){
  7. ...
  8. //Settheinitialbrewvalues
  9. setBrewCount(0);
  10. setBrewTime(3);
  11. }
  12. /**
  13. *Setanabsolutevalueforthenumberofminutestobrew.
  14. *Hasnoeffectifabrewiscurrentlyrunning.
  15. *@paramminutesThenumberofminutestobrew.
  16. */
  17. publicvoidsetBrewTime(intminutes){
  18. if(isBrewing)
  19. return;
  20. brewTime=minutes;
  21. if(brewTime<1)
  22. brewTime=1;
  23. brewTimeLabel.setText(String.valueOf(brewTime)+"m");
  24. }
  25. /**
  26. *Setthenumberofbrewsthathavebeenmade,andupdate
  27. *theinterface.
  28. *@paramcountThenewnumberofbrews
  29. */
  30. publicvoidsetBrewCount(intcount){
  31. brewCount=count;
  32. brewCountLabel.setText(String.valueOf(brewCount));
  33. }
  34. /**
  35. *Startthebrewtimer
  36. */
  37. publicvoidstartBrew(){
  38. //CreateanewCountDownTimertotrackthebrewtime
  39. brewCountDownTimer=newCountDownTimer(brewTime*60*1000,1000){
  40. @Override
  41. publicvoidonTick(longmillisUntilFinished){
  42. brewTimeLabel.setText(String.valueOf(millisUntilFinished/1000)+"s");
  43. }
  44. @Override
  45. publicvoidonFinish(){
  46. isBrewing=false;
  47. setBrewCount(brewCount+1);
  48. brewTimeLabel.setText("BrewUp!");
  49. startBrew.setText("Start");
  50. }
  51. };
  52. brewCountDownTimer.start();
  53. startBrew.setText("Stop");
  54. isBrewing=true;
  55. }
  56. /**
  57. *Stopthebrewtimer
  58. */
  59. publicvoidstopBrew(){
  60. if(brewCountDownTimer!=null)
  61. brewCountDownTimer.cancel();
  62. isBrewing=false;
  63. startBrew.setText("Start");
  64. }
  65. ...

这一大段代码中唯一牵涉到Android的一部分是通过setText方法设置显示的labels。在startBrew方法中,我们建立并启动了一个以秒为单位的倒数计时器,直到一次冲泡完成。注意,我们内嵌地实现了该倒数计时器的两个监听方法(onTick和onFinish)。onTick方法每1000毫秒(1秒)便会被调用一次,直到倒数计时为0时,onFinish方法被调用。

避免硬编码AvoidingHard-CodedTextinyourCode

为了使得本教程的代码更加简洁,我故意将那些标签字符串(比如“BrewUp!”,“Start”,“Stop”等)直接硬编码在了JAVA代码里。当从大一点的工程项目来考虑,这是非常糟糕的编程实践,因为它将会给查找或修改这些字符串带来极大的麻烦。

Android提供了一个更简洁的办法,通过R类将这些字面文本从你的JAVA硬编码中分离出来。

R类允许你在一个xml文件(res/values/strings.xml)中定义并在JAVA实现代码中引用整个应用程序所需的字符串资源。

例如:

        
  1. #/res/values/strings.xml
  2. <stringname="brew_up_label">BrewUp!</string>
  3. ...
  4. #/res/com/example/brewclock/BrewClockActivity.java
  5. ...
  6. brewLabel.setText(R.string.brew_up_label);
  7. ...

现在,如果你想将应用程序中的“BrewUp!”这个文本换成别的,你需要做的仅仅是修改这个xml文件中的值,你的应用程序便会将项目中所有用到这个资源的字符串字面值更新,这真是太棒了!

试试你的咖啡冲泡器

我们的代码已经完工,现在是时候体验一下效果了。点击“运行”或者按快捷键“Ctrl+F11”启动模拟器。当一切启动就绪,你就会看到我们之前设计的界面了,现在,是时候泡杯咖啡了!试着设置不同的冲泡时间并点击Start按钮,观察下倒数计时器吧^^

【后记】

此文为bill初学Android时的教程,感觉讲解逻辑清晰,代码完整,指导意义强,特翻译过来,希望能让更多的朋友受益。

最后,bill真心希望有热心的朋友帮我找找翻译中的弊病,这样bill才好和大家一起学习进步!再次感谢。

更多相关文章

  1. android关闭应用
  2. Android(安卓)SDK 2.2 开发环境搭建
  3. 第15章 Android启动过程 [Android应用开发与系统改造实战]
  4. Android(安卓)SDK 2.2 开发环境搭建
  5. Android笔记之adb命令应用实例1(手机端与PC端socket通讯上)
  6. android > Android新增API之AudioEffect中文API与应用实例
  7. Android和js、H5进行交互数据
  8. android使用aidl实现进程间通信
  9. Android(安卓)应用程序快速启动的秘诀

随机推荐

  1. Android(安卓)Monkey压力测试环境搭建及
  2. Invoke-customs are only supported star
  3. Android中的OpenGL ES使用基础
  4. 二维码识别IOS或Android客户端
  5. 调用高德地图、百度地图客户端
  6. android EditText 限制输入大小写,大写转
  7. Android(安卓)10.0 Activity启动详解(二)
  8. Gradle Android基本应用
  9. Android学习之多线程编程(handler篇)
  10. Android(安卓)Studio 自定义皮肤主题和背