Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android多屏幕適配筆記

Android多屏幕適配筆記

編輯:關於Android編程

1、常用單位及其關系

px:像素

inch:英寸

pt:1/72 英寸

dpi:一英寸長的直線上的像素點的數量,即像素密度。不同的設備,dpi值不同,顯示效果不同,dpi的值跟設備硬件有關。標准值是160dp。

dp(dip):獨立像素密度。即在標准屏幕下,1個像素點的長度,標准屏幕是160dpi,可以理解為1英寸長度上有160個像素。標准屏幕中1dp=1px。

px = dp*(dpi/160);//當dpi=160時,1px=1dp

分辨率:屏幕上長寬方向上像素點的數量,即一個屏幕上像素的數量。

例如:720*1280 = 屏幕x軸上有720個像素,屏幕y軸上有1280個像素

分辨率單位:dpi(點每英寸)、lpi(線每英寸)、ppi(像素每英寸)

屏幕的物理尺寸:屏幕對角線的長度,單位是inch

sp:專用於設定文字大小,受dpi影響和用戶的字體偏好設定影響。

各單位和px的換算關系見TypedValue.applyDimension方法

 

public static float applyDimension(int unit, float value,
                                       DisplayMetrics metrics)
    {
        switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
        }
        return 0;
    }

//顯示器
DisplayMetrics d = getResources().getDisplayMetrics();//可以獲得scaledDensity,densityDpi,heightPixels,widthPixels等信息。
Configuration configuration = getResources().getConfiguration();//獲取設備的配置信息
//configuration.screenHeightDp  當前屏幕可用空間的高度,單位是dp
//configuration.screenWidthDp   當前屏幕可用空間的寬度,單位是dp
//configuration.densityDpi      當前設備的dpi信息

 

例子:

已知設備1080*1920,使用DisplayMetrics獲取的實際信息是1080*1776,y軸方向上的像素有誤差是因為軟鍵盤,實際屏幕要小。

使用Configuration獲取的設備的dpi=480dpi,根據公式px=dp*(dpi/160)。

現在px=1080,dpi=480,則dp=360.

使用configuration.screenWidthDp得到的數值為360,和上面用公式算出的一致。

但是y軸方向上用公式計算出來的應該是1776/3=592.但是用scrrenHeightDp獲取的只有567。

 

通過源碼驗證上述是否成立:

applyDimension方法就是通過輸入的任何值轉換成px,也就是說,該方法是任何單位和px的換算關系。

COMPLEX_UNIT_DIP就是dip單位,就是平時說的dp。和px的換算關系是

value* metrics.density;

metrics.density是密度,默認值是

SystemProperties.getInt("qemu.sf.lcd_density",SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT))/ 160

160是中密度屏幕的標准dpi

所以屏幕密度density=設備dpi/160

DENSITY_DEFAULT=160

densityDpi=SystemProperties.getInt("qemu.sf.lcd_density",SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT))/DENSITY_DEFAULT

density=densityDpi/DENSITY_DEFAULT

scaledDensity=density

xdpi=densityDpi

ydpi=densityDpi

但是實際上得到的xdpi!=ydpi的

xdpi:x軸屏幕每英寸的實際物理像素


2、換算方程式

 

px=dp*(dpi/160)
px=sp* metrics.scaledDensity   px=sp*(dpi/160)
px=pt*xdpi*(1.0f/72)   pt*(1/72)=inch
px=inch*xdpi
px=mm*xdpi*(1.0f*25.4f)  mm*(1.0f/25.4f)=inch

 

易亂點:

分辨率1080*1920單位是像素,有的認為單位是dpi,但是通過源碼驗證,單位就是px

物理尺寸單位是inch

dpi跟設備有關系

只有在dpi=160時,1px=1dp


3、資源查找原則

 

app運行時,系統會根據屬性選擇適配的資源進行展示。如果有符合的資源則使用,反之,當符合的資源不存在時,系統會去尋找最相近的可用資源來代替。但是,查找的屬性不同,查找的順序會有所有差異。

 

res文件夾下的資源文件以優先級從高到低排列,命名規則:資源名-屬性1-屬性2-…..

v15修飾的資源僅用於4.0及以上的設備

w640dp修飾的適配640dp寬度的設備

h720dp修飾的資源適配720dp高度的設備

