編輯:關於Android編程
Android多終端適配是我們在實際開發中必然會遇到也必然要解決的問題,解決多終端適配的方法有很多,比如使用百分比布局庫(percent-support-lib)、在res目錄下生成不同文件下的dimen值、盡量的使用wrap_content/match_parent/weight權重、盡量用dp替代px 文字使用sp做為單位等。
由於Android系統的開放性,任何用戶、開發者、OEM廠商、運營商都可以對Android進行定制,修改成他們想要的樣子。但是這種“碎片化”到底到達什麼程度呢?
在2012年,OpenSignalMaps(以下簡稱OSM)發布了第一份Android碎片化報告,統計數據表明,
2012年,支持Android的設備共有3997種。
2013年,支持Android的設備共有11868種。
2014年,支持Android的設備共有18796種到
到目前為止就更多了,千千萬萬的Android機型,屏幕尺寸這麼多,為了讓我們開發的程序能夠比較美觀的顯示在不同尺寸、分辨率、像素密度(這些概念我會在下面詳細講解)的設備上,那就要在開發的過程中進行的處理問題了。
重要概念
什麼是屏幕尺寸、屏幕分辨率、屏幕像素密度?
什麼是dp、dip、dpi、sp、px?他們之間的關系是什麼?
什麼是mdpi、hdpi、xdpi、xxdpi?如何計算和區分?
屏幕尺寸
屏幕尺寸指屏幕的對角線的長度,單位是英寸,1英寸=2.54厘米 比如常見的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等
屏幕分辨率
屏幕分辨率是指在橫縱向上的像素點數,單位是px,1px=1個像素點。一般以縱向像素*橫向像素,如1960*1080。
屏幕像素密度
屏幕像素密度是指每英寸上的像素點數,單位是dpi,即“dot per inch”的縮寫。屏幕像素密度與屏幕尺寸和屏幕分辨率有關,在單一變化條件下,屏幕尺寸越小、分辨率越 高,像素密度越大,反之越小。
dp、dip、dpi、sp、px
px我們應該是比較熟悉的,前面的分辨率就是用的像素為單位,大多數情況下,比如UI設計、Android原生API都會以px作為統一的計量單位,像是獲取屏幕寬高等。
dip和dp是一個意思,都是Density Independent Pixels的縮寫,即密度無關像素,上面我們說過,dpi是屏幕像素密度,假如一英寸裡面有160個像素,這個屏幕的像素密度 就是160dpi,那麼在這種情況下,dp和px如何換算呢?在Android中,規定以160dpi為基准,1dip=1px,如果密度是320dpi,則1dip=2px,以此類推。
mdpi、hdpi、xdpi、xxdpimdpi、hdpi、xdpi、xxdpi用來修飾Android中的drawable文件夾及values文件夾,用來區分不同像素密度下的圖片和dimen值。
在進行開發的時候,我們需要把合適大小的圖片放在合適的文件夾裡面
1、使用百分比布局庫(Android-percent-support)
兩種布局供大家使用
PercentRelativeLayout、PercentFragmentLayout,顧名思義這是繼承自RelativeLayout和FragmentLayou兩個容器類
支持的屬性有:
layout_widthPercent:占父控件寬度百分百
layout_heightPercent:占父控件高度百分百
layout_marginPercent
、layout_marginLeftPercent
、layout_marginTopPercent
、layout_marginRightPercent
、
layout_marginBottomPercent
、layout_marginStartPercent
、layout_marginEndPercent
這些屬性一看就明白它的意思
使用:它的使用比較簡單,github上也有源碼Android-percent-support-lib-sample
首先在build.gradle中添加
compile 'com.android.support:percent:22.2.0'然後就可以用它來進行布局,看下面的效果圖,簡單明了
2、在res目錄下生成不同分辨率下的dimens文件
目錄結構大致如下
這個時候我們就可以盡情的寫具體的數值了,比如:layout_marginLeft="@dimen/dimen_30_dip",這個基准尺寸就是設計圖尺寸,如果UI設計師給你的設計圖就是480*800你用工具生成的基准也是480*800的話就無需要對標注進行換算,設計圖傷標注的是多少,layout中就直接寫具體的數值也是沒問題的
存在的弊端:
對於沒有考慮到屏幕尺寸,可能會出現意外的情況
apk的大小會增加;
3、使用wrap_content、match_parent、weight
要確保布局的靈活性並適應各種尺寸的屏幕,應使用 “wrap_content” 和 “match_parent” 控制某些視圖組件的寬度和高度。
使用 “wrap_content”,系統就會將視圖的寬度或高度設置成所需的最小尺寸以適應視圖中的內容,而 “match_parent”(在低於 API 級別 8 的級別中稱為 “fill_parent”)則會展開組件以匹配其父視圖的尺寸。
如果使用 “wrap_content” 和 “match_parent” 尺寸值而不是硬編碼的尺寸,視圖就會相應地僅使用自身所需的空間或展開以填滿可用空間。此方法可讓布局正確適應各種屏幕尺寸和屏幕方向。
下面是一段示例代碼
下圖是在橫縱屏切換的時候的顯示效果,我們可以看到這樣可以很好的適配屏幕尺寸的變化。
weight是線性布局的一個獨特的屬性,我們可以使用這個屬性來按照比例對界面進行分配,完成一些特殊的需求。
但是,我們對於這個屬性的計算應該如何理解呢?
首先看下面的例子,我們在布局中這樣設置我們的界面
我們在布局裡面設置為線性布局,橫向排列,然後放置兩個寬度為0dp的按鈕,分別設置weight為1和2,在效果圖中,我們可以看到兩個按鈕按照1:2的寬度比例正常排列了,這也是我們經常使用到的場景,這是時候很好理解,Button1的寬度就是1/(1+2) = 1/3,Button2的寬度則是2/(1+2) = 2/3,我們可以很清楚的明白這種情景下的占比如何計算。
但是假如我們的寬度不是0dp(wrap_content和0dp的效果相同),則是match_parent呢?
下面是設置為match_parent的效果
我們可以看到,在這種情況下,占比和上面正好相反,這是怎麼回事呢?說到這裡,我們就不得不提一下weight的計算方法了。
android:layout_weight的真實含義是:如果View設置了該屬性並且有效,那麼該 View的寬度等於原有寬度(android:layout_width)加上剩余空間的占比。
從這個角度我們來解釋一下上面的現象。在上面的代碼中,我們設置每個Button的寬度都是match_parent,假設屏幕寬度為L,那麼每個Button的寬度也應該都為L,剩余寬度就等於L-(L+L)= -L。
Button1的weight=1,剩余寬度占比為1/(1+2)= 1/3,所以最終寬度為L+1/3*(-L)=2/3L,Button2的計算類似,最終寬度為L+2/3(-L)=1/3L。
這是在水平方向上的,那麼在垂直方向上也是這樣嗎?
下面是測試代碼和效果
如果是垂直方向,那麼我們應該改變的是layout_height的屬性,下面是0dp的顯示效果
下面是match_parent的顯示效果,結論和水平是完全一樣的
雖然說我們演示了match_parent的顯示效果,並說明了原因,但是在真正用的時候,我們都是設置某一個屬性為0dp,然後按照權重計算所占百分比。
使用相對布局,禁用絕對布局
在開發中,我們大部分時候使用的都是線性布局、相對布局和幀布局,絕對布局由於適配性極差,所以極少使用。
由於各種布局的特點不一樣,所以不能說哪個布局好用,到底應該使用什麼布局只能根據實際需求來確定。我們可以使用 LinearLayout 的嵌套實例並結合 “wrap_content” 和 “match_parent”,以便構建相當復雜的布局。不過,我們無法通過 LinearLayout 精確控制子視圖的特殊關系;系統會將 LinearLayout 中的視圖直接並排列出。
如果我們需要將子視圖排列出各種效果而不是一條直線,通常更合適的解決方法是使用 RelativeLayout,這樣就可以根據各組件之間的特殊關系指定布局了。例如,我們可以將某個子視圖對齊到屏幕左側,同時將另一個視圖對齊到屏幕右側。
下面的代碼以官方Demo為例說明。
在上面的代碼中我們使用了相對布局,並且使用alignXXX等屬性指定了子控件的位置,下面是這種布局方式在應對屏幕變化時的表現
在小尺寸屏幕的顯示
在平板的大尺寸上的顯示效果
雖然控件的大小由於屏幕尺寸的增加而發生了改變,但是我們可以看到,由於使用了相對布局,所以控件之前的位置關系並沒有發生什麼變化,這說明我們的適配成功了。
最近閒著沒事做了一個Android小程序,具體如下:效果圖:原始界面點擊按鈕運行 運行後界面實現代碼:public class Mai
使用Vitamio打造自己的Android萬能播放器(1)——准備一、實現目標1.1亮度控制模仿VPlayer界面:1.2聲音控制模
介紹Android 2.2(API 8)開始提供了一個可管理和操作設備的類DevicePolicyManager,通過這個類可以進行鎖屏、設置密碼、清除密碼、恢復出廠設置
1、概述控件基於android-Ultra-Pull-to-Refresh做的header定制,繼承PtrFrameLayout,把事件分發給裡面的RadioGroup,