在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ 響應(yīng)式 Android 應(yīng)用
與四軸無人機(jī)的通訊
在沙盒中編寫腳本
結(jié)構(gòu)體和值類型
深入理解 CocoaPods
UICollectionView + UIKit 力學(xué)
NSString 與 Unicode
代碼簽名探析
測試
架構(gòu)
第二期-并發(fā)編程
Metal
自定義控件
iOS 中的行為
行為驅(qū)動開發(fā)
Collection View 動畫
截圖測試
MVVM 介紹
使 Mac 應(yīng)用數(shù)據(jù)腳本化
一個完整的 Core Data 應(yīng)用
插件
字符串
為 iOS 建立 Travis CI
先進(jìn)的自動布局工具箱
動畫
為 iOS 7 重新設(shè)計 App
XPC
從 NSURLConnection 到 NSURLSession
Core Data 網(wǎng)絡(luò)應(yīng)用實(shí)例
GPU 加速下的圖像處理
自定義 Core Data 遷移
子類
與調(diào)試器共舞 - LLDB 的華爾茲
圖片格式
并發(fā)編程:API 及挑戰(zhàn)
IP,TCP 和 HTTP
動畫解釋
響應(yīng)式 Android 應(yīng)用
初識 TextKit
客戶端
View-Layer 協(xié)作
回到 Mac
Android
Core Image 介紹
自定義 Formatters
Scene Kit
調(diào)試
項目介紹
Swift 的強(qiáng)大之處
測試并發(fā)程序
Android 通知中心
調(diào)試:案例學(xué)習(xí)
從 UIKit 到 AppKit
iOS 7 : 隱藏技巧和變通之道
安全
底層并發(fā) API
消息傳遞機(jī)制
更輕量的 View Controllers
用 SQLite 和 FMDB 替代 Core Data
字符串解析
終身學(xué)習(xí)的一代人
視頻
Playground 快速原型制作
Omni 內(nèi)部
同步數(shù)據(jù)
設(shè)計優(yōu)雅的移動游戲
繪制像素到屏幕上
相機(jī)與照片
音頻 API 一覽
交互式動畫
常見的后臺實(shí)踐
糟糕的測試
避免濫用單例
數(shù)據(jù)模型和模型對象
Core Data
字符串本地化
View Controller 轉(zhuǎn)場
照片框架
響應(yīng)式視圖
Square Register 中的擴(kuò)張
DTrace
基礎(chǔ)集合類
視頻工具箱和硬件加速
字符串渲染
讓東西變得不那么糟
游戲中的多點(diǎn)互聯(lián)
iCloud 和 Core Data
Views
虛擬音域 - 聲音設(shè)計的藝術(shù)
導(dǎo)航應(yīng)用
線程安全類的設(shè)計
置換測試: Mock, Stub 和其他
Build 工具
KVC 和 KVO
Core Image 和視頻
Android Intents
在 iOS 上捕獲視頻
四軸無人機(jī)項目
Mach-O 可執(zhí)行文件
UI 測試
值對象
活動追蹤
依賴注入
Swift
項目管理
整潔的 Table View 代碼
Swift 方法的多面性
為什么今天安全仍然重要
Core Data 概述
Foundation
Swift 的函數(shù)式 API
iOS 7 的多任務(wù)
自定義 Collection View 布局
測試 View Controllers
訪談
收據(jù)驗(yàn)證
數(shù)據(jù)同步
自定義 ViewController 容器轉(zhuǎn)場
游戲
調(diào)試核對清單
View Controller 容器
學(xué)無止境
XCTest 測試實(shí)戰(zhàn)
iOS 7
Layer 中自定義屬性的動畫
第一期-更輕量的 View Controllers
精通 iCloud 文檔存儲
代碼審查的藝術(shù):Dropbox 的故事
GPU 加速下的圖像視覺
Artsy
照片擴(kuò)展
理解 Scroll Views
使用 VIPER 構(gòu)建 iOS 應(yīng)用
Android 中的 SQLite 數(shù)據(jù)庫支持
Fetch 請求
導(dǎo)入大數(shù)據(jù)集
iOS 開發(fā)者的 Android 第一課
iOS 上的相機(jī)捕捉
語言標(biāo)簽
同步案例學(xué)習(xí)
依賴注入和注解,為什么 Java 比你想象的要好
編譯器
基于 OpenCV 的人臉識別
玩轉(zhuǎn)字符串
相機(jī)工作原理
Build 過程