屏幕密度屬性ldpi、mdpi、hdpi、xhdpi、xxhdpi、nodpi、tvdpi

ldpi=120

mdpi=160

hdpi=240

xhdpi=320

xxhdpi=480

xxxhdpi=640

 

其中nodpi用於開發者不希望系統對圖片進行縮放的情況

tvdpi介於hdpi和mdpi之間。tvdpi一般在213左右,多用於android系統的只能電視,大部分app很少用到

 

對dpi屬性來說,查找的順序為,高dpi的資源優先。例如,沒能找到hdpi的圖片資源,則系統的搜索順序是

drawable-xhdpi->drawable-xxhdpi->drawable-mdip->drawable->drawable->drawable-ldpi。

這裡drawable被認為比drawable-ldpi更接近hdpi。

 

有時候,我們的圖片資源不一定是從drawable文件夾中讀取的,還有可能是從sd卡上讀取的,或者從網絡上下載的。這個時候,我們需要注意,默認情況下,通過BitmapFactory.decodeFile()函數生成的圖片被認為是MDPI的,如果想讓圖片也獲得與drawable文件夾相似的縮放能力,則需要通過BitmapFactory.Option.inDensity屬性設置(例如如果圖片是為hdpi准備的,則設置為240)。

 

對於screan size,查找的順序則是小尺寸優先,大尺寸放棄。例如,在Galaxy note 2上執行apk時,如果未能找到layout-large資源,則查找順序為:layout-normal->layout->layout-small,不會查找layout-xlarge。


4、屏幕適配方案一

 

步驟:

1)假設設計圖的基准是720*1280,那麼在設計圖中1px對於1920*1080分辨率的手機應該是1.5px


\

\

 

在布局文件中就可以直接使用像素標識了,其實本質上是百分比

布局文件中的使用,比如說現在做一個670*80px的按鈕,在density=1的時候,1dp=1px,在density=2.0的手機,1px=2.0dp,在density=1.5的手機中1px=1.5dp

如果使用dp設置這個button的大小,以2.0為基准,設置大小335*40dp,

在density=1.5的手機上,實際占的大小是502.5*60px。如果手機的分辨率是480*800px的就會出現button顯示不全的情況。

 

但是,使用上面指定分辨率屬性資源的,根據不同的手機分辨率應用自動尋找對應的資源文件。dimen_670_dip*dimen_80_dip在分辨率720*1280手機中是670*80px

在1080*1920分辨率的手機中是1005*120px。不需要計算就可以得到相應的尺寸。(不需要人為去計算,根據資源查找原則,系統會自動選擇最適合屏幕的資源)

 


 

因為大小按照不同的手機不同的分辨率進行了適配,但是字體也要進行適配。不然大小變小了,字體沒有適配就會出現太小或太大的問題。

pt和sp的換算關系還跟用戶的設置有關系,所以最好的方法就是,字體大小也使用px單位的換算。


5、屏幕適配方案二-------谷歌百分比布局庫

 

android-support-percent.jar

方案一的適配已經運用在多款互聯網應用,但是方案一的適配有一個缺點,就是會增加apk的大小。

使用谷歌的百分比布局庫就可以解決這個問題

百分比布局庫就是講RelativeLayout換成PercentRelativeLayout,

將FrameLayout換成PercentFrameLayout

支持寬高設置和margin設置

 

Eclipse中直接將jar復制進libs文件夾,並依賴庫percent

F:\Android\SDK\extras\android\support\percent

sdk路徑/extras/android/support/percent

AndroidStudio在build.gradle中添加compile 'com.android.support:percent:22.2.0'

使用示例

 


        
    

6、常用方法

 

/**
     * 根據手機的分辨率從 dp 的單位 轉成為 px(像素)
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 根據手機的分辨率從 px(像素) 的單位 轉成為 dp
     */
    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }


    public static int getScreenWidth(Activity activity){
        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        int screenWidth = dm.widthPixels;
        return screenWidth;
    }

    public static int getScreenHeigth(Activity activity){
        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        int screenHeigh = dm.heightPixels;
        return screenHeigh;
    }


    public static int measureHeight(View view){

        int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
        int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
        view.measure(w, h);
        int height =view.getMeasuredHeight();
        return height;
    }

    public static int measureWidth(View view){
        int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
        int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        view.measure(w, h);
        int width =view.getMeasuredWidth();
        return width;
    }

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved