巧用dimens適配多個分辨率2

巧用dimens適配多個分辨率

   讓應用自動適配多個分辨率的屏幕,是每個android程序員的基本功,就好像前端工程師熟練編寫CSS Hack一樣。適配工作中一個重要的工作就是對頁面的調整。

    對於頁面的適配,有很多的方法和技巧。比如佈局中儘量使用wrapcontent ,fillparent,儘量避免具體的數字,由系統來計算合適的寬高;或者爲每個分辨率寫一套佈局文件,設置對應分辨率下控件的寬高;

   爲每一個分辨率寫一套佈局文件雖然夠獨立,夠簡單。但是維護起來成本較高。一個頁面的改動,往往涉及多個佈局文件的改動,讓人很痛苦。

小技巧

   我們可以嘗試只寫一套xml佈局,然後爲該佈局準備多套dimension文件。

   說的詳細一點就是,xml佈局中組件的寬高,不要使用具體的數值來表示,而是配置到dimension文件中。每套dimension文件中數值的大小都是成比例計算出來。

  比如在1980*1080分辨率下,定義 px15表示15px 

<dimen name= "px15" >15px</ dimen>

那麼在 1080 * 720分辨率下,px15要成比例縮小1.5倍, 定義px15 表示 10px

<dimen name= "px15" >10px</ dimen>

所以在xml佈局文件中,我們可以這樣來表示:

<LinearLayout

 

android:layout_width="@dimen/px150"

 

android:layout_height="@dimen/px15"

 

android:orientation="vertical" >

 

    ……

 

    ……

 

</LinearLayout>

  這套佈局文件中的LinearLayout 在1980 * 1080 分辨率下的寬高爲 150 x 15  , 在 1080 * 720分辨率下的寬高就會自動變成 100 * 10

  其他分辨率同理

疑問

  1.有的同學會疑問,這樣不就變成需要維護多套dimenson文件了?換湯不換藥呀?

  其實不然,對於dimension文件我們可以使用代碼來控制生成,數值範圍可以根據自己的情況來。其他分辨率下只需要按照相應比例,使用代碼算一下即可。

  編寫一個這樣的生成代碼並不難,下篇文章我們再給出。

  生成完畢後,Values 目錄結構如下:

  2. 按比例計算佈局一定可靠嗎,會不會出現混亂的現象

  有可能會,這個時候就需要協調佈局使用的寬高,選擇合適的寬高讓頁面在各個分辨率下,看起來不算離譜就行,不一定嚴格按照設計來。大部分頁面是兼容的。

 

以上介紹了使用dimension文件做適配。說道了使用代碼自動生成所有的dimension文件,接下來我們給出相關代碼。

  DimensTools:

package com.example.test;

import java.io.*;

import java.util.*;

/**

* dimens數據自動生成工具

* 

*/

public class DimensTools {

     /** 源文件 */

     static String oldFilePath = "./res/values-nodpi/dimens.xml";

     /** 新生成文件路徑 */

     static String filePath720 = "./res/values-1280x720/dimens.xml";

     /** 新生成文件路徑 */

     static String filePath672 = "./res/values-1280x672/dimens.xml";

     /** 新生成文件路徑 */

     static String filePath1080 = "./res/values-1920x1080/dimens.xml";

     /** 縮小倍數 */

     static float changes = 1.5f;

     public static void main(String[] args) {

          //生成1-1920px

          String allPx= getAllPx();

          DeleteFolder(oldFilePath);

          writeFile(oldFilePath, allPx);

          String st = convertStreamToString(oldFilePath, changes);

          DeleteFolder(filePath720);

          writeFile(filePath720, st);

          DeleteFolder(filePath672);

          writeFile(filePath672, st);

          String st1 = convertStreamToString(oldFilePath, 1f);

          DeleteFolder(filePath1080);

          writeFile(filePath1080, st1);

     }

     /** 讀取文件 生成縮放後字符串 */

     public static String convertStreamToString(String filepath, float f) {

          StringBuilder sb = new StringBuilder();

          try {

               BufferedReader bf = new BufferedReader(new FileReader(filepath));

               String line = null;

               System.out.println("q1");

               String endmark = "px</dimen>";

               String startmark = ">";

               while ((line = bf.readLine()) != null) {

                    if (line.contains(endmark)) {

                         int end = line.lastIndexOf(endmark);

                         int start = line.indexOf(startmark);

                         String stpx = line.substring(start + 1, end);

                         int px = Integer.parseInt(stpx);

                         int newpx = (int) ((float) px / f);

                         String newline = line.replace(px + "px", newpx + "px");

                         sb.append(newline + "\r\n");

                    } else {

                         sb.append(line + "\r\n");

                    }

               }

               System.out.println(sb.toString());

          } catch (IOException e) {

               e.printStackTrace();

          }

          return sb.toString();

     }

     /**

     * 根據路徑刪除指定的目錄或文件,無論存在與否

     *

     * @param sPath

     *            要刪除的目錄或文件

     * @return 刪除成功返回 true,否則返回 false。

     */

     public static boolean DeleteFolder(String sPath) {

          File file = new File(sPath);

          // // 判斷目錄或文件是否存在

          if (!file.exists()) { // 不存在返回 false

               return true;

          } else {

               // 判斷是否爲文件

               if (file.isFile()) { // 爲文件時調用刪除文件方法

                    return deleteFile(sPath);

               } else { // 爲目錄時調用刪除目錄方法

               // return deleteDirectory(sPath);

               }

          }

          return false;

     }

     /** 存爲新文件 */

     public static void writeFile(String filepath, String st) {

          try {

               FileWriter fw = new FileWriter(filepath);

               BufferedWriter bw = new BufferedWriter(fw);

               bw.write(st);

               bw.flush();

               bw.close();

          } catch (IOException e) {

               e.printStackTrace();

          }

     }

     /** 生成全px文件 */

     public static String getAllPx() {

          StringBuilder sb = new StringBuilder();

          try {

               sb.append("<resources>" + "\r\n");

               sb.append("<dimen name=\"screen_width\">1920px</dimen>" + "\r\n");

               sb.append("<dimen name=\"screen_height\">1080px</dimen>" + "\r\n");

               for (int i = 1; i <= 1920; i++) {

                    System.out.println("i="+i);

                    sb.append("<dimen name=\"px" + i + "\">" + i + "px</dimen>"

                              + "\r\n");

               }

               sb.append("</resources>" + "\r\n");

               System.out.println(sb.toString());

          } catch (Exception e) {

               e.printStackTrace();

          }

          return sb.toString();

     }

     /**

     * 刪除單個文件

     *

     * @param sPath

     *            被刪除文件的文件名

     * @return 單個文件刪除成功返回true,否則返回false

     */

     public static boolean deleteFile(String sPath) {

          boolean flag = false;

          File file = new File(sPath);

          // 路徑爲文件且不爲空則進行刪除

          if (file.isFile() && file.exists()) {

               file.delete();

               flag = true;

          }

          return flag;

     }

}

  使用方法:cmd下使用javac ,java命令運行。這樣有點費勁哈,改天用ant寫個自動腳本放上來。

  注:先建立好相應的文件夾,672也按照1.5的比例縮放的。可以根據自己的需要調整。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章