本教程介紹如何建立Android應用程序。它基於Android5.0(Lollipop)介紹Android Studio的用法。html
Android是基於Linux內核的操做系統。負責開發Android系統的項目被爲Android Open Source Project (AOSP) ,由谷歌領導。java
Android系統支持後臺處理,提供了豐富的用戶界面庫,使用的OpenGL標準支持2-D和3-D圖形,並容許訪問文件系統以及嵌入式SQLite數據庫。python
Android應用包含可見和不可見組件,並可重用其餘應用程序的組件。android
在Android中重用其餘應用組件即任務的(Task),好比調用圖片管理應用。事件流以下:c++
安卓平臺組件以下:程序員
應用 - Android開源項目包含幾個默認的應用程序,如瀏覽器,相機,圖庫,音樂,電話等。web
應用程序框架 - Android應用與Android系統高層交互API。數據庫
庫和運行時 - 應用程序框架和Dalvik運行時的經常使用功能的庫(如:圖形渲染,數據存儲,網頁瀏覽等)和運行Android應用的核心Java庫。編程
Linux內核 - 底層硬件的通訊層。數組
谷歌提供的Google Play是程序員能夠提供他們的Android應用給用戶的市場。客戶使用谷歌Play可購買和安裝應用程序。
Google Play還提供了更新的服務。若是程序員上傳本身的應用程序的新版本時,該服務將通知現有用戶有更新可用並容許他們來安裝更新。
Google Play提供服務和庫訪問,好比谷歌地圖和Android設備之間同步的服務。這些服務對舊版安卓也可用,不依賴安卓版本
Android Software Development Kit (Android SDK): 包含來建立,編譯和打包Android應用的工具。這些工具大部分基於命令行。主要基於Java編程語言,也涉及Python和c++等。
Android debug bridge (adb):能鏈接到虛擬或真實的Android設備以管理設備或調試應用。
Gradle和Android Gradle 插件:Android的工具使用Gradle做爲構建系統。 Android團隊提供了Gradle插件用於構建Android應用,Android項目的根目錄的build.gradle文件是輸入。好比:
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.4.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { jcenter() } }
不一樣版本的插件參見https://jcenter.bintray.com/com/android/tools/build/gradle/。
Android Studio基於IntelliJ IDE。Android工具爲Android特定文件提供了專門的編輯器。多數Android的配置文件都基於XML。編輯器能夠在XML表示和用於輸入數據的結構化UI之間進行切換。
安卓5.0的運行時爲Android RunTime (ART)。ART使用提早編譯。應用程序的部署時代碼翻譯成機器代碼。編譯代碼大30%的,但執行更快,只編譯一次,也會更省電。dex2oat工具編譯.dex文件爲可執行和連接格式(ELF文件Executable and Linkable Format)。該文件包含DEX代碼,編譯的本地代碼和元數據。保持.dex代碼容許現有的工具仍然能夠工做。ART的垃圾收集進行了優化,減小了應用凍結時間。
Android應用主要用Java編程語言。開發人員建立了Android特定的配置文件,並用Java寫應用邏輯。
Android的工具將這些應用程序文件打包成爲Android應用。在IDE部署時,整個Android應用程序被編譯,打包,部署並啓動。Java源文件是由Java編譯器轉換成Java類文件。
Android SDK的dx工具把Java類文件轉換到.dex(Dalvik的可執行文件)文件同時去除冗餘內容。所以,這些.dex文件的遠小於相應的類文件。
.dex文件和Android項目的資源文件,例如圖像和XML文件的,打包成一個apk文件(Android Package)文件。aapt (Android Asset Packaging Tool)完成此步驟。
而後adb能夠部署.apk到Android設備。
硬件建議,在2.6 GHz CPU,8 GB的內存。 SSD硬盤更佳。
Android SDK的是32位的,所以64位的Linux系統須要安裝包ia32-libs庫。好比Ubuntu:。
apt-get install ia32-libs
在Ubuntu 13.04還必須安裝OpenGL支持。
# install OpenGL support # sudo apt-get install libgl1-mesa-dev
下載http://developer.android.com/sdk/installing/studio.html
Windows安裝很簡單,只需啓動你下載的.exe文件。在Max OSX拖放Android Studio到應用程序文件夾。
在Linux上解壓縮下載的ZIP文件到一個合適的位置,在android-studio/bin/中執行studio.sh。
Tools → Android → SDK Manager 或下面的快捷方式:
支持庫能夠在較低的Android版本提供更高的Android版本的功能。
在Android SDK管理器中選擇Extras並安裝Android支持庫。 Android的支持庫爲Eclipse ADT工具使用。
Android目前有幾個版本的庫中,V4,V7和V13版本對應安卓的各個API。高版本支持庫的Android設備也須要較低的版本一塊兒使用。例如,支持庫V7須要V4庫。
在谷歌開發團隊着力於Android Studio的發展,因此這是目前Android應用程序最好的發展環境。目前的ADT工具使用特殊的Eclipse構建系統,而不是新的Gradle構建系統,構建時可能產生不一致,另外也不支持AAR文件。
Android的工具包含Android設備模擬器(emulator)。該模擬器可用於運行Android虛擬設備(AVD Android Virtual Device),它模擬真正的Android手機。
AVD讓你不訪問真機的狀況下對不一樣的Android版本和配置Android應用進行測試。即便你有真正的Android設備,也應該熟悉AVDS的建立和使用。
在建立AVD時定義爲虛擬設備的配置。這包括分辨率、Android的API版本和顯示密度。
您能夠定義多個有不一樣配置的AVD,並同時運行,一次測試不一樣的設備配置。
注意若是在啓動過程中止,AVD可能會損壞。舊機器上第一次啓動可能須要長達10分鐘的。通常須要1-3分鐘的啓動新的AVD。
你能夠用鼠標控制的圖形用戶界面。右側仿真器的菜單還能夠訪問手機的按鈕。
在Android設備安裝以前,Android應用程序都必須進行簽名。Eclipse使用debug key自動簽名。此調試證書有365天有效期。當證書過時後,刪除debug.keystore文件j就會從新生成。默認存儲位置在OS X和Linux是在~/.android/
,Windows XP:C:\Documents andSettings\[username]\.android\
中,在Windows Vista和Windows 7:C:\Users\[username]]\.android\
。快捷方式以下:
Shortcut | Description |
---|---|
Alt+Enter | Maximizes the emulator. |
Ctrl+F11 | Changes the orientation of the emulator from landscape to portrait and vice versa. |
F8 | Turns the network on and off |
AVD能夠模擬Android設備或谷歌的設備。前者包含Android開源項目的程序。後者AVD包含附加谷歌特有的代碼,可使用新谷歌地圖API或新的位置服務。
快照或主機GPU功能只能選擇一個。前者第二次啓動啓動速度很是快。後者渲染速度更快。
AVD能夠運行基於ARM的CPU體系結構或基於英特爾CPI。後者在Intel / AMD的硬件快,由於模擬器不須要翻譯ARM CPU指令到Intel / AMD的CPU。
Intel image API(不是每一個版本都有)
能夠經過Android SDK管理器進行安裝,在Android Studio建立設備時自動安裝。經過包詳細信息可進行配置。
驅動安裝:
下載以後Android安裝目錄下的extras/intel
文件夾包含驅動程序。你須要經過運行啓動.exe文件來安裝驅動程序。
下載後,您能夠建立基於英特爾模擬器新的AVD。模擬器啓動速度不變,但Android應用程序的執行過程更快。
Linux須要一個更復雜的設置,參見https://software.intel.com/en-us/android/articles/intel-hardware-accelerated-execution-manager。
在設備上打開USB調試(Settings → Development Options)可使用真機,Windows一般須要安裝驅動程序,參見http://developer.android.com/guide/developing/device.html。
注意Android版本的設備須要知足Android應用程序的最低版本。
若是鏈接了多臺設備,你能夠選擇。若是隻有一個設備鏈接時,應用程序被自動部署在該設備上。
另外特別推薦仿真器:Genymotion https://www.genymotion.com/
啓動頁面點擊"Start a new Android Studio project"啓動新的Android Studio項目。另外,您能夠從菜單File → New Project進入。
Property | Value |
---|---|
Application name | Test App |
Company Domain | vogella.com |
Package Name | com.vogella.testapp |
API (Minimum, Target, Compile with) | Latest |
Template | Empty Activity |
選擇「Empty Activity」, 效果以下:
由經過Tools → Android→ AVD Manager管理器定義新的Android虛擬設備(AVD)。
啓動模擬器,經過Run → Run 'app' 啓動應用:
Android應用是可獨立於其餘Android應用啓動和使用安裝單位。Android應用由Android組件,Java源文件和資源文件組成。
基於Intent對象的任務描述,Android應用組件能夠鏈接到其餘Android應用的組件。這樣能夠建立跨應用的任務。
Android的軟件組件:Application、Activities、Services、Broadcast receivers (short: receivers)、Content providers (short: providers)。
Android應用有一個Application類
,它最早啓動並最後關閉。若是沒有明確的制定,Android會建立默認Application對象。
activity是Android應用的可視化表示。 Android應用能夠有多個activity。Activity使用 UI工具(Widget)和佈局管理器及fragment來建立用戶界面並與用戶交互。這兩個因素在接下來的章節中介紹。
廣播接收器(Broadcast receiver)能夠註冊爲監聽系統消息和intent。若是指定的事件發生接收器獲得Android系統的通知。例如能夠註冊一個Android系統完成啓動事件的接收器。
服務執行任務,而無需提供用戶界面。它們能夠與其它Android組件通訊,例如,經由廣播接收器通知用戶。
內容提供者(content provider)定義了應用數據的結構化的接口。provider可用於在應用訪問的數據,但也可用於與其餘應用共享數據。SQLite數據庫常常和provider一塊兒使用。 SQLite數據庫存儲數據,provider訪問數據。
類android.content.Context(上下文)的實例鏈接應用和Android系統,也能夠訪問項目資源和應用程序中全局信息。例如,您能夠查看當前設備顯示的大小。上下文類還能夠訪問Android的服務,例如,報警管理器觸發基於時間的事件。Activity和service擴展Context
類。
Activity:前面已經介紹。
Fragment:片斷是Activity內運行的context組件。片斷封裝的應用代碼,使得它更容易重用,並支持不一樣大小的設備。
下圖的MainActivity在較小的屏幕,僅顯示一個片斷,並容許用戶導航到另外一片斷。在寬屏幕當即顯示這兩個片斷。
視圖(View)是用戶界面工具,例如按鈕或文本域。View有可用於配置它們的外觀和行爲的屬性。ViewGroup中負責安排其餘View,也稱爲佈局管理器(layout manager)。佈局管理器的基類是android.view.ViewGroup類(基類android.view.View類)。佈局管理器能夠嵌套建立複雜的佈局。
主屏幕和鎖屏小工具:Widget是主要用於Android主屏幕上的交互式組件。它們一般顯示某些種類型數據,並容許用戶執行。例如Widget能夠顯示新電子郵件的簡短摘要,而且若是用戶選擇了電子郵件,能夠開啓對應的電子郵件應用。
爲了不和view(這也稱爲widget)混淆,本文指明是主屏widget。
動態壁紙爲Android主屏幕建立背景。
組件和Android應的設置在AndroidManifest.xml文件描述。此文件被稱爲manifest文件或manifest。manifest還指定應用的其餘元數據,例如icon和應用程序的版本號。Android系統安裝的應用時讀取該文件。而Android系統評估這個配置文件,並肯定應用的權限。
應用全部活動,服務和內容提供商組件必須在此文件中靜態聲明。廣播接收器能夠靜態地在manifest文件生命或在運行時動態使用。
Android manifest文件還必須包含應用所需的權限。例如網絡訪問。下面是簡單的manifest文件實例:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.rssreader" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:name="RssApplication" android:allowBackup="false" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="RssfeedActivity" android:label="@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".DetailActivity" android:label="Details" > </activity> <activity android:name="MyPreferenceActivity" > </activity> <service android:name="RssDownloadService" > </service> </application> </manifest>
package
屬性定義該文件中Java對象引用的基礎包。若是Java對象在不一樣的包,必須包的全名聲明。
Google Play要求每一個Android應用都使用本身獨特的包名。一般使用反向域名,以免與其餘Android應用衝突。
android:versionName
and android:versionCode
指定應用的版本。 versionName對
用戶可見,而且能夠是任意字符串。android:versionCode
必須是整數。而Android市場基於android:versionCode
肯定是否安裝執行更新。您一般以從1開始遞加。
<application>
部分容許定義元數據和選擇性定義一個explicit應用類。是宣佈Android組件的容器。
<activity>
標籤訂義activity組件
。 name屬性指向類。
intent filter部分Android運行時該activity註冊爲應用可能的入口點,並在Android系統的launcher可見。(android:name="android.intent.action.MAIN"
) 代表能夠啓動,category android:name="android.intent.category.LAUNCHER"
代表添加
activity到launcher
。
@string/app_name
指向資源文件,包含應用名稱。資源文件的使用很容易地對不一樣的設備提供不一樣的資源(例如,字符串,顏色,圖標),容易地翻譯應用。
相似<activity>
,您可使用service,receiver和provider生命其餘Android組件。
Value | Description |
---|---|
minSdkVersion | Define the minimum version of Android your application works on. This attribute is used as a filter in Google Play, i.e., a user cannot install your application on a device with a lower API level than specified in this attribute. |
targetSdkVersion | Specifies the version on which you tested and developed. If it is not equal to the API version of the Android device, the Android system might apply forward- or backward-compatibility changes. It is good practice to always set this to the latest Android API version to take advantages of changes in the latest Android improvements. |
uses-configuration
能夠指明輸入方式.
例如硬鍵盤。
<uses-configuration android:reqHardKeyboard="true"/>
uses-feature
容許您指定硬件配置。例如要求具備攝像頭。
<uses-feature android:name="android.hardware.camera" />
installLocation
指定安裝位置如
果能夠在外部存儲安裝。使用auto
或preferExternal
容許。實際上這個選項不多使用,如安裝在外部存儲,一旦設備被鏈接到計算機做爲USB存儲應用就被中止。
更多資料:http://developer.android.com/intl/zh-cn/guide/topics/manifest/manifest-intro.html
Android能夠建立如圖像和XML配置文件靜態資源。資源文件必須放在應用/res目錄中預約義的子文件夾。
Resource | Folder | Description |
---|---|---|
Drawables | /res/drawables |
Images (e.g., png or jpeg files) or XML files which describe a Drawable object. Since Android 5.0 you can also use vector drawables which scale automatically with the density of the Android device. |
Simple Values | /res/values |
Used to define strings, colors, dimensions, styles and static arrays of strings or integers via XML files. By convention each type is stored in a separate file, e.g., strings are defined in the res/values/strings.xml file. |
Layouts | /res/layout |
XML files with layout descriptions are used to define the user interface for Activities and fragments. |
Styles and Themes | /res/values |
Files which define the appearance of your Android application. |
Animations | /res/animator |
Defines animations in XML for the animation API which allows to animate arbitrary properties of objects over time. |
Raw data | /res/raw |
Arbitrary files saved in their raw form. You access them via an InputStream object. |
Menus | /res/menu |
Defines the actions which can be used in the toolbar of the application. |
下面/res/values/
,它定義了一些字符串常量,字符串數組,顏色和尺寸。values.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Test</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string-array name="operationsystems"> <item>Ubuntu</item> <item>Android</item> <item>Microsoft Windows</item> </string-array> <color name="red">#ffff0000</color> <dimen name="mymargin">10dp</dimen> </resources>
附加限定符到文件夾名稱指示相關的資源應該用於特殊的配置。例如能夠指定佈局文件僅適用於特定的屏幕尺寸。
Android構建系統爲每一個資源分配一個ID。在Android項目gen目錄
中包含R.java引用文件,其中包含這些生成的值。這些引用是靜態的整數值。
添加新的資源文件,相應的引用會自動在R.java文件中建立。不須要手工修改。Android系統提供的方法經過這些ID來訪問相應的資源文件。
例如,在源代碼中訪問R.string.yourString ID的字符串,你會使用的上下文類定義getString(R.string.yourString)
方法。
而Android SDK使用駝峯表示法大部分的ID,例如,buttonRefresh的。
系統資源在Android命名空間。例如,android.R.string.cancel取消操做定義的平臺字符串。
Android的activity使用views (widgets)和fragment定義其用戶界面。該用戶界面可在/res/layout
文件夾或Java代碼中定義。您也能夠混合使用這兩種方法。經過XML佈局文件定義的佈局是首選方法,可分隔佈局定義和編程邏輯。它也容許爲不一樣的設備定義不一樣的佈局的。
佈局資源文件被稱爲layout。佈局指定ViewGroup和View,好比:
<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=".MainActivity" > <TextView android:id="@+id/mytext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </RelativeLayout>
setContentView()
方法可分配佈局給activity,好比:
package com.vogella.android.first; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
若是須要經過Java代碼訪問view,須要經過android:id給
視圖惟一ID。好比:
<Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Show Preferences" > </Button>
在/res/values/
ids.xml中定義id是好方法:
<?xml version="1.0" encoding="utf-8"?> <resources> <item name="button1" type="id"/> </resources>
在佈局文件可使用ID。
<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" tools:context=".MainActivity" > <Button android:id="@id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:layout_marginRight="27dp" android:text="Button" /> </RelativeLayout>
注意:若是要在獨立文件中定義id,首先須要刪除在佈局文件中的@+id條目,不然會獲得文件已經建立了的錯誤信息。
計算layout和畫view是資源密集型操做。佈局要可能簡單。例如應該避免嵌套佈局管理器太深。
Android中的view表明widget,例如按鈕或佈局管理器。 Android SDK提供的標準views(widgets,例如,經過按鈕、TextView、EditText類。它還包括複雜的widget,例如ListView。
在Android的全部視圖擴展android.view.View類。這個類是比較大(超過1.8萬行的代碼),併爲子類提供了大量的的基本功能。
view的主包是的基類是android.view命名空間的一部分,android.widget爲Android平臺的默認widget。
佈局管理器(layout manager)是ViewGroup的子類,負責自己及其子視圖的佈局。 Android支持不一樣的默認佈局管理器。Android 4.0的最相關的佈局管理器是的LinearLayout、FrameLayout、RelativeLayout的和GridLayout
。AbsoluteLayout已不建議使用,TableLayout能夠更有效地經過GridLayout來實現。
全部佈局容許開發者定義的屬性。孩子也能夠定義可被其父親佈局進行評估的屬性。孩子能夠經過如下屬性指定他們但願的寬度和高度。
ttribute | Description |
---|---|
android:layout_width |
Defines the width of the widget. |
android:layout_height |
Defines the height of the widget. |
Widget可使用固定尺寸,例如dp
定義爲100dp。雖然dp
固定大小,可根據設備配置擴展。
match_parent
告訴應用最大限度地在父親最大化widget。wrap_content儘可能少使用以保證正確渲染。
窗口小部件正確呈現的最低金額。這些元素的效果表如今如下的圖形。
FrameLayout是在子元素的頂部互相畫。有漂亮的視覺效果。好比Gmail:
LinearLayout中把全部子元素放入行或者列(基於android:orientation肯定)
。可能的屬性爲horizontal或
vertical,默認爲
horizontal。
horizontal效果以下:
Vertical效果以下:
LinearLayout中能夠嵌套以實現更復雜的佈局。LinearLayout支持經過android:layout_weight
分配權重。
RelativeLayout的用於複雜的佈局。好比要居中一個組件,設置android:layout_centerInParent爲true
。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ProgressBar android:id="@+id/progressBar1" style="?android:attr/progressBarStyleLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /> </RelativeLayout>
Android 4.0引入了網格佈局(GridLayout)
。相似表格,繪圖區域爲行,列和單元格。
你能夠指定每一個視圖要多少列,放置的行和列。若是沒有指定,GridLayout
使用默認值,例如:一列一行,視圖的位置取決於聲明的順序。好比:
下面的佈局文件定義了使用GridLayout的佈局。
<?xml version="1.0" encoding="utf-8"?> <GridLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/GridLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:columnCount="4" android:useDefaultMargins="true" > <TextView android:layout_column="0" android:layout_columnSpan="3" android:layout_gravity="center_horizontal" android:layout_marginTop="40dp" android:layout_row="0" android:text="User Credentials" android:textSize="32dip" /> <TextView android:layout_column="0" android:layout_gravity="right" android:layout_row="1" android:text="User Name: " > </TextView> <EditText android:id="@+id/input1" android:layout_column="1" android:layout_columnSpan="2" android:layout_row="1" android:ems="10" /> <TextView android:layout_column="0" android:layout_gravity="right" android:layout_row="2" android:text="Password: " > </TextView> <EditText android:id="@+id/input2" android:layout_column="1" android:layout_columnSpan="2" android:layout_row="2" android:inputType="textPassword" android:ems="8" /> <Button android:id="@+id/button1" android:layout_column="2" android:layout_row="3" android:text="Login" /> </GridLayout>
這將建立相似下面的截圖的用戶界面。
ScrollView
或HorizontalScrollView類不是佈局管理器,但要提供可視性,即便在不適合屏幕上。滾動視圖能夠包含一個視圖,例如含有多個視圖的佈局管理器。 若是子view太大,滾動視圖容許滾動的內容。
代碼實例:
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" android:orientation="vertical" > <TextView android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="8dip" android:paddingRight="8dip" android:paddingTop="8dip" android:text="This is a header" android:textAppearance="?android:attr/textAppearanceLarge" > </TextView> </ScrollView>
android:fillViewport="true"
屬性保證了滾動視圖設置爲全屏, 哪怕元素比屏幕小。
繼續前面的例子:修改res/layout/
activity_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" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:showIn="@layout/activity_main" tools:context=".MainActivity"> <TextView android:text="Hello World!" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
修改後的文件:
<?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=".MainActivity" > <EditText android:id="@+id/main_input" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentStart="true" android:layout_alignParentEnd="true" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/main_input" android:layout_below="@+id/main_input" android:layout_marginTop="31dp" android:onClick="onClick" android:text="Start" /> </RelativeLayout>
MainActivity.java
原文件:
package com.vogella.testapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
使用該文件點擊"START"按鈕,會由於沒有實現onClick
而發生崩潰。
下面增長onClick:
package com.vogella.testapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Toast; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void onClick (View view) { Toast.makeText(this, "Button 1 pressed", Toast.LENGTH_LONG).show(); } }
如今就有彈出信息顯示。下面修改爲顯示編輯框的內容。
package com.vogella.testapp; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // you may have here an onCreateOptionsMenu method // this method is not required for this exercise // therefore you can delete it public void onClick(View view) { EditText input = (EditText) findViewById(R.id.main_input); String string = input.getText().toString(); Toast.makeText(this, string, Toast.LENGTH_LONG).show(); } }
上面代碼由於原代碼的log部分有錯而刪除,不影響主體功能。
繼續修改activity_main.xml,添加radio組和radio按鈕:
ID | View |
---|---|
orientation | Radio Group |
horizontal | First radio button |
vertical | Second radio button |
<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=".MainActivity" > <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/main_input" android:layout_alignParentTop="true" android:layout_alignParentStart="true" android:layout_alignParentEnd="true" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Start" android:id="@+id/button" android:layout_below="@id/main_input" android:layout_alignParentStart="true" android:onClick="onClick"/> <RadioGroup android:id="@+id/orientation" android:layout_below="@id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp"> <RadioButton android:id="@+id/horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Horizontal" > </RadioButton> <RadioButton android:id="@+id/vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="Vertical" > </RadioButton> </RadioGroup> </RelativeLayout>
如今佈局以下:
更改onCreate()
。使用findViewById()
方法來查找您的佈局中的RadioGroup。
基於當前選擇單選按鈕實現監聽器,選擇以後改變方向爲橫向或縱向。
MainActivity.java代碼以下:
package com.vogella.testapp; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.RadioGroup; import android.widget.Toast; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RadioGroup group1 = (RadioGroup) findViewById(R.id.orientation); group1.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.horizontal: group.setOrientation(LinearLayout.HORIZONTAL); break; case R.id.vertical: group.setOrientation(LinearLayout.VERTICAL); break; } } }); } // you may have here an onCreateOptionsMenu method // this method is not required for this exercise // therefore you can delete it public void onClick(View view) { EditText input = (EditText) findViewById(R.id.main_input); String string = input.getText().toString(); Toast.makeText(this, string, Toast.LENGTH_LONG).show(); } }
下載地址:https://play.google.com/store/apps/details?id=de.vogella.android.temperature
也能夠在Google Play掃描二維碼:
建立工程:
Property | Value |
---|---|
Application Name | Temperature Converter |
Package name | com.vogella.android.temperatureconverter |
API (Minimum, Target, Compile with) | Latest |
Template | Empty Activity |
Activity | MainActivity |
Layout | activity_main |
在res/values/strings.xml
建立屬性
Type | Name | Value |
---|---|---|
Color | myColor | #F5F5F5 |
String | celsius | to Celsius |
String | fahrenheit | to Fahrenheit |
String | calc | Calculate |
修改後內容以下:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Temperature Converter</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <color name="myColor">#F5F5F5</color> <string name="celsius">to Celsius</string> <string name="fahrenheit">to Fahrenheit</string> <string name="calc">Calculate</string> </resources>
修改佈局res/layout/activity_main.xml
內容以下:
<?xml version="1.0" encoding="utf-8"?> <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" 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=".MainActivity" android:background="@color/myColor"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/inputValue" android:inputType="numberSigned|numberDecimal"/> <RadioGroup android:id="@+id/radioGroup1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignStart="@+id/editText1" android:layout_below="@+id/editText1"> <RadioButton android:id="@+id/radio0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="@string/celsius" /> <RadioButton android:id="@+id/radio1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/fahrenheit" /> </RadioGroup> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignStart="@+id/radioGroup1" android:layout_below="@+id/radioGroup1" android:layout_marginTop="22dp" android:text="@string/calc" android:onClick="onClick"/> </LinearLayout>
建立ConverterUtil類用於轉換溫度:
com.vogella.android.temperatureconverter; { convertFahrenheitToCelsius(fahrenheit) { ((fahrenheit - ) * / ); } convertCelsiusToFahrenheit(celsius) { ((celsius * ) / ) + ; } }
修改MainActivity.java
原文件:
package com.vogella.android.temperatureconverter; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
修改後:
package com.vogella.android.temperatureconverter; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.RadioButton; import android.widget.Toast; public class MainActivity extends Activity { private EditText text; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (EditText) findViewById(R.id.inputValue); } // this method is called at button click because we assigned the name to the // "OnClick" property of the button public void onClick(View view) { switch (view.getId()) { case R.id.button1: RadioButton celsiusButton = (RadioButton) findViewById(R.id.radio0); RadioButton fahrenheitButton = (RadioButton) findViewById(R.id.radio1); if (text.getText().length() == 0) { Toast.makeText(this, "Please enter a valid number", Toast.LENGTH_LONG).show(); return; } float inputValue = Float.parseFloat(text.getText().toString()); if (celsiusButton.isChecked()) { text.setText(String .valueOf(ConverterUtil.convertFahrenheitToCelsius(inputValue))); celsiusButton.setChecked(false); fahrenheitButton.setChecked(true); } else { text.setText(String .valueOf(ConverterUtil.convertCelsiusToFahrenheit(inputValue))); fahrenheitButton.setChecked(false); celsiusButton.setChecked(true); } break; } } }
運行:
未完待續,參考資料: http://www.vogella.com/tutorials/Android/article.html
微博 http://weibo.com/cizhenshi 做者博客:http://www.cnblogs.com/pythontesting/ python測試開發精華羣 291184506 PythonJava單元白盒測試 144081101