響應(yīng)式 Android 應(yīng)用

引言

開發(fā)一款移動應(yīng)用是一個創(chuàng)造性的過程。你一定會想要創(chuàng)作一款這樣的應(yīng)用,它美觀實(shí)用,它在任何設(shè)備上都能運(yùn)行流暢,它讓用戶覺得賞心悅目,它讓自己引以為傲,下面我就會告訴你我是如何創(chuàng)作具有這些特性的安卓應(yīng)用的。

對于安卓開發(fā)存在一個普遍的誤解,那就是安卓設(shè)備尺寸的多樣性使得開發(fā)出具有上述特性的應(yīng)用變得十分棘手。 你肯定已經(jīng)看過《安卓可視化碎片》這篇文章了( Android Fragmentation Visualized),文章列舉出了驚人數(shù)目的不同安卓設(shè)備.

事實(shí)上,你確實(shí)需要在設(shè)計上花費(fèi)很多心思,但絕對不必比在其他平臺上花費(fèi)得多。安卓開發(fā)者擁有高性能的工具去應(yīng)對設(shè)備配置的多樣性,并確保應(yīng)用在所有設(shè)備上都能完美運(yùn)行。

在這篇文章中,我主要會涉及三方面的內(nèi)容,它們包括:安卓設(shè)備多樣性的三個方面,以及這種多樣性是如何影響開發(fā)的,還有安卓應(yīng)用的設(shè)計。我會從一個較高的層次并從 iOS 開發(fā)者角度來談?wù)撨@些內(nèi)容:

  • 安卓開發(fā)者是怎樣針對屏幕尺寸的微小差異進(jìn)行優(yōu)化的? 怎樣處理不同設(shè)備的寬高差異?
  • 安卓開發(fā)者是怎樣考慮屏幕密度差異(screen density variations)問題的?
  • 應(yīng)用怎樣才能夠被優(yōu)化去適應(yīng)不同的設(shè)備? 怎樣才能制作一款在手機(jī)和平板上都完美運(yùn)行的應(yīng)用呢?

屏幕尺寸 (Screen Size)

我們首先回顧一下 iOS 設(shè)備的屏幕尺寸。實(shí)際上有三種: 3.5 英寸 iPhone,4 英寸 iPhone,以及 iPad。盡管 iPad mini 比 iPad 小,但從開發(fā)者角度,這僅僅只是按比例縮小了。對許多應(yīng)用來說,3.5 英寸和 4 英寸的設(shè)備屏幕尺寸的差別幾乎沒有影響,因?yàn)閮H僅只是高度改變了。

iOS 繪畫系統(tǒng)使用點(diǎn)(points)而不是像素(pixels),因此屏幕是否是視網(wǎng)膜屏不會影響頁面布局。頁面布局或是靜態(tài)的 (針對每種設(shè)備用編程方式設(shè)計精確到點(diǎn),或者使用設(shè)備相應(yīng)的 xib 文件) 或動態(tài)的 (使用自動布局 Auto Layout 或者自適應(yīng) Autoresizing Masks)。

相比之下,在安卓平臺上,有數(shù)量驚人的不同尺寸的屏幕需要支持。安卓開發(fā)者們是如何確保他們的應(yīng)用在所有設(shè)備上都運(yùn)行流暢呢?

在許多方面,安卓設(shè)計和網(wǎng)頁設(shè)計很相似。網(wǎng)頁設(shè)計必須支持任何可能存在的瀏覽器尺寸。類似的,安卓應(yīng)用設(shè)計是建立在預(yù)期了屏幕尺寸改變的前提下的。我們設(shè)計的視圖能夠按照自身限制條件自動填充空間和內(nèi)容。

既然你在設(shè)計時必須將不同的屏幕尺寸都考慮到,那么支持設(shè)備橫屏也理所應(yīng)當(dāng)需要被考慮。當(dāng)一款應(yīng)用需要支持任何尺寸的屏幕大小時,橫向僅僅就只是設(shè)備的一項附加配置。

布局文件

讓我們深入到布局系統(tǒng)的更多細(xì)節(jié)中。布局文件是描述用戶界面的 XML 文件。

如下圖所示,我們創(chuàng)建了一個布局文件樣本。這個文件被用作應(yīng)用的登錄視圖:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:padding="14dp">
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="username"/>
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="password"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Login"/>
</LinearLayout>

http://wiki.jikexueyuan.com/project/objc/images/11-12.png" alt="" />

http://wiki.jikexueyuan.com/project/objc/images/11-13.png" alt="" />

在上面的布局文件中,線性布局 LinearLayout 被用來線性排列 視圖Views。我們實(shí)例化了 線性布局中的三個視圖: 一個用戶名 EditText,一個密碼 EditText,和一個登錄按鈕。

需要注意的是在布局文件中的每個視圖的寬 layout_width 和高 layout_height 。這些屬性被用來設(shè)置視圖的具體寬高。我們使用兩個常量來設(shè)置每個屬性: wrap_contentmatch_parent。如果用 wrap_content 來設(shè)置視圖的高度,那么那個視圖會根據(jù)它需要呈現(xiàn)的內(nèi)容調(diào)整至相應(yīng)高度。如果用 match_parent 來設(shè)置視圖的寬,那么那個視圖會和它的父視圖一樣寬。

通過使用 wrap_contentmatch_parent 的值,我們設(shè)計了一款可以自動伸縮去適應(yīng)任何屏幕的視圖。

和 iOS 最重要的區(qū)別在于,布局 XML 文件和在其中設(shè)置的視圖并未設(shè)置大小。事實(shí)上,在布局文件的視圖被放置到屏幕上之前,并沒有被設(shè)置任何大小相關(guān)聯(lián)的值。

屏幕密度 (Screen Density)

安卓開發(fā)中視圖可變性的另一個影響因素是屏幕密度。你怎樣才能編寫一款可以適應(yīng)不同密度屏幕的應(yīng)用的呢?

你應(yīng)該知道,iOS 開發(fā)里會考慮到兩種屏幕: 普通屏幕和 Retina 屏幕。如果文件名里 @2x 后綴被使用,系統(tǒng)會自動根據(jù)設(shè)備種類選擇合適的圖像。

安卓應(yīng)用屏幕密度適配的原理和 iOS 相似,但是可變性更強(qiáng)。不同于 iOS 有兩個圖片容器 (image buckets),安卓開發(fā)者有很多。我們標(biāo)準(zhǔn)的圖片容器大小是 mdpi (Median Dots Per Inch),或者稱作中密度。這個 mdpi 容器和普通的iOS圖片尺寸一致。然后,hdpi (High Dots Per Inch),或者高密度,是中密度 mdpi 的 1.5 倍。最后,xhdpi (Extra High Dots Per Inch),或稱為超高密度,是普通尺寸的 2 倍,這和 iOS 的 Retina 高清屏尺寸一致。安卓還能利用其它的圖像容器,包含 xxhdpixxxhdpi。

資源選定 (Resource Qualifiers)

我們對增添多種圖片尺寸似乎無計可施,但是安卓使用了一種健壯的資源選定系統(tǒng)來挑選具體應(yīng)該使用的資源。

下面,將介紹一個關(guān)于資源選定如何處理圖片的例子。在一個安卓項目中,有一個 res 文件夾,這里放置 app 所要使用的所有資源。包含圖片,以及布局文件,還有一些其他項目資源。

http://wiki.jikexueyuan.com/project/objc/images/11-14.png" alt="" />

這里,ic_launcher.png 圖片重復(fù)出現(xiàn)在下面三個文件夾: drawable-hdpidrawable-mdpi,和 drawable-xhdpi。當(dāng)請求名為 ic_launcher 的圖片時,系統(tǒng)運(yùn)行時會根據(jù)設(shè)備配置自動選擇適應(yīng)的圖片.

這能讓我們根據(jù)不同屏幕尺寸最優(yōu)化圖片,但是重復(fù)存儲的圖片勢必浪費(fèi)資源。

這些屏幕密度就是模糊限制因素 (fuzzy qualifiers)。如果你使用和上面的例子中的帶有 xxhdpi 屏幕的設(shè)備,系統(tǒng)將自動選擇 xhdpi 版本的圖像然后根據(jù)屏幕密度縮放圖片。這種特性允許我們只須創(chuàng)建一個版本的圖像就可以按需為其他密度的屏幕優(yōu)化。

一個普遍模型是提供高密度的圖片,然后讓安卓去將圖像縮小,以適應(yīng)低屏幕密度的設(shè)備。

密度獨(dú)立像素 (DIPs)

應(yīng)對屏幕密度變化做出的最后調(diào)整是在布局文件里設(shè)置準(zhǔn)確的尺寸。想像你希望你的應(yīng)用支持屏幕外部填充。我們怎樣設(shè)置元素值使得視圖能夠根據(jù)不同設(shè)備自動匹配屏幕密度?

好吧,iOS 開發(fā)者可以將這樣的填充精確至像素點(diǎn)。在非 Retina 屏設(shè)備上,原像素值會被使用,而在 Retina 設(shè)備上,系統(tǒng)會自動 double 該像素值。

在安卓上,你也可以以原像素點(diǎn)為單位設(shè)置圖像填充,但是那些值不會縮放以適用于高密度屏幕的設(shè)備。相反的,安卓開發(fā)者會設(shè)置在密度獨(dú)立像素里的測量單元 (通常被稱作密度獨(dú)立像素,或者設(shè)備像素單元)。這些單元會像 iOS 自適應(yīng)大小一樣 根據(jù)設(shè)備密度自動做出縮放調(diào)整。

設(shè)備種類

最后需要考慮的一點(diǎn)是在安卓開發(fā)中不同種類的設(shè)備是怎樣被管理的。值得注意的是 iOS 有兩個獨(dú)立的類: iPhone 和 iPad。但是,安卓截然不同,因?yàn)榘沧繐碛幸幌盗胁煌姆N類,而且手機(jī)和平板之間的差別可以是任意的。先前提到的資源選定體系被重度使用來支持這一范圍的屏幕尺寸變化。

對于簡單屏幕,它們可以基于設(shè)備大小尺寸并根據(jù)內(nèi)容調(diào)整填充。例如,我們可以檢驗(yàn)一下維度資源 (dimension resources).我們可以在一個普通的位置定義一個維度值并在我們的布局文件中引用它:

<?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:layout_margin="@dimen/container_margin" >
    ...
</LinearLayout>

注意 @dimen/container_margin 的值。這代表了一個存儲在資源系統(tǒng)中的被命名值。我們能夠定義一個基本的邊距屬性值作為默認(rèn)值:

res/values/dimens.xml 里:

<resouces>
    <dimen name=”container_margin”>4dp</dimen>
</resources>

然后,我們?yōu)槠桨鍎?chuàng)建一個合格版本的填充:

res/values-w600dp/dimens.xml 中:

<resouces>
   <dimen name=”container_margin”>96dp</dimen>
</resources>

現(xiàn)在,在寬度至少有 600 個設(shè)備點(diǎn)單元的設(shè)備上,較大的容器邊緣間距值會被系統(tǒng)選擇。這個多出來的邊界可以調(diào)整我們的用戶界面,這樣一來,這款在手機(jī)上表現(xiàn)良好的應(yīng)用,現(xiàn)在在平板上就不只是一個簡單的拉伸版本而已了。

分割視圖

上面的尺寸實(shí)例在某些情況下是一個很實(shí)用的工具,但是,常常會出現(xiàn)一種情況,那就是由于平板尺寸較大,有了放置額外的應(yīng)用組件的空間,所以應(yīng)用可以變得更為有用。

在 iOS 應(yīng)用中,一個通常的方式是使用一個分離的視圖控制器。UISplitViewController 允許你控制兩個視圖控制器,并將它們同時顯示在 iPad 應(yīng)用的一個屏幕上。

在安卓上,我們有一個相似的系統(tǒng),但卻可以有更多的控制和更多的選擇用于擴(kuò)展。你的應(yīng)用的核心部件可以被分為可重用的部分,就是 fragments,類似于 iOS 里面的視圖控制器。所有應(yīng)用里的任一個單屏幕的控制邏輯都能夠被以一個 fragment 的形式呈現(xiàn)出來。當(dāng)在手機(jī)上的時候,我們向用戶呈現(xiàn)一個 fragment。當(dāng)在平板上時,我們可以向用戶呈現(xiàn)兩個 (或更多的) fragments。

我們可以再次依賴資源選定系統(tǒng)為手機(jī)或者平板供應(yīng)一個獨(dú)特的布局文件,這將允許我們在平板上控制兩個 fragment,而在手機(jī)上控制一個。

例如,下面定義的布局文件會被用在手機(jī)設(shè)備上:

res/layout/activity_home.xml 中:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

這個被 container ID 定義的 FrameLayout 會包含我們應(yīng)用的主視圖,并且會為其提供主 fragment 作為容器。

我們可以為平板設(shè)備創(chuàng)建這個文件的對應(yīng)的版本:

res/layout-sw600dp/activity_home.xml 中:

<?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">
        <FrameLayout 
        android:id="@+id/container"
        android:layout_width="250dp"
        android:layout_height="match_parent" />
        <FrameLayout 
        android:id="@+id/detail_container"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="match_parent" />
    </LinearLayout>

現(xiàn)在,當(dāng)我們在平板設(shè)備上使用 activity_home 布局文件時,我們會有兩個窗口,而不是一個,這意味著我們能夠支配兩個 fragment 視圖。我們現(xiàn)在可以幾乎不用修改代碼就能在一個屏幕上呈現(xiàn)主視圖和詳情視圖。在運(yùn)行時候,系統(tǒng)會根據(jù)設(shè)備的配置決定布局文件的使用版本。

結(jié)論

除了 sw600dp 資源選定以外,這篇文章提到的所有工具都可以供任何你支持的任何安卓設(shè)備使用。其實(shí)有一種在 sw600dp 加入之前就存在的更老,粒度更小的資源選定方式,一般用于那些更早的的設(shè)備上。

正如上面所示,安卓開發(fā)者擁有適用于任何設(shè)備的優(yōu)化工具。你會發(fā)現(xiàn)一些安卓應(yīng)用在許多設(shè)備上并不非常適合 (這種情況其實(shí)蠻常見)。我想要強(qiáng)調(diào)的是 從已有平臺上把設(shè)計從既存的平臺上強(qiáng)塞到安卓里這種行為其實(shí)并不合適。我強(qiáng)烈建議你重新思考一下你的設(shè)計并為你的用戶提供一種更愉悅的體驗(yàn).

上一篇:編譯器下一篇:繪制像素到屏幕上