1. 程式人生 > >Android螢幕適配實踐總結

Android螢幕適配實踐總結

##名詞解釋
####px (pixels) 最為熟悉的畫素,設計圖以此為單位標註;
####dp或dip (device independent pixels) 裝置獨立畫素,與裝置螢幕有關,Android的UI標註以此為單位可最大限度適配不同解析度;
####sp (scaled pixels — best for text size):類似dp, 主要處理字型的大小;

dpi (dots per inch)螢幕畫素密度,描述螢幕畫素整合度。

##單位換算
Android規定以160dpi為標註,此時1dp=1px,如果畫素密度為320dpi,則1dp=2px,以此類推。

##畫素密度分組
這裡寫圖片描述

這裡寫圖片描述
參考連結 http://www.cocoachina.com/android/20151030/13971.html

將切圖放到對應的分組資料夾,系統會自動去適配。

##舉例
假設設計圖為1920px1080px的標註圖,需要執行的裝置為1280px720px ,dpi=160
1、首先按標註圖設定各標註尺寸,放到res\values\dimens.xml檔案中,此檔案中預設為160dpi的尺寸,即1dp=1px,直接按標註圖寫標註值即可;
2、需要適配的裝置尺寸換算,由於dpi不變,仍為160dpi,但解析度變小,在原尺寸上全部乘以係數(1280/1920)/1=2/3=0.666667(末尾會附上轉換的程式碼),將轉換後的dimens.xml檔案放到res\values-sw720dp資料夾下,該檔案及表示最小螢幕寬度為720dp的裝置會在這個資料夾找配置檔案;
3、160dpi對應的畫素密度分組為hdpi,需要將切圖放到res\drawable-hdpi資料夾下;
4、切圖和轉換後的dimens.xml檔案放到對應的資料夾就完成了該裝置的適配。

備註:如果要適配到1920*1080px,240dpi的裝置(1.5x)上,dimens.xml的換算係數為(1920/1920)/1.5=2/3=0.6667
檢視裝置螢幕引數:

DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int dpi = displayMetrics.densityDpi;//dpi值,如160, 240
double density = displayMetrics.density;//以160dpi為基準的畫素密度,如1x,1.5x,2x等

int width = displayMetrics.widthPixels;
//螢幕解析度寬度,單位px,如1920px int height = displayMetrics.heightPixels;//螢幕解析度高度,單位px,如1080px Configuration cfg = getResources().getConfiguration(); int smallScreenWidth = cfg.smallestScreenWidthDp;//最小螢幕寬度,如720dp,系統就是根據該值去查詢到底需要哪一個dimens.xml檔案,例如720dp的裝置會使用res\values-sw720dp資料夾下的dimens.xml //如果需要測試設定讀取到的值為多少,可以加類似如下列印 Log.i(TAG,"left="+Math.round(getResources().getDimension(R.dimen.margin_left)));

一般我們需要知道的資訊是dpi和最小螢幕寬度,即可完成適配。

##總結:
1、res\values\dimens.xml檔案中存放的是160dpi基準尺寸,根據裝置的不同需要換算適配不同的尺寸,換算後放到對應的資料夾中,如res\values-sw720dp限定符為最小螢幕寬度為720dp的裝置會使用此資料夾下的配置尺寸;
2、根據dpi的不同,將切圖放到對應的資料夾下,如160dpi~240dpi的裝置都可將切圖放到res\drawable-hdpi資料夾
3、儘可能的使用match_parent, fill_parent, wrap_content來設定控制元件寬高,少用dp設定寬高,dp只用於設定邊距,避免使用px;

##附件:
####尺寸轉換程式碼

package pxTodp;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 這個類用於將設計圖上的畫素值,轉換為Android裡面的dp
 * 用法:1、在values資料夾的dimens.xml中按設計圖填寫邊距及位置值,單位為dp
 *      2、利用此工具將dimens.xml轉為為新的值,轉換倍數自定義
 */

public class DimenTool {
    private static final String SOURCE_FILE_NAME = "dimens.xml";//注意檔案路徑,是否能找到該檔案,可以將該類提取到eclipse中單獨執行
    private static final String DES_FILE_NAME = "dimens_720.xml";
    private static final double MULTIPLE = 2.0/3.0;//設計圖為1920*1080轉換為1280*720

    public static void gen() {
        File file = new File("dimens.xml");
        BufferedReader reader = null;
        StringBuilder sw720 = new StringBuilder();

        try {
            System.out.println("生成不同解析度:");
            reader = new BufferedReader(new FileReader(file));
            String tempString;
            int line = 1;
            // 一次讀入一行,直到讀入null為檔案結束

            while ((tempString = reader.readLine()) != null) {
                if (tempString.contains("</dimen>")) {
                    String start = tempString.substring(0, tempString.indexOf(">") + 1);
                    String end = tempString.substring(tempString.lastIndexOf("<") - 2);
                    int num = Integer.valueOf(tempString.substring(tempString.indexOf(">") + 1, tempString.indexOf("</dimen>") - 2)).intValue();
                    sw720.append(start).append((int) Math.round(num * MULTIPLE)).append(end).append("\n");
                } else {
                    sw720.append(tempString).append("\n");
                }
                line++;
            }
            reader.close();

            writeFile(DES_FILE_NAME, sw720.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public static void writeFile(String file, String text) {
        PrintWriter out = null;
        try {
            out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            out.println(text);
        } catch (IOException e) {
            e.printStackTrace();
        }
        out.close();
    }

    public static void main(String[] args) {
        gen();
    }
}