目錄(?)[+]
Fromhttpswwwtianmayingcomtutoriala-simple-sample-for-android-development開發實例概述建立開發環境工欲善其事必先利其器配置java開發環境Android Studio的安裝創建項目項目結構運行應用在模擬器上運行應用在真機上運行應用展示列表簡化的老師列表準備數據實現模型設置Adapter運行效果優化模型改進列表創建新的布局創建自定義的ArrayAdapter運行效果創建第二個Activity實現行為事件處理Activity的跳轉Intent通過Intent傳遞參數設置Intent的Extra數據根據Intent數據展示內容androidandroid-studio 0 2今天帶大家做一個簡單的Android App,這個App會顯示創新工程實踐老師們的照片和信息,不妨先看一看效果:
雖然這個App非常簡單,但是涉及到了Android開發中的一些關鍵知識,比如:
配置開發環境App中一個屏幕的抽象:Activity
屏幕之間的跳轉:Intent
構成屏幕展示的視圖組件:顯示圖片的ImageView
,顯示文字的TextView
,把組件組成一個列表的視圖ListView
通過Adapter
來控制模型和視圖組件之間通信,即如何在視圖上展示特定的數據通過事件來處理用戶的交互:OnClickListener
讓我們開始吧!
在編寫代碼之前,我們需要在我們的計算機中配置集成開發環境(IDE,Integrated Development Environment),它是用來開發和部署軟件的工具集合。
如果你之前有過編程的經歷,那么一定會知道最重要的工具是編譯器——它將我們用高級語言編寫的源代碼轉換成計算機可以執行的指令來完成指定的任務。
開發環境的安裝和配置往往需要花費不少時間。對于不同的計算機以及操作系統平臺,安裝配置過程都不盡相同,會出現很多不可預測的錯誤—。新手見到這些錯誤往往會一頭霧水、不知如何解決。
好的開始等于成功的一般,開始學習前最重要的一個步驟就是完成開發環境的配置,讓我們開始吧。
Android的開發使用Java語言,因此首先需要在開發設備上配置好Java的開發環境。
參考Java開發環境安裝與配置。
Android Studio是Google官方強烈推薦的集成開發環境。在Android官方網站下載Android Studio,它包含了:
基于IntelliJ平臺的Android IDEAndroid SDK工具(API、驅動、源碼、樣例等等)Android模擬器由于眾所周知的原因,可能需要“翻墻”才能夠完整安裝Android Studio,這里給出一個百度網盤的下載鏈接:http://pan.baidu.com/s/1i3rIfPz
下載安裝文件之后,普通軟件的安裝過程沒有任何區別,不再贅述。
如果下載的不是最新版本,啟動Android Studio后,可以通過Check for Update更新到最新的版本。
這里先告訴大家一個小招數,如果在編程過程中,遇到錯誤提示,alt+Enter
(即按照alt
鍵的同時按下回車鍵)可以自動進行錯誤修復。比如,在開發過程中我們經常需要引入一些包,就能自動幫我們引入。
啟動Android Studio
如果Android Studio中尚未打開任何項目,在Welcome頁面選擇Start a new Android Studio PRoject
如果Android Studio中已經打開了其他項目,從文件
菜單中選擇New Project
Configure your new project中填寫相應信息:
application Name是我們項目的名稱,我們填寫為InnovationCourse
Company Domain是開發者所在的組織,一般是公司的域名,這里我們不妨填寫為zhihuishu.com
Project Location是項目存在在本地的位置
填寫好后,點擊Next
Select the form factors your app will run on中選擇Phone and Tablet
并設置Mininum SDK
為API 15: Android 4.0.3 (IceCreamSandwich)
。Mininum SDK
表示所支持的Android的最低版本,版本越低支持的設備數量就會越多。我們可以選擇不同的版本來看所支持設備的百分比。百分比越大,表示越多人可以使用你的APP。選擇好后點擊Next
Add an activity to Mobile中選擇Blank Activity
,點擊Next
Customize the Activity中設置Activity信息,這里我直接使用Android Studio提供的默認信息即可
Finish
,一個項目就創建成功了!如果你急于開始項目的開發,你可以略過這一小節。
現在我們已經創建了一個基本的Android應用,它包含了Android Studio幫助我們生成的文件,在默認的Android
視圖中,文件結構如下圖所示:
這里我們看到的是Android Studio給我們生成MainActivity
的代碼骨架,這個Activity就代表App啟動的時候,我們看到的那個屏幕。這個Java文件定義了一個Activity,當應用運行時,MainActivity
類啟動一個Acitivty
并加載activity_main.xml
布局文件,將其顯示在屏幕上。Acitvity
和layout
的關聯是在MainActivity
中onCreate()
方法里完成的:setContentView(R.layout.activity_main);
我們再雙擊layout
目錄下的activity_main.xml
,可以看到這個屏幕的預覽:
點擊下方的Text,我們可以以文本的形式看到這個文件的內容。這個文件就定義了屏幕中應該顯示哪些組件。你如果學過HTML的話,可以類比一下,HTML描述了一個網頁長什么樣子,而這個XML文件則描述了App長什么樣子??梢钥吹剑@個布局簡單的在屏幕上顯示了一條消息——Hello world!
我們再來來具體看一下其它幾個重要的文件:
app/src/main/AndroidManifest.xml
Android Manifest文件是描述Android應用的基本信息,并定義了應用中的各個組件(Activity是一種組件)。
)app/src/main/res
目錄下包含了應用所需要的資源文件:
drawable<density>/
- 圖片資源文件layout/
- 用戶界面布局描述文件menu/
- 應用的菜單布局values/
常量值例如字符串、顏色數值等strings/
國際化數據Create Virtual Device
創建模擬器創建完成后,AVD Manager如下圖:
模擬器創建完成后,回到Android Studio的項目中,在工具欄里點擊Run
按鈕,接下來會彈出一個Choose Device
窗口,選擇Launch emulator
并設置好需要使用的模擬器。
接下來等待模擬器啟動,然后就可以看見剛剛創建的應用運行在模擬器窗口中了(剛啟動的機器可能需要在模擬器中解鎖屏幕)
在真機上運行應用需要先進行一些設置:
將真機通過USB線纜連接至開發機器。如果在Windows上開發,可能需要選擇合適的USB驅動,可以參考OEM USB Drivers文檔在真機系統中打開USB調試選項接下來就可以在Android Studio運行應用了,方法和在模擬器相同,只是在Choose Device
窗口中需要選擇USB連接的真機。
這里我們以模擬器為例進行講解。
打開activity_main.xml
布局文件,在Design視圖下,我們將上面的HelloWorld標簽刪掉。
我們準備在這個屏幕中顯示老師的列表,而一個列表是一個ViewGroup,內部包含了其他的視圖。我們在顯示手機屏幕的預覽區的左側可以看到大量的視圖組件,這些就是用來構建我們App模樣的基本元素。我們我們選中ListView,將其拖入預覽區內
我們前后左右拖動一下,使其布滿屏幕。也可以切換到Text視圖來編輯XML,XML進行了修改之后,切回Design視圖可以馬上看到效果。
最終acitivity_main.xml
中的內容為:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.zhihuishu.innovationcourse.MainActivity"> <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/teacher_listView" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /></RelativeLayout>注意,這里面android:id="@+id/teacher_listView"
定義了這個ListView
的ID為teacher_listView
,這是需要大家手動去修改的。當然你也可以全部復制后替換掉整個XML文件的內容。
這個ID非常重要,我們在Java程序中,將需要通過這個ID來找到這個視圖組件,進行相應的設置和操作。
視圖組件還有其他一些屬性,比如這里其它四個屬性都是跟布局相關的屬性,比如android:layout_alignParentLeft="true"
就表示與包含它的父視圖是左側對齊的。其它屬性我們就不一一解釋了。
簡化的老師列表
準備數據:實現模型
我們這里先實現一個簡化的老師列表,只顯示老師的名字,圖片暫時不管。
首先我們需要準備老師的數據,我們來創建一個Teacher
類。
選中java
目錄下的com.zhihuishu.innovationcourse
包,【右鍵】->【New】->【Java Class】,在彈出的窗口中輸入類的名稱Teacher。
給Teacher
類增加一個獲取所有老師姓名的方法。這個Teacher
類,正是我們所說的MVC中M,即Model。
package com.zhihuishu.innovationcourse;import java.util.ArrayList;import java.util.List;public class Teacher { public static List<String> getAllTeachers() { List<String> teachers = new ArrayList<String>(); teachers.add("張海霞"); teachers.add("陳江"); teachers.add("葉蔚"); return teachers; }}這里我們采用了硬編碼的形式,通常情況下數據是從數據庫中取出來的,而且是不斷變化的。不過這里我們不涉及數據庫訪問,簡化處理了。大家知道有數據庫的存在就可以了。
設置Adapter
用來將數據傳遞給ListView
的適配器是ArrayAdapter
。這里我們傳入的是一個字符串的數組,因此我們創建一個ArrayAdapter<String>
類。
這部分代碼添加到MainActivity.java
的onCreate
方法中:
public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化一個Adapter ArrayAdapter<String> teacherAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, Teacher.getAllTeachers()); //通過ID獲取listView ListView listView = (ListView) findViewById(R.id.teacher_listView); //設置listView的Adapter listView.setAdapter(teacherAdapter); } ...}注意初始化Adapter的代碼ArrayAdapter<String> teacherAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, Teacher.getAllTeachers());
三個參數的含義:
第一個參數是this
,表示傳入的是當前的Activity第二個參數是android.R.layout.simple_list_item_1
,這是Android系統自帶的一個列表元素(即列表中的每一行)布局,只顯一串簡單的文字第三個參數是需要顯示的所有數據構成的List,即數據源后面我們會傳入自己定義的元素布局(因為我們還希望在每一行中顯示老師的圖片),數據源也需要修改,因為此時不僅僅包含字符串了,還需要包含圖片。
運行效果
我們已經可以看到一個簡單的老師列表的效果了:

優化模型
老師的信息不僅僅包括姓名,還包括圖片和介紹。因此我們需要給Teacher
類增加一些屬性,分別為name
、imageId
和desc
。
老師的圖片我們實現準備好了,大家只需要拷貝進入drawable
文件夾就能在Java代碼中引用了。我們之前說過drawable
文件夾就是用來存放圖片文件的。
增加屬性之后我們還需要做三件事情:
增加一個構造函數,這個構造有三個參數。即我們創建一個Teacher
類的實例時,需要告訴系統這個老師的名字、圖片和介紹。給每個屬性增加getter
和setter
,面向對象編程講究信息的隱藏,因此老師們的屬性都是private
的,為了讓外部能夠訪問老師的屬性,比如獲取老師的圖片來進行展示,那么就需要有訪問屬性的公共函數。getter
和setter
就是扮演這樣的角色。修改getAllTeachers()
方法,這個方法此時返回的是Teacher
對象構成的List,而不是字符串構成的List了。在這個方法的實現中,我們就通過Teacher的構造函數生成了三個Teacher
對象。package com.zhihuishu.innovationcourse;import java.util.ArrayList;import java.util.List;public class Teacher { private String name; private int imageId; private String desc; //構造函數 public Teacher(String name, int imageId, String desc) { this.name = name; this.imageId = imageId; this.desc = desc; } // 返回一個Teacher的列表 public static List<Teacher> getAllTeachers() { List<Teacher> teachers = new ArrayList<Teacher>(); teachers.add(new Teacher("張海霞", R.drawable.zhx, "張海霞,北京大學教授國際大學生iCAN創新創業大賽發起人、主席北京大學信息科學技術學院教授全球華人微納米分子系統學會秘書長IEEE NTC 北京分會主席。")); teachers.add(new Teacher("陳江", R.drawable.cj, "陳江,北京大學信息科學技術學院副教授,高等學校電路和信號系統教學與教材研究會常務理事,中國通信理論與信號處理委員會委員。")); teachers.add(new Teacher("葉蔚", R.drawable.yw, "葉蔚,北京大學軟件工程國家工程研究中心副研究員,創辦了技術學習服務平臺天碼營(http://tianmaying.com)與軟件開發協同工具Onboard(http://onboard.cn)。")); return teachers; } // 以下都是訪問內部屬性的getter和setter public String getName() { return name; } public void setName(String name) { this.name = name; } public int getImageId() { return imageId; } public void setImageId(int imageId) { this.imageId = imageId; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; }}改進列表
創建新的布局
為了在列表的一行中,同時顯示老師的圖片和名稱,我們需要創建自定義的布局。
選中res/layout
目錄,【右鍵】->【New】->【Layout Resource File】,在彈出對話框中,輸入如下信息:

File Name為布局文件的名稱,我們輸入teacher_item。其他的輸入框使用默認信息即可。其中Root Element表示布局的方式,這里我們無需修改,使用默認的LinearLayout
,即視圖組件通過線性的方式來進行布局。
新的布局中,我們需要在左側顯示一張圖片,右側顯示老師姓名,因此我們往預覽區拖入一個ImageView
和TextView
,然后切換到Text視圖進行編輯,最終的布局文件如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="50dp" android:layout_height="50dp" android:layout_marginBottom="5dp" android:layout_marginTop="5dp" android:id="@+id/teacher_small_imageView" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="New Text" android:id="@+id/teacher_name_textView" android:layout_gravity="center_vertical" /></LinearLayout>注意我們將根元素<LinearLayout>
的android:orientation
改為了horizontal
,因為我們希望老師的圖片和老師的姓名水平線性布局。
ImageView命名為teacher_small_imageView
,長寬都為50dp,與上下的間距為5dp。dp是一種長度的單位,也有其他類型的單位,dp能夠比較好的兼容各種分辨率的設備。
TextView命名為teacher_name_textView
,長寬為根據內容自適應,與左側圖片間距為10dp,垂直居中。
創建自定義的ArrayAdapter
我們創建一個自定義的ArrayAdapter。我們創建一個命名為TeacherAdapter
的類,讓其繼承ArrayAdapter<Teacher>
,同時提供一個構造函數。
package com.zhihuishu.innovationcourse;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;import java.util.zip.Inflater;public class TeacherAdapter extends ArrayAdapter<Teacher> { public TeacherAdapter(Context context, int resource, List<Teacher> objects) { super(context, resource, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { // 獲取老師的數據 Teacher teacher = getItem(position); // 創建布局 View oneTeacherView = LayoutInflater.from(getContext()).inflate(R.layout.teacher_item, parent, false); // 獲取ImageView和TextView ImageView imageView = (ImageView) oneTeacherView.findViewById(R.id.teacher_small_imageView); TextView textView = (TextView) oneTeacherView.findViewById(R.id.teacher_name_textView); // 根據老師數據設置ImageView和TextView的展現 imageView.setImageResource(teacher.getImageId()); textView.setText(teacher.getName()); return oneTeacherView; }}這段代碼的主要功能就是,提供了一個getView()
方法的重載實現,我們通過重載這個方法就能夠讓listView根據我們的要求來生成每一個列表元素了。而這個方法做了四件事情:
獲取老師的數據,getItem(position)
會把poistion
位置的Teacher
對象返回給你,這件事情Adapter會幫你處理好,你只管調用就好了。創建布局,View oneTeacherView = LayoutInflater.from(getContext()).inflate(R.layout.teacher_item, parent, false);
這條語句大家照著寫就好了,你只需要知道這是根據Layout文件生成一個布局(布局也是一個View的子類)。獲取ImageView和TextView最后根據老師數據設置ImageView和TextView的展現在MainActivity.java
中的代碼也需要做相應的修改,此時我們要創建一個TeacherAdapter
的對象,并將其設置為listView
的Adapter。
public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TeacherAdapter teacherAdapter = new TeacherAdapter(this, R.layout.teacher_item, Teacher.getAllTeachers()); ListView listView = (ListView) findViewById(R.id.teacher_listView); listView.setAdapter(teacherAdapter); } ...}運行效果
此時已經可以看到更好看的老師列表界面了:
創建第二個Activity
一切進展順利,我們已經了解如何創建Activity中的視圖,如何通過Adapter給視圖傳遞數據。接下來我們要做一個功能,當點擊列表中的每一項時,會進入第二個Activity,顯示老師的大圖片以及詳細介紹。
所以我們先來創建第二個Activity吧。
選中java
目錄下的com.zhihuishu.innovationcourse
包,【右鍵】->【New】->【Activity】->【Blank Activity】,在彈出的窗口中輸入Activity名稱TeacherDetailActivity,點擊【Finish】。

類似于teacher_item.xml
布局的編輯,我們往預覽區中拖入一個ImageView
和TextView
,然后在Text視圖中進行布局的編輯。最終的布局配置如下:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.zhihuishu.innovationcourse.TeacherDetailActivity"> <ImageView android:layout_width="300dp" android:layout_height="300dp" android:id="@+id/teacher_large_imageView" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Text" android:id="@+id/teacher_desc_textView" android:layout_below="@+id/teacher_large_imageView" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" /></RelativeLayout>很多屬性我們之前已經遇到過了。這里我們使用了另外一種布局RelativeLayout
,顧名思義,就是通過視圖元素的相對位置來進行布局。其中關鍵的一行代碼是android:layout_below="@+id/teacher_large_imageView"
,這表示teacher_large_imageView
在teacher_large_imageView
的下方。
實現行為:事件處理
這個Activity的布局已經創建好了,如何跳轉到這個Activity呢?這時我們需要識別出用戶的點擊行為,當用戶點擊發生時才能進行跳轉。
我們回到TeacherAdapter
的getView()
方法,在最后一條return
語句前加入:
oneTeacherView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 這里進行跳轉 } });這段代碼就是在返回oneTeacherView
之前,設置一個OnClick
點擊事件的監聽器,當事件發生的時候,就會執行public void onClick(View v)
內部的代碼。
Activity的跳轉:Intent
接下來我們就要進行真正的跳轉了, Intent
終于排上用場了,代碼如下:
oneTeacherView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 初始化一個準備跳轉到TeacherDetailActivity的Intent Intent intent = new Intent(getContext(), TeacherDetailActivity.class); // 準備跳轉 getContext().startActivity(intent); } });增加兩行代碼就能跳轉到第二個Activity了。但是運行起來之后,在第二個Activity中我們并沒有看到數據。所以讓我們來做最后一步吧,你馬上就要成功了。
在進行跳轉的時候,我們需要把老師的數據傳遞給TeacherDetailActivity
,并在TeacherDetailActivity
中進行適當的設置。
通過Intent傳遞參數
設置Intent的Extra數據
Intent
的putExtra
方法就是用來傳遞參數的,我們只需在初始化Intent
對象之后把老師的數據傳遞進去即可。
需要注意的一點是,為了訪問teacher
變量,需要在申明的時候加上final
修飾符。注意代碼中哪些地方發生了變化,完整的代碼如下:
package com.zhihuishu.innovationcourse;import android.content.Context;import android.content.Intent;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;public class TeacherAdapter extends ArrayAdapter<Teacher> { public TeacherAdapter(Context context, int resource, List<Teacher> objects) { super(context, resource, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { // 獲取老師的數據 final Teacher teacher = getItem(position); // 創建布局 View oneTeacherView = LayoutInflater.from(getContext()).inflate(R.layout.teacher_item, parent, false); // 獲取布局中的ImageView和TextView ImageView imageView = (ImageView) oneTeacherView.findViewById(R.id.teacher_small_imageView); TextView textView = (TextView) oneTeacherView.findViewById(R.id.teacher_name_textView); // 根據老師數據設置ImageView和TextView的展現 imageView.setImageResource(teacher.getImageId()); textView.setText(teacher.getName()); oneTeacherView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 初始化一個準備跳轉到TeacherDetailActivity的Intent Intent intent = new Intent(getContext(), TeacherDetailActivity.class); // 往Intent中傳入Teacher相關的數據,供TeacherDetailActivity使用 intent.putExtra("teacher_image", teacher.getImageId()); intent.putExtra("teacher_desc", teacher.getDesc()); // 初始化一個準備跳轉到TeacherDetailActivity的Intent getContext().startActivity(intent); } }); return oneTeacherView; }}根據Intent數據展示內容
最后我們修改TeacherDetailActivity
的onCreate()
方法,加入從Intent
獲取數據并設置視圖展現的代碼。
package com.zhihuishu.innovationcourse;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.widget.ImageView;import android.widget.TextView;public class TeacherDetailActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_teacher_detail); // 從Intent獲取數據 int imageId = getIntent().getIntExtra("teacher_name", 0); String desc = getIntent().getStringExtra("teacher_desc"); // 獲取特定的視圖 ImageView imageView = (ImageView) findViewById(R.id.teacher_large_imageView); TextView textView = (TextView) findViewById(R.id.teacher_desc_textView); // 根據數據設置視圖展現 imageView.setImageResource(imageId); textView.setText(desc); }}注意int imageId = getIntent().getIntExtra("teacher_image", 0);
語句中傳入的屬性名teacher_image
一定要寫對,和putExtra()
方法中的保持一致。通常我們是通過定義常量的方式來定義這樣的字符串名字,這里為了簡單處理我們用了硬編碼的方式。
好了,運行起來看看吧,跳轉沒有問題了,恭喜你,整個APP已經搞定了。
參考代碼要獲取本文的參考代碼,請訪問: http://tianmaying.com/tutorial/a-simple-sample-for-android-development/repo
|
新聞熱點
疑難解答