Android应用开发-快速入门
內(nèi)容摘要
- 了解Android 操作系統(tǒng)
- 搭建Android 開(kāi)發(fā)工具
- 使用Android 模擬器
- 案例-電話(huà)撥號(hào)器/短信發(fā)送器
- 掌握點(diǎn)擊事件的四種實(shí)現(xiàn)方式
- 掌握Android 常見(jiàn)布局
- 了解Android 中的長(zhǎng)度單位
1. 手機(jī)制式
手機(jī)的發(fā)展根據(jù)通信技術(shù)大致可以劃分為4 個(gè)時(shí)代(G:Generation 的縮寫(xiě))
第一代模擬制式手機(jī)(1G):1G就是大哥大,手機(jī)類(lèi)似于簡(jiǎn)單的無(wú)線(xiàn)電雙工電臺(tái),通話(huà)是鎖定在一定頻率,所以使用可調(diào)頻電臺(tái)就可以竊聽(tīng)通話(huà)
第二代GSM、CDMA等數(shù)字手機(jī)(2G):手機(jī)使用PHS,GSM或者CDMA這些十分成熟的標(biāo)準(zhǔn),具有穩(wěn)定的通話(huà)質(zhì)量和合適的待機(jī)時(shí)間,支持彩信業(yè)務(wù)的GPRS和上網(wǎng)業(yè)務(wù)的WAP服務(wù),以及各式各樣的Java程序等
第三代移動(dòng)通信技術(shù)(3G):3G,是英文3rd Generation的縮寫(xiě),指第三代移動(dòng)通信技術(shù)。指將無(wú)線(xiàn)通信與國(guó)際互聯(lián)網(wǎng)等多媒體通信結(jié)合的新一代移動(dòng)通信系統(tǒng)。它能夠處理圖像、音樂(lè)、視頻流等多種媒體形式,提供包括網(wǎng)頁(yè)瀏覽、電話(huà)會(huì)議、電子商務(wù)等多種信息服務(wù)
第四代移動(dòng)電話(huà)行動(dòng)通信(4G):4G。該技術(shù)包括TD-LTE和FDD-LTE兩種制式。4G是集3G與WLAN于一體,并能夠傳輸高質(zhì)量視頻圖像,它的圖像傳輸質(zhì)量與高清晰度電視不相上下。4G系統(tǒng)能夠以100Mbps的速度下載,比目前的撥號(hào)上網(wǎng)快200倍,并能夠滿(mǎn)足幾乎所有用戶(hù)對(duì)于無(wú)線(xiàn)服務(wù)的要求。此外,4G可以在DSL和有限電視調(diào)制解調(diào)器沒(méi)有覆蓋的地方部署,然后再擴(kuò)展到整個(gè)地區(qū)
1G制式:徹底退出歷史舞臺(tái)……
2G/3G/4G的區(qū)別:網(wǎng)速的區(qū)別。
2G:打個(gè)電話(huà)給你:“我租了一張蒼老師的VCD,一起來(lái)看”。
3G:發(fā)個(gè)消息給你:“種子發(fā)你郵箱了,注意查收,請(qǐng)叫我雷鋒”。
4G:發(fā)個(gè)地址給你:“在線(xiàn)看,高清的,還能邊看邊吐槽”。
2G 撥號(hào)上網(wǎng),帶寬12.2k每用戶(hù)。
3G 寬帶上網(wǎng),帶寬384k~2M每用戶(hù)。
4G 光纖到戶(hù),帶寬可以達(dá)到100M每用戶(hù)。
1.1 買(mǎi)手機(jī)注意網(wǎng)絡(luò)制式
- 2G制式:
- GSM:移動(dòng)/聯(lián)通
- CDMA:電信
- 3G制式
- WCDMA:聯(lián)通
- TD-SCDMA:移動(dòng)
- CDMA 2000:電信
- 4G制式
- FDD-LTE:電信/聯(lián)通
- TD-LTE(3個(gè)版本,對(duì)應(yīng)三大運(yùn)營(yíng)商,互不兼容):移動(dòng)/電信/聯(lián)通
2. Android簡(jiǎn)單歷史
2.1 安卓之父:安迪·魯賓
2003年10月,安迪·魯賓牽頭創(chuàng)建了一家公司,名為Android,開(kāi)始開(kāi)發(fā)一款針對(duì)手機(jī)端的操作系統(tǒng)。
2005年8月,谷歌低調(diào)收購(gòu)了這家公司及其團(tuán)隊(duì),安迪·魯賓成為Google公司工程部副總裁,繼續(xù)負(fù)責(zé)Android項(xiàng)目。
2007年11月,谷歌公司正式向外界展示了這款名為Android的操作系統(tǒng),并宣布建立一個(gè)全球性的聯(lián)盟組織,該組織由34家手機(jī)制造商、軟件開(kāi)發(fā)商、電信運(yùn)營(yíng)商以及芯片制造商共同組成,他們共同搭建起了Android系統(tǒng)最早的生態(tài)圈。
2011年,Android在全球的市場(chǎng)份額首次超過(guò)塞班系統(tǒng),躍居第一,目前的主要競(jìng)爭(zhēng)對(duì)手是iOS。
2.2 Android進(jìn)化史
- 2008 年9 月23 日Android 1.0 發(fā)布,代號(hào)Bender(發(fā)條機(jī)器人),這也是Android 系統(tǒng)最早的版本
- 2009 年9 月15 日Android 1.6 發(fā)布,代號(hào)Donut(甜甜圈)該版本首次支持了CDMA 網(wǎng)絡(luò)
- 2009 年11 月Android 2.0 發(fā)布,代號(hào)Eclair(松餅)無(wú)論從哪個(gè)方面說(shuō),它都是Android 發(fā)展歷史上第二個(gè)重要的里程碑時(shí)刻(第一個(gè)是Android1.5)
- 2010 年5 月20 日Android 2.2 發(fā)布,代號(hào)Froyo(凍酸奶)為Android 添加了很多企業(yè)級(jí)功能
- 2011 年10 月19 日Android 4.0 發(fā)布,代號(hào)Ice Cream Sandwich(冰激凌三明治)是Android 發(fā)展歷史上最重大的一次升級(jí)
- 2012 年6 月28 日Android 4.1 發(fā)布,代號(hào)Jelly Bean(果凍豆)是谷歌繼蜂巢之后,一次全新的平板策略嘗試
- 2014 年10 月15 日Android 5.0 發(fā)布,代號(hào)Lollipop(棒棒糖),全新的UI 設(shè)計(jì),全新的操作系統(tǒng)
- 2015 年10 月6 日Android 6.0 發(fā)布,代號(hào)Marshmallow(棉花糖),這次的新版系統(tǒng)在UI 和交互上和Android 5.X 保持高度一致
- 2016年5月19日,谷歌在美國(guó)加州的山景城舉辦了 Google I/O 開(kāi)發(fā)者大會(huì)中發(fā)布。2016年6月,Android N正式命名為“牛軋?zhí)恰?/li>
3. Android體系結(jié)構(gòu)
Android 的系統(tǒng)架構(gòu)采用了分層的設(shè)計(jì)。從架構(gòu)圖看,Android 分為四層,從低層到高層分別是Linux 內(nèi)核層、系統(tǒng)運(yùn)行庫(kù)層、應(yīng)用程序框架層和應(yīng)用程序?qū)?/p>
3.1 LINUX KERNEL
Linux核心,Android系統(tǒng)是基于Linux系統(tǒng)修改過(guò)來(lái)的,Android底層都是Linux的東西,大多都是操作硬件的一些驅(qū)動(dòng),如Display Driver、Audio Drivers等,Linux 內(nèi)核也同時(shí)作為硬件和軟件棧之間的抽象層
3.2 LIBRARIES
用C語(yǔ)言編寫(xiě)的完成Android核心功能的一些類(lèi)庫(kù),這些庫(kù)能被Android 系統(tǒng)中不同的組件使用。它們通過(guò)Android 應(yīng)用程序框架為開(kāi)發(fā)者提供服務(wù)
- OpenGL|ES(圖形圖像引擎簡(jiǎn)化版)
- WebKit(瀏覽器內(nèi)核)
- SQLite(輕量級(jí)數(shù)據(jù)庫(kù))
- Surface Manager(界面管理器)
- Media Framework(多媒體框架)
- FreeType(字體類(lèi)庫(kù))
- SGL(另一個(gè)圖形圖像引擎)
- SSL(基于TCP的安全協(xié)議)
- libc(零散的類(lèi)庫(kù))
3.3 Android Runtime
- Core Libraries - 該核心庫(kù)提供了Java 編程語(yǔ)言核心庫(kù)的大多數(shù)功能
- Dalvik Virtual Machine
Android底層是Linux系統(tǒng),使用C、C++語(yǔ)言編寫(xiě)的,所以Android程序(Java語(yǔ)言編寫(xiě))要在Linux上運(yùn)行就需要虛擬機(jī),也就是DVM。每一個(gè)Android 應(yīng)用程序都在它自己的進(jìn)程中運(yùn)行,都擁有一個(gè)獨(dú)立的Dalvik 虛擬機(jī)實(shí)例。Dalvik 虛擬機(jī)依賴(lài)于linux 內(nèi)核的一些功能,比如線(xiàn)程機(jī)制和底層內(nèi)存管理機(jī)制
3.4 APPLICATION FRAMEWORK
應(yīng)用框架層,全部是用Java語(yǔ)言編寫(xiě)的,供開(kāi)發(fā)人員調(diào)用。Android 系統(tǒng)中的每個(gè)應(yīng)用都依賴(lài)于該框架提供的一系列服務(wù)和系統(tǒng),其中包括:
- 活動(dòng)管理器( Activity Manager) 用來(lái)管理應(yīng)用程序生命周期并提供常用的導(dǎo)航回退功能。
- 豐富而又可擴(kuò)展的視圖(Views),可以用來(lái)構(gòu)建應(yīng)用程序, 它包括列表(lists),網(wǎng)格(grids),文本框(textboxes),按鈕(buttons),甚至可嵌入的web 瀏覽器。
- 內(nèi)容提供器(Content Providers)使得應(yīng)用程序可以訪(fǎng)問(wèn)另一個(gè)應(yīng)用程序的數(shù)據(jù)(如聯(lián)系人數(shù)據(jù)庫(kù)), 或者共享它們自己的數(shù)據(jù)。
- 資源管理器(Resource Manager)提供非代碼資源的訪(fǎng)問(wèn),如本地字符串,圖形,和布局文件( layoutfiles )。
- 通知管理器(Notification Manager) 使得應(yīng)用程序可以在狀態(tài)欄中顯示自定義的提示信息。
3.5 APPLICATIONS
應(yīng)用層,我們安裝的所有應(yīng)用都屬于這一層,如,微信,植物大戰(zhàn)僵尸。該層不僅包括系統(tǒng)內(nèi)置的應(yīng)用也包括用戶(hù)自己安裝的應(yīng)用,比如email 客戶(hù)端,SMS短消息程序,日歷,地圖,瀏覽器,聯(lián)系人管理程序,QQ,微信,淘寶,美團(tuán)等,該層所有的應(yīng)用程序都是使用Java語(yǔ)言編寫(xiě)的
3.6 舉例:鬧鐘應(yīng)用
鬧鐘應(yīng)用的功能實(shí)際上就是定時(shí)播放音樂(lè)。鬧鐘應(yīng)用調(diào)用APPLICATION FRAMEWORK層的MediaPlayer,MeidaPlayer訪(fǎng)問(wèn)LIBRARIES層中的Media Framework,Media Framework再使用C語(yǔ)言操作Andio Drivers去播放音樂(lè)
4. Dalvik VM和JVM的比較
JavaSE 程序使用的虛擬機(jī)叫Java Virtual Machine,簡(jiǎn)稱(chēng)JVM,Android 應(yīng)用也使用Java 語(yǔ)言開(kāi)發(fā),但是使用的虛擬就是Dalvik Virtual Machine,簡(jiǎn)稱(chēng)DVM。
Dalvik 是Google 公司自己設(shè)計(jì)用于Android 平臺(tái)的Java 虛擬機(jī)。它執(zhí)行的是已轉(zhuǎn)換為.dex(即Dalvik Executable)格式的Java 應(yīng)用程序的運(yùn)行,.dex 格式是專(zhuān)為Dalvik 設(shè)計(jì)的一種壓縮格式,適合內(nèi)存和處理器速度有限的系統(tǒng)。
Dalvik 經(jīng)過(guò)優(yōu)化,允許在有限的內(nèi)存中同時(shí)運(yùn)行多個(gè)虛擬機(jī)的實(shí)例,并且每一個(gè)Dalvik 應(yīng)用作為一個(gè)獨(dú)立的Linux 進(jìn)程執(zhí)行。獨(dú)立的進(jìn)程可以防止在虛擬機(jī)崩潰的時(shí)候所有程序都被關(guān)閉。
DVM執(zhí)行的是.dex格式文件,JVM執(zhí)行的是.class格式文件。Android程序編譯完之后生成.class文件,然后,dex工具會(huì)把.class文件處理成.dex文件,然后把資源文件和.dex文件等打包成.apk文件,apk就是android package的意思。
4.1 DVM相比JVM運(yùn)行效率更高的原因
每個(gè)jar包中都會(huì)有很多的class文件,每個(gè)class文件都有一個(gè)Header,Header中保存了class文件的初始信息,如,生成該class的jdk版本。而在apk文件中的dex文件,只有一個(gè)Header,所有class文件的初始信息都保存在其中,效率更高
每個(gè)class文件中有常量、字節(jié)碼、方法、域等保存自己的對(duì)應(yīng)的信息。dex文件中把所有class文件中的常量放在常量池中,所有class文件中的字節(jié)碼放到一個(gè)字節(jié)碼常量池中,等等。雖然這樣打包慢一點(diǎn),但是讀取的時(shí)候會(huì)很快。
class文件存在很多的冗余信息,dex工具會(huì)去除冗余信息,并把所有的.class文件整合到.dex文件中,減少了I/O操作,提高了類(lèi)的查找速度。
4.2 Dalvik 和標(biāo)準(zhǔn)Java 虛擬機(jī)(JVM)主要差別
Dalvik 基于寄存器,而JVM 基于棧。基于寄存器的虛擬機(jī)對(duì)于編譯后變大的程序來(lái)說(shuō),在它們執(zhí)行的時(shí)候,花費(fèi)的時(shí)間更短。
Dalvik 和Java 運(yùn)行環(huán)境的區(qū)別:
- Dalvik 主要是完成對(duì)象生命周期管理,堆棧管理,線(xiàn)程管理,安全和異常管理,以及垃圾回收等重要功能
- Dalvik 負(fù)責(zé)進(jìn)程隔離和線(xiàn)程管理,每一個(gè)Android 應(yīng)用在底層都會(huì)對(duì)應(yīng)一個(gè)獨(dú)立的Dalvik 虛擬機(jī)實(shí)例,其代碼在虛擬機(jī)的解釋下得以執(zhí)行
- 不同于Java 虛擬機(jī)運(yùn)行Java 字節(jié)碼,Dalvik 虛擬機(jī)運(yùn)行的是其專(zhuān)有的文件格式Dex
- dex 文件格式可以減少整體文件尺寸,提高I/O 操作的類(lèi)查找速度
- odex 是為了在運(yùn)行過(guò)程中進(jìn)一步提高性能,對(duì)dex 文件的進(jìn)一步優(yōu)化
- 所有的Android 應(yīng)用的線(xiàn)程都對(duì)應(yīng)一個(gè)Linux 線(xiàn)程,虛擬機(jī)因而可以更多的依賴(lài)操作系統(tǒng)的線(xiàn)程調(diào)度和管理機(jī)制
- 有一個(gè)特殊的虛擬機(jī)進(jìn)程Zygote,他是虛擬機(jī)實(shí)例的孵化器。它在系統(tǒng)啟動(dòng)的時(shí)候就會(huì)產(chǎn)生,它會(huì)完成虛擬機(jī)的初始化,庫(kù)的加載,預(yù)制類(lèi)庫(kù)和初始化的操作。如果系統(tǒng)需要一個(gè)新的虛擬機(jī)實(shí)例,它會(huì)迅速?gòu)?fù)制自身,以最快的數(shù)據(jù)提供給系統(tǒng)。對(duì)于一些只讀的系統(tǒng)庫(kù),所有虛擬機(jī)實(shí)例都和Zygote 共享一塊內(nèi)存區(qū)域
- Dalvik 是由Dan Bornstein 編寫(xiě)的,名字來(lái)源于他的祖先曾經(jīng)居住過(guò)名叫Dalvík 的小漁村,村子位于冰島
4.3 Android的新虛擬機(jī)ART
- ART 模式是什么?
ART 模式英文全稱(chēng)為:Android runtime,谷歌從Android 4.4 系統(tǒng)開(kāi)始新增的一種應(yīng)用運(yùn)行模式,與傳統(tǒng)的Dalvik 模式不同,ART 模式可以實(shí)現(xiàn)更為流暢的Android 系統(tǒng)體驗(yàn)。
在4.4 系統(tǒng)之前,Android 系統(tǒng)在Linux 的底層下構(gòu)筑Dalvik 一層的虛擬機(jī),通過(guò)其可以更好適應(yīng)多樣的硬件架構(gòu),開(kāi)發(fā)者只需要按一套規(guī)則進(jìn)行應(yīng)用便可,無(wú)需因?yàn)椴煌挠布軜?gòu)而處理與底層的驅(qū)動(dòng)關(guān)系,從而大大提高開(kāi)發(fā)的效率,但因?yàn)閼?yīng)用均是運(yùn)行在Dalvik 虛擬機(jī)中,因此應(yīng)用程序每次運(yùn)行的時(shí)候,一部分代碼都需要重新進(jìn)行編譯,這過(guò)程需要消耗一定的時(shí)間和降低應(yīng)用的執(zhí)行效率,最明顯的便是拖延了應(yīng)用的啟動(dòng)時(shí)間和降低了運(yùn)行速度。
- ART 模式有什么作用?
ART 模式最大的作用就是提升了Android 系統(tǒng)流暢度,相比Dalvik 模式中出現(xiàn)的耗電快、占用內(nèi)存大、即使是旗艦機(jī)用久了也會(huì)卡頓嚴(yán)重等現(xiàn)象,ART 模式中這種問(wèn)題得到了很好的解決,通過(guò)在安裝應(yīng)用程序時(shí),自動(dòng)對(duì)程序進(jìn)行代碼預(yù)讀取編譯,讓程序直接編譯成機(jī)器語(yǔ)言,免去了Dalvik 模式要時(shí)時(shí)轉(zhuǎn)換代碼,實(shí)現(xiàn)高效率、省電、占用更低的系統(tǒng)內(nèi)存、手機(jī)運(yùn)行流暢。
- ART 模式的缺點(diǎn)
ART 模式可以降低手機(jī)硬件配置要求,減少RAM 內(nèi)存依賴(lài),不過(guò)在安卓4.4 系統(tǒng)中,安裝應(yīng)用的時(shí)間比安卓4.4 以下版本系統(tǒng)更長(zhǎng),這主要由于應(yīng)用安裝過(guò)程中需要先執(zhí)行編碼導(dǎo)致,并且安裝應(yīng)用更占存儲(chǔ)空間(ROM)
Android 5.0以上版本的手機(jī)正式開(kāi)始使用ART
4.4 DVM和ART虛擬機(jī)的區(qū)別
Dalvik:應(yīng)用程序每次運(yùn)行的時(shí)候,字節(jié)碼都需要通過(guò)即時(shí)編譯器轉(zhuǎn)換為機(jī)器碼,這會(huì)拖慢應(yīng)用的運(yùn)行效率。
ART:應(yīng)用在第一次安裝的時(shí)候,字節(jié)碼就會(huì)預(yù)先編譯成機(jī)器碼(java語(yǔ)言翻譯成C指令),使其成為真正的本地應(yīng)用,應(yīng)用的啟動(dòng)和執(zhí)行速度都會(huì)顯著提升。弊端就是ART需要存儲(chǔ)java和C兩份指令,有些耗內(nèi)存。
上圖說(shuō)明:進(jìn)入開(kāi)發(fā)者模式,選擇運(yùn)行環(huán)境切換。在切換至ART模式時(shí),系統(tǒng)會(huì)重新啟動(dòng),改變運(yùn)行環(huán)境,需要等待程序優(yōu)化完畢,即可。
QQ實(shí)際占用內(nèi)用內(nèi)存,原本為44.64MB,ART模式下,變?yōu)?3.00MB,說(shuō)明ART有些耗內(nèi)存(存兩份指令)。
5. Android開(kāi)發(fā)環(huán)境搭建
目前主流的開(kāi)發(fā)工具有兩個(gè),一個(gè)是Eclipse 另外一個(gè)是Android Studio。Eclipse 需要和ADT(Android Develop Tool)插件整合后才能使用,不過(guò)Google 官方已經(jīng)直接提供了Eclipse 和ADT 集成好的開(kāi)發(fā)工具,叫ADT-Bundle,但是現(xiàn)在Google已經(jīng)不再支持這種方式開(kāi)發(fā),已經(jīng)完全轉(zhuǎn)移到Android Studio平臺(tái)
Android Studio 是Google 基于IntelliJ IDEA 開(kāi)發(fā)的Android 集成開(kāi)發(fā)工具,目前國(guó)內(nèi)使用該開(kāi)發(fā)工具的企業(yè)也越來(lái)越多。Android 基礎(chǔ)階段我們依然使用Eclipse 作為開(kāi)發(fā)工具,在后面的課程中才會(huì)使用到Android Studio。
獲取SDK工具包(Software development kits)下載地址、Android首頁(yè)、 Android中文版首頁(yè)
工具包,包含以下內(nèi)容:
- Eclipse+ADT插件
- Android SDK
- Android Platform-tools
- 最新的Android開(kāi)發(fā)平臺(tái)
- 最新的模擬器鏡像
Android Studio是一個(gè)Android開(kāi)發(fā)環(huán)境,基于IntelliJ IDEA,類(lèi)似Eclipse ADT,Android Studio提供了集成的Android開(kāi)發(fā)工具用于開(kāi)發(fā)和調(diào)試。
6. SDK目錄結(jié)構(gòu)
雙擊SDK Manager.exe。
SDK文件夾目錄結(jié)構(gòu)(請(qǐng)對(duì)應(yīng)上圖查看):
- add-ons文件夾中保存著附加庫(kù),比如Google Maps。
- build-tools文件夾中保存著編譯工具。
- tools文件中只有少數(shù)指令需要我們手動(dòng)調(diào)用,如,draw9patch.bat。
- platform-tools文件夾中包含可執(zhí)行程序和批處理文件,其中adb.exe很重要。
- extras文件夾中v4表示最低可以支持到1.6版本,v7表示最低可以支持到1.7版本。
- temp文件夾為臨時(shí)目錄。
docs文件夾中是SDK幫助文檔,在線(xiàn)文檔使用起來(lái)很不方便。但是,我們可以使用離線(xiàn)文檔。雙擊sdk目錄下的docs文件夾,雙擊此文件夾中的index.html,雙擊打開(kāi)。然后,會(huì)等待很久,因?yàn)闉g覽器要去google服務(wù)器請(qǐng)求數(shù)據(jù)。如果請(qǐng)求不到,就會(huì)一直請(qǐng)求,直到超時(shí)。如果斷網(wǎng)了,也就請(qǐng)求不到數(shù)據(jù)了
但是,我們可以脫機(jī)使用。步驟1、打開(kāi)火狐,選擇“開(kāi)發(fā)者”–>“脫機(jī)工作”。
步驟2、打開(kāi)SDK離線(xiàn)文檔,可以搜索API。如,Activity。
2、安裝intel文件夾中的IntelHAXM.exe可能報(bào)錯(cuò)。如果報(bào)錯(cuò)為如下,說(shuō)明本機(jī)不支持安裝HAXM.exe,不用裝了。
如果報(bào)錯(cuò)如下,說(shuō)明本機(jī)支持,但是支持加速器的選項(xiàng)沒(méi)有打開(kāi),去BIOS中打開(kāi)即可。進(jìn)入BIOS找到virtual technology選項(xiàng),選擇enable即可。
7. 模擬器的創(chuàng)建
1、首先指定SDK的路徑。
點(diǎn)擊Windows–>preferences–>Android,默認(rèn)指定正確的SDK路徑。但是,如果以前裝過(guò)SDK,那么就會(huì)指定舊的SDK,也就是錯(cuò)誤的,手動(dòng)更換成新的SDK路徑即可。
2、點(diǎn)擊虛擬機(jī)管理器按鈕–>點(diǎn)擊New,創(chuàng)建模擬器。
3、點(diǎn)擊“detail”可以看到模擬器配置明細(xì)。
4、點(diǎn)擊“Start”–>Launch,啟動(dòng)模擬器。
不建議使用這么大的分辨率,屏幕分辨率越大,啟動(dòng)越慢,最好用320*480的分辨率。
8. 創(chuàng)建Android項(xiàng)目
步驟1、右擊–>New–>Android Application Project。
步驟二、設(shè)置Android項(xiàng)目參數(shù)。
步驟三、設(shè)置應(yīng)用圖標(biāo)。
步驟四、創(chuàng)建Activity。我們創(chuàng)建的時(shí)候都使用空白的Activity,需要什么效果,最好自己寫(xiě)。自動(dòng)生成的Activity,很多自動(dòng)生成的代碼需要?jiǎng)h除、修改,很麻煩。
給Activity起個(gè)名字,一般就叫MainActivity,不需要修改。
步驟五、生成項(xiàng)目成功。
步驟六、空白項(xiàng)目也可以部署,運(yùn)行。右擊–>Run As–>Android Application。
然后,此項(xiàng)目就會(huì)被部署到Android的模擬器上。選擇Console中的Android選項(xiàng)卡,可以看到部署的狀態(tài)。
步驟七、運(yùn)行成功。
9. Android項(xiàng)目目錄結(jié)構(gòu)
示例1:更改應(yīng)用程序圖標(biāo)、名稱(chēng)。
1、 將圖標(biāo)存入drawable-hdpi文件夾中。
2、查看R.java文件,可以看到生成了相應(yīng)的id。
3、打開(kāi)AndroidManifest.xml文件,修改。
4、運(yùn)行。
1、在AndroidManifest.xml文件中,修改圖標(biāo)及應(yīng)用名稱(chēng)時(shí),一定要注意:如果activity標(biāo)簽中沒(méi)有android:label及android:icon這兩個(gè)屬性,那么顯示的就是application標(biāo)簽中的這兩個(gè)屬性的值,不存在覆蓋問(wèn)題。但是,如果activity標(biāo)簽中也有android:label及android:icon這兩個(gè)屬性,那么就會(huì)覆蓋application標(biāo)簽中的android:label及android:icon屬性。也就是說(shuō),顯示的就是activity標(biāo)簽中的這兩個(gè)屬性的值。
2、圖片3中的圖標(biāo)及應(yīng)用名稱(chēng)會(huì)始終依據(jù)AndroidManifest.xml文件中的application標(biāo)簽中的android:icon和android:label兩個(gè)屬性值展示,因?yàn)榇私缑鎸儆诠芾眄?yè)面,要與圖1和圖2中的普通的Activity區(qū)分開(kāi)。
示例2:修改展示內(nèi)容。
1、修改res中values文件夾中的strings.xml文件。
2、查看R.java文件,可以看到生成了相應(yīng)的id。
3、修改res中l(wèi)ayout文件夾中的布局文件activity_mainxml。
4、運(yùn)行。
10. 應(yīng)用打包安裝過(guò)程
1、Android項(xiàng)目編譯、打包成apk.apk中包含
- .dex文件
- resources.arsc(apk中的“配置文件”、“布局文件”、“圖片”的索引)
- uncompiled resources(未編譯的資源,res文件下的資源都是不會(huì)被編譯的,res文件夾下的圖片、布局文件都是原封不動(dòng)的打包到apk中)
- 清單文件(AndroidManifest.xml,也會(huì)被原封不動(dòng)的打包進(jìn)apk中)
PS:被編譯的只有.java代碼
2、簽名(給apk包打個(gè)數(shù)字簽名)。然后再通過(guò)ADB運(yùn)行到Devices emulator上,Devices指的是手機(jī),Emulator指的是模擬器。系統(tǒng)判斷兩個(gè)應(yīng)用是否屬于同一款應(yīng)用,首先先確認(rèn)清單文件中Manifest標(biāo)簽的package屬性值(應(yīng)用程序在系統(tǒng)中的唯一標(biāo)識(shí))是否相同,其次判斷簽名是否相同。只有兩個(gè)都相同,才會(huì)存在高版本覆蓋低版本的情況。也就是說(shuō),只有簽名相同或者包名相同,是無(wú)法覆蓋的。簽名是屬于企業(yè)商業(yè)機(jī)密,是不能被他人獲取的。簽名是用一個(gè)key文件(相當(dāng)于是秘鑰)計(jì)算出來(lái)的一個(gè)字符串,不同的秘鑰生成的字符串肯定不同,不同公司的簽名也是不同的。所以,一般是無(wú)法山寨另一個(gè)公司的應(yīng)用程序的。
PS:1、啟動(dòng)應(yīng)用程序后,通過(guò)LogCat(LogCat展示的是Android模擬器的后臺(tái)輸出)可以看到一個(gè)應(yīng)用程序的包名。
2、在Android里面,安裝一個(gè)應(yīng)用程序是不能選路徑的。
通過(guò)點(diǎn)擊Window–>Show View–>Other…–>Android–>File Explorer,可以查看Android設(shè)備的文件目錄結(jié)構(gòu)。
3、所有第三方應(yīng)用(也就是可以刪除的項(xiàng)目)安裝在data/app目錄下,并且apk文件名是以包名命名的。
4、所有系統(tǒng)應(yīng)用(不可以刪除的項(xiàng)目)都安裝在system/app目錄下。
11. DDMS
DDMS 是Dalvik Debug Monitor Service 的簡(jiǎn)稱(chēng)。DDMS 為IDE 和emulator 以及Android 真機(jī)架起來(lái)了一座橋梁。開(kāi)發(fā)人員可以通過(guò)DDMS 看到目標(biāo)機(jī)器上運(yùn)行的進(jìn)程/線(xiàn)程狀態(tài),可以看進(jìn)程的heap 信息,可以查看logcat 信息,可以查看進(jìn)程分配內(nèi)存情況,可以向目標(biāo)機(jī)發(fā)送短信以及打電話(huà),可以向Android發(fā)送地理位置信息。下面以Eclipse 的DDMS perspective 為例簡(jiǎn)單介紹DDMS 的功能
1、Devices選項(xiàng)卡用來(lái)查看與開(kāi)發(fā)環(huán)境建立連接的Android設(shè)備,在這里是模擬器,也可以是真機(jī)。
2、SD卡所在的目錄為storage/sdcard。
3、Emulator Control為控制模擬器的選項(xiàng)卡。
PS:1、這里有個(gè)bug,一旦用模擬器打電話(huà),連接就會(huì)終端。只需要點(diǎn)擊Devices選項(xiàng)卡右邊的小三角–>Reset ADB,重啟ADB即可。
2、DDMS中所有的選項(xiàng)卡都可以在Java中使用,只需要切換到Java透視圖,點(diǎn)擊Window–>show View,選擇需要的選項(xiàng)卡即可。
12. 常用ADB指令
ADB,Android debug bridge Android調(diào)試橋,用于建立Android設(shè)備與開(kāi)發(fā)環(huán)境的連接。
模擬器中的操作日志原本是不可能在Windows平臺(tái)上輸出的。但是,正是由于有了ADB,所以L(fǎng)ogCat中才可以輸出模擬器中的操作日志。
1、ADB是一個(gè)可執(zhí)行的指令,在CMD中使用,使用前首先配置環(huán)境變量。
ADB相關(guān)指令功能介紹:
adb install xxx.apk:把一個(gè)apk安裝到模擬器中。
adb uninstall 應(yīng)用包名:從模擬器中卸載一個(gè)apk。
adb devices:查看當(dāng)前跟eclipse建立連接的Android設(shè)備。
PS:adb同時(shí)也是個(gè)進(jìn)程,如果這個(gè)進(jìn)程掛掉了,Android設(shè)備和開(kāi)發(fā)環(huán)境連接就會(huì)中斷。
示例:
1、打開(kāi)“任務(wù)管理器”–>點(diǎn)擊“adb.exe”–>點(diǎn)擊“結(jié)束進(jìn)程”。
2、可以看到?jīng)]有任何Android設(shè)備再連接到模擬器上了。
3、通過(guò)控制臺(tái),我們可以看到經(jīng)過(guò)11秒嘗試連接后,ADB連接重新恢復(fù)。
4、11秒時(shí)間太長(zhǎng),我們可以使用adb kill-server殺死adb進(jìn)程,通過(guò)adb start-server開(kāi)啟adb。
可以看到經(jīng)過(guò)不用花11秒,ADB就已經(jīng)啟動(dòng)了。
5、通過(guò)adb devices也可以重啟ADB。
adb shell:進(jìn)入Android的命令行,其實(shí)是Linux的命令行。
示例:
1、可以通過(guò)ls指令查看當(dāng)前目錄結(jié)構(gòu)。
2、可以通過(guò)cd data進(jìn)入data目錄,然后再通過(guò)ls查看data下的目錄結(jié)構(gòu)。
3、通過(guò)ps可以查看當(dāng)前Android設(shè)備上運(yùn)行的所有的進(jìn)程,包括C進(jìn)程和Java進(jìn)程。
4、在Devices中看到的都是Java進(jìn)程,可以通過(guò)“stop”按鈕關(guān)掉進(jìn)程。例如,關(guān)掉sms(短信)進(jìn)程。
PS
如果連接ADB時(shí)出現(xiàn)emulator-5554 offline,那就必須通過(guò)重啟模擬器解決了。
如果感覺(jué)模擬器太慢,可以通過(guò)真機(jī)測(cè)試,速度更快一些。有些測(cè)試模擬器更方便一些,因?yàn)檎鏅C(jī)有些目錄結(jié)構(gòu)是無(wú)法查看的。
有些進(jìn)程是不能關(guān)閉的,例如com.android.launcher進(jìn)程,關(guān)了,Android就會(huì)崩潰。不過(guò)關(guān)閉之后,它會(huì)自動(dòng)重啟。
某些時(shí)候,通過(guò)adb start-server啟動(dòng)adb會(huì)失敗,可能就是5037端口被占用了。例如,360手機(jī)助手,騰訊手機(jī)管家都有可能占用此端口。可以通過(guò)netstat -ano查看是哪個(gè)進(jìn)程占用了5037端口。如下圖中可以看到,pid(如果看不到,那么點(diǎn)擊任務(wù)管理器–>選擇列–>勾上PID即可)為1848的進(jìn)程占用了5037端口,而pid為1848的進(jìn)程目前正是adb進(jìn)程。如果不是adb進(jìn)程,那么就直接殺掉占用5037端口的進(jìn)程,然后重新啟動(dòng)adb進(jìn)程即可。
13. 電話(huà)撥號(hào)器
撥號(hào)器只負(fù)責(zé)撥號(hào)功能,打電話(huà)功能是通過(guò)切換到打電話(huà)的應(yīng)用實(shí)現(xiàn)的。撥號(hào)器應(yīng)用可以替換,但是打電話(huà)應(yīng)用是無(wú)法替代的,只能使用Android自己的打電話(huà)應(yīng)用。原因是與打電話(huà)相關(guān)的API,上層應(yīng)用是無(wú)法調(diào)用的,只有系統(tǒng)級(jí)別的應(yīng)用才能調(diào)用。也就是說(shuō)打電話(huà)相關(guān)的API在Android jar包中都是不存在的。但是,這些API在源碼中是可以查看的。
步驟一、創(chuàng)建項(xiàng)目。
步驟二、寫(xiě)布局文件,打開(kāi)res\layout\activity_main.xml,編輯。
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:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"android:orientation="vertical"tools:context=".MainActivity" ><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="請(qǐng)輸入號(hào)碼:"android:textSize="18sp" /><EditText android:id="@+id/et"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="請(qǐng)輸入號(hào)碼"/><Button android:id = "@+id/bt"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="撥打"/> </LinearLayout>PS
TextView用來(lái)顯示文本。
layout_width,layout_height是定義文本寬高的,默認(rèn)值是wrap_content,表示正好能夠緊緊包裹文本內(nèi)容的寬高,也就是文本大小決定寬高多少。layout_width,layout_height有3個(gè)屬性值,fill_parent與match_parent都是一樣的,表示填充父元素。在上面的代碼中也就是填充滿(mǎn)LinearLayout(線(xiàn)性布局)。可以看到LinearLayout的layout_width、layout_height也是填充滿(mǎn)父元素,也就是填充滿(mǎn)手機(jī)屏幕。但是,并沒(méi)有填充滿(mǎn)。原因在于paddingBottom、paddingTop、paddingLeft、paddingRight等屬性也決定了其與父元素(手機(jī)屏幕)的內(nèi)間距大小。
Android不推薦使用像素,長(zhǎng)度用dp,字體大小用sp,不要使用像素,因?yàn)橄袼卦谄聊贿m配時(shí)很難做。
布局類(lèi)型在這里使用LinearLayout(現(xiàn)形布局)而不是RelativeLayout(相對(duì)布局)的原因在于線(xiàn)性布局不存在元素重疊的情況,而相對(duì)布局則存在。
LinearLayout的屬性android oritation表示排列方式,有兩種,vertical(垂直排列)和horizontal(水平排列)。
EditText用來(lái)展示輸入框。
EditText中的屬性hint表示:如果文本框中有內(nèi)容,就不顯示提示內(nèi)容;如果文本框沒(méi)有內(nèi)容,就會(huì)顯示提示內(nèi)容。
步驟三、寫(xiě)java代碼,打開(kāi)src\cn.itcast.dialer\MainActivity.java,編輯。
src\cn.itcast.dialer\MainActivity.java
package cn.itcast.dialer; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class MainActivity extends Activity {//onCreate方法是被系統(tǒng)在創(chuàng)建Activity時(shí)調(diào)用的。@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//設(shè)置按鈕點(diǎn)擊偵聽(tīng)//通過(guò)資源id來(lái)獲取指定的組件的對(duì)象Button bt = (Button) findViewById(R.id.bt);//設(shè)置點(diǎn)擊偵聽(tīng)bt.setOnClickListener(new MyListener());}//這里的OnClickListener的全名為:android.view.View.OnClickListenerclass MyListener implements OnClickListener {//按鈕按下時(shí),此方法被調(diào)用@Overridepublic void onClick(View v) {//findViewById返回的是布局所有組件的父類(lèi)android.view.View,需要強(qiáng)轉(zhuǎn)EditText et = (EditText) findViewById(R.id.et);//拿到用戶(hù)輸入的號(hào)碼String phone = et.getText().toString();//告訴系統(tǒng),我們的動(dòng)作//1. 創(chuàng)建意圖對(duì)象Intent intent = new Intent();//2. 設(shè)置動(dòng)作intent.setAction(intent.ACTION_CALL);//3. 設(shè)置號(hào)碼,通過(guò)Uri轉(zhuǎn)intent.setData(Uri.parse("tel:" + phone));//4. 把動(dòng)作告訴系統(tǒng),開(kāi)啟打電話(huà)應(yīng)用的ActivitystartActivity(intent);} } }14. 關(guān)聯(lián)源碼的方法
在Android Studio下,無(wú)需關(guān)聯(lián)源碼直接點(diǎn)擊即可查看源碼,因?yàn)锳ndroid Studio會(huì)自動(dòng)反編譯源碼
1、Ctrl+左鍵,點(diǎn)擊某個(gè)類(lèi),再點(diǎn)擊Attach Source按鈕。
2、點(diǎn)擊External Folder…
3、選擇關(guān)聯(lián)sdk\sources\android-18
看到源碼,則說(shuō)明關(guān)聯(lián)成功。
步驟四、試運(yùn)行,可以看到出現(xiàn)了安全異常,沒(méi)有權(quán)限。因?yàn)榇螂娫?huà)是需要費(fèi)用的,所以需要出示權(quán)限。
步驟五、添加權(quán)限。
打開(kāi)清單文件AndroidManifest.xml,使用可視化方式,點(diǎn)擊Permission選項(xiàng)卡–>Add–>Uses Permission。
添加Uses Permission的屬性“android.permission.CALL_PHONE”,Ctrl+S保存。
可以看到清單文件代碼中生成了如下代碼。
步驟六、重新運(yùn)行,可以看到,撥打成功。
15. 點(diǎn)擊事件的實(shí)現(xiàn)
代碼:三種java寫(xiě)法。
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: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:orientation="vertical"><Button android:id="@+id/bt_iq"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="點(diǎn)我一下,云鶴智商-10" /><Button android:id="@+id/bt_eq"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="點(diǎn)我一下,云鶴情商-10" /></LinearLayout>src\cn.itcast.clickevent\MainActivity.java
package cn.itcast.clickevent;import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button;public class MainActivity extends Activity implements OnClickListener{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button bt_iq = (Button) findViewById(R.id.bt_iq);Button bt_eq = (Button) findViewById(R.id.bt_eq);//第一種:Java寫(xiě)法,內(nèi)部類(lèi)實(shí)現(xiàn)OnClickListener接口,上個(gè)案例中就是按照內(nèi)部類(lèi)的方法實(shí)現(xiàn)的。//第二種:Java寫(xiě)法,匿名內(nèi)部類(lèi)實(shí)現(xiàn)OnClickListener接口。bt_iq.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {System.out.println("點(diǎn)我一下,云鶴智商-10");}});bt_eq.setOnClickListener(this);}//第三種:Java寫(xiě)法,當(dāng)前類(lèi)實(shí)現(xiàn)OnClickListener接口。@Overridepublic void onClick(View v) {System.out.println("點(diǎn)我一下,云鶴情商-10");}}運(yùn)行結(jié)果:
代碼:Android寫(xiě)法。
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: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:orientation="vertical"><Button android:id="@+id/bt1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="按鈕1"android:onClick="click1"/><Button android:id="@+id/bt2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="按鈕2"android:onClick="click1" /><Button android:id="@+id/bt3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="按鈕3"android:onClick="click1" /></LinearLayout>src\cn.itcast.clickevent\MainActivity.java
package cn.itcast.clickevent;import android.app.Activity; import android.os.Bundle; import android.view.View;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}//Android寫(xiě)法。//注意:1. 在Activity中定義。// 2. 方法名必須與Button的onClick屬性值相同。// 3. 返回值必須為void。// 4. 參數(shù)必須為View類(lèi)型對(duì)象。系統(tǒng)調(diào)用此方法時(shí),會(huì)把觸發(fā)的對(duì)象傳進(jìn)來(lái)。這里就是按鈕,Button是View的子類(lèi)。// 5. 多個(gè)按鈕Button的onClick屬性值可以相同,點(diǎn)擊任何一個(gè)按鈕都會(huì)調(diào)用相同的方法。通過(guò)id可以判斷用戶(hù)按下的是哪一個(gè)按鈕。public void click1(View v) {int id = v.getId();switch(id){case R.id.bt1:System.out.println("按鈕1被按下");break;case R.id.bt2:System.out.println("按鈕2被按下");break;case R.id.bt3:System.out.println("按鈕3被按下");break;}}}運(yùn)行結(jié)果:
16. 短信發(fā)送器
代碼: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: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:orientation="vertical"><!-- android:inputType="phone"表示只能輸入電話(huà)號(hào)碼 --><EditText android:id="@+id/et_phone"android:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="請(qǐng)輸入號(hào)碼"android:inputType="phone" /><!-- android:lines="5"表示只能輸入5行 --><EditText android:id="@+id/et_content"android:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="請(qǐng)輸入內(nèi)容"android:lines="5"/><Button android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="發(fā)送"android:onClick="send"/></LinearLayout>src\cn.itcast.smssender\MainActivity.java
package cn.itcast.smssender;import java.util.ArrayList;import android.app.Activity; import android.os.Bundle; import android.telephony.SmsManager; import android.view.View; import android.widget.EditText;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void send(View v) {//獲取用戶(hù)輸入的號(hào)碼和數(shù)據(jù)EditText et_phone = (EditText) findViewById(R.id.et_phone);EditText et_content = (EditText) findViewById(R.id.et_content);String phone = et_phone.getText().toString();String content = et_content.getText().toString();//獲取發(fā)送短信的API//SmsManager要使用android.telephony包內(nèi)的,不要使用android.telephony.gsm包內(nèi)的,已過(guò)時(shí)。SmsManager sm = SmsManager.getDefault();//如果短信過(guò)長(zhǎng),發(fā)布出去,可以把長(zhǎng)短信拆分成若干條短短信。ArrayList<String> smss = sm.divideMessage(content);for(String str : smss){//第一個(gè)參數(shù)表示對(duì)方號(hào)碼。//第二個(gè)參數(shù)表示短信服務(wù)中心的號(hào)碼,可以傳null,表示使用默認(rèn)的短信服務(wù)中心地址。//第三個(gè)參數(shù)表示短信內(nèi)容。//第四個(gè)參數(shù)表示廣播,如果不傳null,短信發(fā)送成功或失敗時(shí),會(huì)給予回執(zhí)信息。//第五個(gè)參數(shù)表示如果對(duì)方成功接收信息了,會(huì)給予回執(zhí)信息。sm.sendTextMessage(phone, null, str, null, null);}}}添加權(quán)限:
運(yùn)行結(jié)果:
1、發(fā)送一般短信結(jié)果。
2、發(fā)送超長(zhǎng)短信結(jié)果。
17. dp和px
dp最終顯示長(zhǎng)度多少是根據(jù)屏幕密度來(lái)?yè)Q算的,屏幕越大,1dp就能顯示更長(zhǎng)的像素。
320x480屏幕上,1dp=1px,160dp=160px,正好是屏幕寬度的一般。
480x800屏幕上,1dp=1.5px,160dp=240px,正好是屏幕寬度的一般
sp與dp類(lèi)似,只是sp用于字體大小,dp用于長(zhǎng)度大小。
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: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:layout_width="160px"android:layout_height="wrap_content"android:text="@string/hello_world"android:background="#ff0000"android:textSize="15sp"/><TextView android:layout_width="160dp"android:layout_height="wrap_content"android:text="@string/hello_world"android:background="#ff0000"android:textSize="15sp"/></LinearLayout>運(yùn)行結(jié)果:
320x480屏幕下顯示:
480x800屏幕下顯示:
18. 布局介紹
為適應(yīng)各種界面風(fēng)格,滿(mǎn)足開(kāi)發(fā)的需要,Android提供了6種布局方式
- LinearLayout(線(xiàn)性布局)
- RelativeLayout(相對(duì)布局)
- FrameLayout(幀布局)
- TableLayout(表格布局)
- AbsoluteLayout(絕對(duì)布局)
- GridLayout(網(wǎng)格布局)
通過(guò)這6種布局我們可以做出來(lái)各種復(fù)雜的UI效果。
18.1 線(xiàn)性布局LinearLayout
- orientation屬性是指定線(xiàn)性布局的排列方向:
- horizontal 水平
- vertical 垂直
示例1: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"tools:context=".MainActivity"android:orientation="vertical"><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="第一個(gè)" /><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="第二個(gè)" /><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="第三個(gè)" /></LinearLayout>運(yùn)行結(jié)果:
1、設(shè)置android: orientation為vertical結(jié)果。
2、設(shè)置android: orientation為horizontal結(jié)果。
gravity屬性是指定當(dāng)前控件內(nèi)容顯示位置:
- left 左邊
- right 右邊
- top 上邊
- bottom 底邊
示例2: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"tools:context=".MainActivity"android:orientation="vertical"><TextView android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"android:text="第一個(gè)"android:background="#ff0000"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center_horizontal"android:text="第二個(gè)"android:background="#00ff00"/></LinearLayout>運(yùn)行結(jié)果:
設(shè)置第一個(gè)TextView的android:layout_width屬性值為match_parent,由于父組件足夠?qū)?#xff0c;因此設(shè)置第一個(gè)TextView的android:gravity屬性值為center_horizontal,可以看到控件內(nèi)容居中。但是,第二個(gè)TextView的父組件寬高都是由包裹著內(nèi)容決定的,所以,設(shè)置第二個(gè)TextView的android:gravity起不到任何效果。
layout_gravity屬性是指定當(dāng)前控件在父元素的位置:
- left 左邊
- right 右邊
- top 上邊
- bottom 底邊
示例3: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"tools:context=".MainActivity"android:orientation="vertical"><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="第一個(gè)"android:background="#ff0000"android:layout_gravity="right"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="第二個(gè)"android:background="#00ff00"android:layout_gravity="center_horizontal"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="第三個(gè)"android:layout_gravity="bottom"/></LinearLayout>運(yùn)行結(jié)果:
設(shè)置第一個(gè)TextView的android:layout_gravity屬性值為right,設(shè)置第二個(gè)TextView的android:layout_gravity屬性值為center_horizontal,設(shè)置第三個(gè)TextView的android:layout_gravity屬性值為bottom。然后會(huì)發(fā)現(xiàn),第三個(gè)TextView的設(shè)置將不會(huì)有任何效果。因?yàn)?#xff0c;
在線(xiàn)性布局中,豎直排列(vertical)時(shí),頂部、底部、豎直居中對(duì)齊都無(wú)效。水平排列(horizontal)時(shí),左右對(duì)齊,水平居中對(duì)齊都無(wú)效。
layout_weightSum(權(quán)重)屬性是把線(xiàn)性布局中剩余空間分成N份。
layout_weight (權(quán)重)屬性是指定當(dāng)前控件在父元素(線(xiàn)性布局)中占N份。
示例4: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"tools:context=".MainActivity"android:orientation="horizontal"><TextView android:layout_width="match_parent"android:layout_height="wrap_content"android:text="第一個(gè)"android:background="#ff0000"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="第二個(gè)"android:background="#00ff00"/><TextView android:layout_width="match_parent"android:layout_height="wrap_content"android:text="第三個(gè)"android:background="#0000ff"/></LinearLayout>運(yùn)行結(jié)果:
水平排列(horizontal)時(shí),設(shè)置第一個(gè)TextView的android:layout_width屬性值為match_parent,將會(huì)發(fā)現(xiàn)第二個(gè)、第三個(gè)TextView被第一個(gè)TextView完全擠出去,看不到了。這時(shí)候就需要使用權(quán)重來(lái)解決這個(gè)問(wèn)題。
示例5: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"tools:context=".MainActivity"android:orientation="horizontal"android:weightSum="2"><TextView android:layout_width="100dp"android:layout_height="wrap_content"android:text="第一個(gè)"android:background="#ff0000"android:layout_weight="1"/><TextView android:layout_width="100dp"android:layout_height="wrap_content"android:text="第二個(gè)"android:background="#00ff00"android:layout_weight="1"/></LinearLayout>運(yùn)行結(jié)果:
首先,將第一個(gè)、第二個(gè)TextView的android:layout_width的屬性值分別設(shè)置為100dp。然后,通過(guò)為L(zhǎng)inearLayout標(biāo)簽設(shè)置android:layout_weightSum屬性值,把屏幕的總寬度權(quán)重設(shè)置為2,每個(gè)TextView的寬度權(quán)重通過(guò)android:layout_weight屬性設(shè)置為1,也就是平均分配。
但是,如果將第一個(gè)TextView的android:layout_width屬性值設(shè)置為100dp,將第二個(gè)TextView的android:layout_width屬性值設(shè)置為50dp,結(jié)果如下。
說(shuō)明:android:weightSum及android:weight的屬性值設(shè)置,針對(duì)的是剩余空間的分配。
第一次分配情況如下:
第二次分配情況如下:
所以,當(dāng)排列為水平排列(horizontal),利用權(quán)重進(jìn)行分配的時(shí)候,一定要搭配將android:layout_width屬性值設(shè)置為0dp來(lái)使用,這樣很容易計(jì)算。同理,當(dāng)排列為垂直排列(vertical),在利用權(quán)重進(jìn)行分配的時(shí)候,一定要搭配將android:layout_height屬性值設(shè)置為0dp來(lái)使用。
PS:
- android:weightSum是可以不寫(xiě)的,上例中,如果第一個(gè)TextView的android:weight屬性值設(shè)置為1,第二個(gè)TextView的android:weight屬性值設(shè)置為2,那么weightSum即為3,兩個(gè)TextView按照1:2分配。但是,如果weightSum設(shè)置為4,相當(dāng)于把寬度切成四份,前面3份,兩個(gè)TextView按照1:2分配,第4塊不分配。
- TextView的android:weight屬性如果不寫(xiě),相當(dāng)于android:weight的屬性值為0,也就是不會(huì)分配到剩余空間任何部分。此時(shí),如果android:layout_width屬性值設(shè)置為0dp,那么就會(huì)報(bào)錯(cuò)。因?yàn)?#xff0c;此TextView已經(jīng)無(wú)法顯示出來(lái)了。
visibility屬性是控制布局是否顯示:
- visible 顯示
- invisible 不顯示但占空間
- gone 隱藏
練習(xí):做出如下效果的布局。
實(shí)現(xiàn):右擊res/layout文件夾–>點(diǎn)擊New–>Android XML File–>選擇LinearLayout–>取一個(gè)名字。
代碼:res\layout\linearlayout_demo.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayout android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:orientation="horizontal"><TextView android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="#000000"/><TextView android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="#ffffff"/><TextView android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="#ff0000"/><TextView android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@android:color/darker_gray"/></LinearLayout><LinearLayout android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:orientation="vertical"><TextView android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="#00ffff"/><TextView android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="#ffffff"/><TextView android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="#ff0000"/><TextView android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="@android:color/darker_gray"/></LinearLayout></LinearLayout>運(yùn)行結(jié)果:
PS:@android:color/darker_gray表示引用Android定義好的顏色資源id
總結(jié)
以上是生活随笔為你收集整理的Android应用开发-快速入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android应用开发:数据存储和界面展
- 下一篇: Android应用开发:网络编程-1