1、屏幕適配是什麼
2、 重要概念講解
3、屏幕適配實戰
4、項目源碼下載php
Android中屏幕適配就是經過對尺寸單位、圖片、文字、佈局這四種類型的資源進行合理的設計和規劃,在佈局時合理利用各類類型的資源,讓佈局擁有適應能力,能在各類設備下保持良好的展示效果。java
屏幕尺寸是指屏幕對角線的長度,單位是英寸,1英寸=2.54釐米android
屏幕分辨率是指橫縱向上的像素點數,單位是px,1px=1個像素點,通常以縱向像素橫向像素,如19201080,分辨率越高,顯示效果越好。app
屏幕像素密度是指每英寸上的像素點數,單位是dpi,屏幕像素密度與屏幕尺寸和屏幕分辨率有關。佈局
(1)安卓裏面獲取屏幕寬和高,也是以px做爲單位的。
(2)在160dpi(即分辨率是480*320)基準下,1dip=1px(也就是px不能適配全部機型),以下圖所示,要充滿屏幕,箭頭的px值是不同的。1dp=那個機型dpi/160px。因此用dp會比px好。學習
(3)在使用sp(設置文字的)時候,使用偶數,不要使用奇數或者小數,最最推薦的是12.14.18,22sp的文字大小(儘可能不要使用12sp如下的大小,用戶可能看不清楚)。測試
安卓軟件運行時,會自動根據屏幕像素去不一樣文件夾加載對應圖片。字體
activity_main2.xml佈局代碼以下:this
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <Button android:layout_width="200dp" android:layout_height="50dp" android:textSize="20sp" android:text="按鈕1"/> <Button android:layout_width="200dp" android:layout_height="50dp" android:layout_marginTop="20dp" android:textSize="20sp" android:text="按鈕2"/> </LinearLayout>
運行結果以下:spa
得出結論:即便使用dp設置控件大小,sp設置字體大小,也是沒法適配全部手機的。由於這是谷歌本身的一個標準。dp是根據屏幕像素和分辨率一塊兒來解決的。可是有些手機像素和分辨率不是對應關係,因此不行。
activity_main3.xml佈局代碼以下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" tools:context=".MainActivity"> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="20sp" android:text="按鈕1"/> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:textSize="20sp" android:text="按鈕2"/> </LinearLayout>
運行結果以下:
得出結論:採用weight,可使得組件按屏幕大小進行放大縮小,weight的計算方式以下:
若是將xml中的android:layout_weight屬性值1和2互換,則結果是相反的,有興趣夥伴能夠下載源碼看看效果。
什麼是.9圖
由於Android有太多的分辨率了,當圓角矩形控件在被拉伸放大的時候,圓角的部分就會出現模糊的狀況。而點九切圖就不一樣,它能夠保證無論你上下仍是左右拉伸,放大均可以保持原有的清晰度。
.9圖存放位置
好比咱們想在屏幕豎屏時候加載什麼佈局,在屏幕橫線時候加載什麼佈局。在手機加載什麼佈局,在平板電腦加載什麼佈局。
該文章暫不展開討論,將在Fragment使用中進行講解。
你們通過上面的學習以後,已經知道有些手機像素和分辨率不是對應關係,沒法使用dp等單位來解決,那麼咱們能夠以某個常見的屏幕分辨率做爲基準,自定義須要適配到的屏幕分辨率的xml文件,以下圖所示:
使用生成器生成對應的文件
生成器代碼(使用320*480做爲基準)以下:
import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintWriter; /** * Created by 吳曉暢 */ public class GenerateValueFiles { private int baseW; private int baseH; private String dirStr = "./res"; private final static String WTemplate = "<dimen name=\"x{0}\">{1}px</dimen>\n"; private final static String HTemplate = "<dimen name=\"y{0}\">{1}px</dimen>\n"; private final static String VALUE_TEMPLATE = "values-{0}x{1}"; //新增文件的分辨率,以x,x;隔開 private static final String SUPPORT_DIMESION = "320,480;480,800;480,854;540,960;600,1024;720,1184;720,1196;720,1280;768,1024;768,1280;800,1280;1080,1812;1080,1920;1440,2560;"; private String supportStr = SUPPORT_DIMESION; public GenerateValueFiles(int baseX, int baseY, String supportStr) { this.baseW = baseX; this.baseH = baseY; if (!this.supportStr.contains(baseX + "," + baseY)) { this.supportStr += baseX + "," + baseY + ";"; } this.supportStr += validateInput(supportStr); System.out.println(supportStr); File dir = new File(dirStr); if (!dir.exists()) { dir.mkdir(); } System.out.println(dir.getAbsoluteFile()); } private String validateInput(String supportStr) { StringBuffer sb = new StringBuffer(); String[] vals = supportStr.split("_"); int w = -1; int h = -1; String[] wh; for (String val : vals) { try { if (val == null || val.trim().length() == 0) continue; wh = val.split(","); w = Integer.parseInt(wh[0]); h = Integer.parseInt(wh[1]); } catch (Exception e) { System.out.println("skip invalidate params : w,h = " + val); continue; } sb.append(w + "," + h + ";"); } return sb.toString(); } public void generate() { String[] vals = supportStr.split(";"); for (String val : vals) { String[] wh = val.split(","); generateXmlFile(Integer.parseInt(wh[0]), Integer.parseInt(wh[1])); } } private void generateXmlFile(int w, int h) { StringBuffer sbForWidth = new StringBuffer(); sbForWidth.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); sbForWidth.append("<resources>"); float cellw = w * 1.0f / baseW; System.out.println("width : " + w + "," + baseW + "," + cellw); for (int i = 1; i < baseW; i++) { sbForWidth.append(WTemplate.replace("{0}", i + "").replace("{1}", change(cellw * i) + "")); } sbForWidth.append(WTemplate.replace("{0}", baseW + "").replace("{1}", w + "")); sbForWidth.append("</resources>"); StringBuffer sbForHeight = new StringBuffer(); sbForHeight.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); sbForHeight.append("<resources>"); float cellh = h *1.0f/ baseH; System.out.println("height : "+ h + "," + baseH + "," + cellh); for (int i = 1; i < baseH; i++) { sbForHeight.append(HTemplate.replace("{0}", i + "").replace("{1}", change(cellh * i) + "")); } sbForHeight.append(HTemplate.replace("{0}", baseH + "").replace("{1}", h + "")); sbForHeight.append("</resources>"); File fileDir = new File(dirStr + File.separator + VALUE_TEMPLATE.replace("{0}", h + "")// .replace("{1}", w + "")); fileDir.mkdir(); File layxFile = new File(fileDir.getAbsolutePath(), "lay_x.xml"); File layyFile = new File(fileDir.getAbsolutePath(), "lay_y.xml"); try { PrintWriter pw = new PrintWriter(new FileOutputStream(layxFile)); pw.print(sbForWidth.toString()); pw.close(); pw = new PrintWriter(new FileOutputStream(layyFile)); pw.print(sbForHeight.toString()); pw.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } public static float change(float a) { int temp = (int) (a * 100); return temp / 100f; } public static void main(String[] args) { //基準大小,好比320.480,其餘則以這個基準進行放大縮小 int baseW = 320; int baseH = 480; String addition = ""; try { if (args.length >= 3) { baseW = Integer.parseInt(args[0]); baseH = Integer.parseInt(args[1]); addition = args[2]; } else if (args.length >= 2) { baseW = Integer.parseInt(args[0]); baseH = Integer.parseInt(args[1]); } else if (args.length >= 1) { addition = args[0]; } } catch (NumberFormatException e) { System.err .println("right input params : java -jar xxx.jar width height w,h_w,h_..._w,h;"); e.printStackTrace(); System.exit(-1); } new GenerateValueFiles(baseW, baseH, addition).generate(); } }
運行代碼,結果會在項目的res文件夾中生成對應的內容,以下圖所示:
舒適提示:上圖每一個文件夾是以320*480做爲基準進行放大縮小後的px值
將上面生成的文件夾複製到實際項目中
複製全部文件夾,右擊studio中的res文件夾進行粘貼
xml佈局中進行引用
activity_main4.xml代碼以下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <Button android:layout_width="@dimen/x200" android:layout_height="@dimen/y30" android:text="按鈕1"/> <Button android:layout_width="@dimen/x200" android:layout_height="@dimen/y30" android:layout_marginTop="@dimen/y30" android:text="按鈕2"/> </LinearLayout>
運行結果以下圖所示:
舒適提示: