Android屏幕適配

jopen 10年前發布 | 59K 次閱讀 Android Android開發 移動開發

android的屏幕適配一直是開發者頭疼的問題,因為android的設備大小不一,而且屏幕顯示效果也不相同,如何對android進行屏幕適配是一個很大的挑戰,為了應對不同的情況,需要仔細研究android對不同屏幕的定義。看過學渣的這篇博客,希望大家對屏幕適配有一個基本的了解。

1 android的屏幕大小

android的屏幕有大有小,為了對不同大小屏幕的設備提供最好的體驗,需要對不同大小的設備進行不同的設計,首先遇到的問題就是android對屏幕大小的區分。

android的屏幕問題在官網有詳細說明,,作為一名學渣,需要細細研讀,首先android把屏幕分為四種大小:small,normal,large,xlarge,這四種屏幕首先是直觀的區分,即對設備的對角線用尺子量一下,用英寸做單位進行區分,比如學渣用的紅米就是4.7英寸,屬于normal,具體分類如圖1所示:

20140609113244687.png

圖1 android屏幕大小區分

如果你的程序獲知android設備屏幕后,根據大小不同可以采用不同的布局方案,但是我們寫程序時,進行布局時,不可能用英寸進行布局,先假設我們使用像素(px)進行布局,但是這里會遇到一個問題,這里需要介紹新的term,請看2。。。。。

2 屏幕的分辨率和密度

 這里遇到的問題需要看幾個術語,android官網上去后有幾個術語介紹,學渣先為大家介紹分辨率和密度

        分辨率(Resolution):The total number of physical pixels on a screen. 即一個設備的物理像素,如1280*720,大家可以自己計算。

    密度(Screen density):The quantity of pixels within a physical area of the screen; usually referred to as dpi (dots per inch).一般我們的密度的單位是像素數目/平方英寸,但是這里推薦了一個新的密度表示方法,就是每英寸的像素數目(dpi)。我們以后用到的密度就是這個dpi

     android里用分辨率和密度這兩個域來記錄設備的真實尺寸,采用密度的主要原因(學渣猜的)應該是“去英寸化”,即在程序中不要出現英寸這個單位,因此用密度和分辨率這兩個值可以保存設備的真實尺寸。

    對于一個程序而言,它可以獲取到屏幕的分辨率和尺寸,進而密度=分辨率/尺寸,可以算出尺寸,在android里,獲取密度尺寸可以參考這里我們這里用一個小程序來求兩個設備的分辨率和密度。學渣定義了兩臺avd,尺寸都是4.7英寸,設備1的分辨率為800*1280,設備2的分辨率為480*800,測試代碼如下:

    package com.example.testscreen;  

    import android.os.Bundle;  
    import android.app.Activity;  
    import android.util.DisplayMetrics;  
    import android.view.Menu;  

    public class MainActivity extends Activity {  
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  

             DisplayMetrics metrics = new DisplayMetrics();  
             getWindowManager().getDefaultDisplay().getMetrics(metrics);  

             //得到設備的分辨率,即寬和高的像素數目  
             int height = metrics.heightPixels;  
             int width = metrics.widthPixels;  

             System.out.println("the height is "+height +" the width is" + width);  

             //得到設備的密度  
             int density = metrics.densityDpi;  
             System.out.println("the density is " + density);  

        }  
    }  

設備1的輸出是:

    06-09 00:10:17.188: I/System.out(2041): the height is 1184 the width is768  
    06-09 00:10:17.188: I/System.out(2041): the density is 320  
設備2的輸出是:

    06-09 00:45:35.085: I/System.out(2088): the height is 736 the width is480  
    06-09 00:45:35.085: I/System.out(2088): the density is 213  

    從兩個設備的輸出可以知道,其實學渣是定義了兩個4.7英寸的avd,但是有著不同的分辨率,(android里有底部欄,看起來有點不一樣),這兩個例子說明了一個問題:相同大小的手機,可以有不同的分辨率,進而就有不同的密度嘍,(因為密度=分辨率/大小)。

3 程序判斷屏幕大小

      每個程序都需要判定屏幕的大小,進而選擇合適的布局(后面會說),如何判定大小(設備的真實尺寸,可以理解為設備對角線的英寸數)呢,就根據2所提到的兩個參數來判斷,一個是分辨率,一個是密度,用設備1而言,知道height是1184像素(px),其密度為320dpi(像素/英寸),則高度的具體值就是1280/320=4(英寸),寬度為800/320=2.5 ,用勾股定理算出對角線的長度,(學渣這里沒有細算)再和圖1匹配,得到這個設備的屏幕大小尺寸。

      屏幕大小判定之后,首先需要在mainfest聲明支持的屏幕大小,如:

    <supports-screens android:largeScreens="true" />  

             要想要好的用戶體驗,程序可以根據不同的大小選擇不同的布局,android官方文檔里也提到了,可以對不同的大小,設置不同的layout,如res/layout-large就是large屏幕時所采用的布局。

    官方文檔里有這么幾句話要注意:Beginning with Android 3.2 (API level 13), the above size groups are deprecated and you should instead use the sw<N>dp configuration qualifier to define the smallest available width required by your layout resources. For example, if your multi-pane tablet layout requires at least 600dp of screen width, you should place it inlayout-sw600dp/.即對于3.2以上的,直接采用dp(dp相當于一種程序中的英寸大小)進行判斷屏幕的寬度,進而選擇不同的布局,如/res/layout-sw600dp,就是寬度要求是600dp以上的我們就選擇這個布局。不過意思和small,large等一樣,只不過把大小換成了具體的數字。

3 去英寸化 

   上面我們提到了去英寸化,如何讓一個程序能夠很好的顯示大小呢,似乎可以采用像素?但是這是完全不可以的。先舉一個簡單的例子說明像素的缺陷,還是采用上述的設備1和設備2進行測試,我們在設備1和設備2都定義一個button,寬度和高度都為200px(像素),效果如圖2所示:

20140609131337421.png

圖2 相同大小的手機,相同的像素大小的button

      其實這個結果一點也不意外,這是因為兩個button的像素大小雖然一樣,但是密度不同,而最后的真實大小是按照英寸來畫的,因為密度=像素/英寸,則 真實大小(英寸數)=像素/密度。那么這個問題怎么破,因為我們的程序一定是在相同大小的屏幕上有相同的大小,如果兩個空間的大小一樣,則是其英寸數相等,而英寸數又不能直接寫在程序里,于是乎出現一個逆天的術語,dp。其實在2里我們看到過這個dp,那么什么是dp呢?

       dp在官網里叫Density-independent pixel (dp),即密度無關的像素,即可以擺脫密度的纏繞,就是前面我所提到的一種具有“去英寸化”功能的新的單位,我們先不提dp的具體計算(后面會說),我們就先假設這個dp就是一個全新的度量單位,讓相等的dp在不同密度的屏幕里有相等的長度,比如1dp無論你是在設備1還是設備2,大小都是相等。這就是解決了“去英寸化”的問題。

4 dp的應用與圖片問題

   通過3的描述,我們應該可以知道,在layout里任何的控件都采用dp就可以保證顯示一致的問題了。這也是google所推薦的。

    但是對于圖片這種外來戶,我們可以規定它在layout中的大小,假如我們規定了圖片的寬度1英寸(可以轉為dp,后面會將),對于一張圖片,其真實的寬度為15像素,在密度為3dpi的屏幕中,可以顯示3個像素,這時需要丟掉12個像素,圖片一定極為不清晰;在密度為15dpi的屏幕里可以顯示15個像素,顯示完全。這就有了分辨率的問題,在寬度都為1英寸的情況下,肯定是能夠顯示全部15個像素的圖片清晰,怎么能讓不同密度的屏幕顯示的照片都比較清晰呢,我們可以對不同密度的屏幕選擇不同的圖片,即高密度選擇高清圖片。對于任何一張圖片,我們都可以做三張,一張低分辨率,一張高分辨率,一張中間值,對于高密度的屏幕,比如密度為15,我們選擇一張分辨率較高的圖片(就是大的圖片),如15英寸的,對于密度為3的,我們讓它顯示一張分辨率為3的,則保證了不會丟失信息,從而保證圖片清晰。

    對于不同密度的屏幕,可以通過/res/drawable-hdpi等進行選擇圖片。這個官網也有。

5 dp的計算  

    其實我們沒必要對dp進行計算,但是為了便于理解,我還是把dp的計算說一下, px = dp * (dpi / 160).這是官網的計算公式。對于一個密度為160dpi的屏幕而言,一個px就等于一個dp。。。。

   另外:android里字體的大小采用sp,具體的還沒有研究,不過作用估計和dp差不多。

 
來自:http://blog.csdn.net/zhao123h/article/details/29564071

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!