Android开发之如何通过百分比实现屏幕适配过程学习总结

2016-02-17 11:04 6,524人阅读 暂无评论
版权声明:本文著作权归 TeachCourse所有,未经许可禁止转载,谢谢支持!
转载请注明出处: http://teachcourse.cn/android-percent-layout-summary

概要

百分比屏幕适配方案的原理:布局文件首先确定一个参考的屏幕分辨率,例如:720x1280,然后其他屏幕分辨率的设备计算每个控件在参考分辨率设备上占据的百分比,百分比包括控件的长、宽、margin距离、padding距离,根据分辨率计算在当前设备所占的比例,最后自动选择values文件夹下最接近当前分辨率dimen值

一个简单的例子

在activity_main.xml布局中放置一个Button按钮,参考的分辨率是480x800,美工会以参考分辨率设计图纸,图纸上面标注按钮的宽120px,高50px,然后与父容器底部对齐水平居中,在分辨率不同的480x800、720x1280、1080x1920设备上显示按钮占据的宽和高在当前分辨率上的比例是一样的,显示出来的效果如下图:

001-简单Demo演示

百分比屏幕适配方案开发步骤

第一步:确定参考的分辨率

参考分辨率确定百分比屏幕适配的比例参数,美工MM会根据你确定的参考分辨率开始设计图纸,在图纸上标注布局控件的位置、尺寸大小,单位是px(像素),根据参考分辨率调用鸿洋博客《Android 屏幕适配方案》中提供的工具GenerateValueFiles.java,代码如下:

  1. package cn.teachcourse.hongyang;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileNotFoundException;  
  5. import java.io.FileOutputStream;  
  6. import java.io.PrintWriter;  
  7.   
  8. /* 
  9.  @date 创建于:2016-2-1 
  10.  */  
  11. public class GenerateValueFiles {  
  12.   
  13.     private int baseW;  
  14.     private int baseH;  
  15.   
  16.     private String dirStr = "./res";  
  17.   
  18.     private final static String WTemplate = "<dimen name=\"x{0}\">{1}px</dimen>\n";  
  19.     private final static String HTemplate = "<dimen name=\"y{0}\">{1}px</dimen>\n";  
  20.   
  21.     /** 
  22.      * {0}-HEIGHT 
  23.      */  
  24.     private final static String VALUE_TEMPLATE = "values-{0}x{1}";  
  25.   
  26.     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;";  
  27.   
  28.     private String supportStr = SUPPORT_DIMESION;  
  29.   
  30.     public GenerateValueFiles(int baseX, int baseY, String supportStr) {  
  31.         this.baseW = baseX;  
  32.         this.baseH = baseY;  
  33.   
  34.         if (!this.supportStr.contains(baseX + "," + baseY)) {  
  35.             this.supportStr += baseX + "," + baseY + ";";  
  36.         }  
  37.   
  38.         this.supportStr += validateInput(supportStr);  
  39.   
  40.         System.out.println(supportStr);  
  41.   
  42.         File dir = new File(dirStr);  
  43.         if (!dir.exists()) {  
  44.             dir.mkdir();  
  45.   
  46.         }  
  47.         System.out.println(dir.getAbsoluteFile());  
  48.   
  49.     }  
  50.   
  51.     /** 
  52.      * @param supportStr 
  53.      *            w,h_...w,h; 
  54.      * @return 
  55.      */  
  56.     private String validateInput(String supportStr) {  
  57.         StringBuffer sb = new StringBuffer();  
  58.         String[] vals = supportStr.split("_");  
  59.         int w = -1;  
  60.         int h = -1;  
  61.         String[] wh;  
  62.         for (String val : vals) {  
  63.             try {  
  64.                 if (val == null || val.trim().length() == 0)  
  65.                     continue;  
  66.   
  67.                 wh = val.split(",");  
  68.                 w = Integer.parseInt(wh[0]);  
  69.                 h = Integer.parseInt(wh[1]);  
  70.             } catch (Exception e) {  
  71.                 System.out.println("skip invalidate params : w,h = " + val);  
  72.                 continue;  
  73.             }  
  74.             sb.append(w + "," + h + ";");  
  75.         }  
  76.   
  77.         return sb.toString();  
  78.     }  
  79.   
  80.     public void generate() {  
  81.         String[] vals = supportStr.split(";");  
  82.         for (String val : vals) {  
  83.             String[] wh = val.split(",");  
  84.             generateXmlFile(Integer.parseInt(wh[0]), Integer.parseInt(wh[1]));  
  85.         }  
  86.   
  87.     }  
  88.   
  89.     private void generateXmlFile(int w, int h) {  
  90.   
  91.         StringBuffer sbForWidth = new StringBuffer();  
  92.         sbForWidth.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");  
  93.         sbForWidth.append("<resources>");  
  94.         float cellw = w * 1.0f / baseW;  
  95.   
  96.         System.out.println("width : " + w + "," + baseW + "," + cellw);  
  97.         for (int i = 1; i < baseW; i++) {  
  98.             sbForWidth.append(WTemplate.replace("{0}", i + "").replace("{1}",  
  99.                     change(cellw * i) + ""));  
  100.         }  
  101.         sbForWidth.append(WTemplate.replace("{0}", baseW + "").replace("{1}",  
  102.                 w + ""));  
  103.         sbForWidth.append("</resources>");  
  104.   
  105.         StringBuffer sbForHeight = new StringBuffer();  
  106.         sbForHeight.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");  
  107.         sbForHeight.append("<resources>");  
  108.         float cellh = h * 1.0f / baseH;  
  109.         System.out.println("height : " + h + "," + baseH + "," + cellh);  
  110.         for (int i = 1; i < baseH; i++) {  
  111.             sbForHeight.append(HTemplate.replace("{0}", i + "").replace("{1}",  
  112.                     change(cellh * i) + ""));  
  113.         }  
  114.         sbForHeight.append(HTemplate.replace("{0}", baseH + "").replace("{1}",  
  115.                 h + ""));  
  116.         sbForHeight.append("</resources>");  
  117.   
  118.         File fileDir = new File(dirStr + File.separator  
  119.                 + VALUE_TEMPLATE.replace("{0}", h + "")//  
  120.                         .replace("{1}", w + ""));  
  121.         fileDir.mkdir();  
  122.   
  123.         File layxFile = new File(fileDir.getAbsolutePath(), "lay_x.xml");  
  124.         File layyFile = new File(fileDir.getAbsolutePath(), "lay_y.xml");  
  125.         try {  
  126.             PrintWriter pw = new PrintWriter(new FileOutputStream(layxFile));  
  127.             pw.print(sbForWidth.toString());  
  128.             pw.close();  
  129.             pw = new PrintWriter(new FileOutputStream(layyFile));  
  130.             pw.print(sbForHeight.toString());  
  131.             pw.close();  
  132.         } catch (FileNotFoundException e) {  
  133.             e.printStackTrace();  
  134.         }  
  135.     }  
  136.   
  137.     public static float change(float a) {  
  138.         int temp = (int) (a * 100);  
  139.         return temp / 100f;  
  140.     }  
  141.   
  142.     public static void main(String[] args) {  
  143.         int baseW = 320;  
  144.         int baseH = 480;  
  145.         String addition = "";  
  146.         try {  
  147.             if (args.length >= 3) {  
  148.                 baseW = Integer.parseInt(args[0]);  
  149.                 baseH = Integer.parseInt(args[1]);  
  150.                 addition = args[2];  
  151.             } else if (args.length >= 2) {  
  152.                 baseW = Integer.parseInt(args[0]);  
  153.                 baseH = Integer.parseInt(args[1]);  
  154.             } else if (args.length >= 1) {  
  155.                 addition = args[0];  
  156.             }  
  157.         } catch (NumberFormatException e) {  
  158.   
  159.             System.err  
  160.                     .println("right input params : java -jar xxx.jar width height w,h_w,h_..._w,h;");  
  161.             e.printStackTrace();  
  162.             System.exit(-1);  
  163.         }  
  164.   
  165.         new GenerateValueFiles(baseW, baseH, addition).generate();  
  166.     }  
  167.   
  168. }  

第二步:利用GenerateValueFiles.java工具生成不同的values值

布局中的控件宽、高、margin、padding在参考分辨率中按照占据的份额,调用GenerateValueFiles.java工具在项目上一级目录中自动生成res文件夹,里面包含不同分辨率的values值,如下图:

002-生成res文件夹

003-生成不同values文件夹

在上述的SUPPORT_DIMESION变量中扩展添加额外尺寸,重新生成res文件夹,将生成的额外values文件夹添加到项目中即可

第三步:布局调用不同尺寸值

美工MM设计图纸上的分辨率要与第二步GenerateValueFiles.java工具参考分辨率一致,布局控件根据图纸上的尺寸大小添加参考分辨率values文件夹下的dimen值,项目运行在分辨率不同的设置上自动选择values文件夹下对应的dimen值

了解基本概念

分辨率

分辨率表示:屏幕宽的像素x高的像素,通常在手机的“关于手机”设置选项里查看,例如:720x1280

屏幕密度

屏幕密度的单位是dpi,dots per inch,每英寸屏幕上包含的像素点数,drawable文件夹表示成:drawable-ldpi、drawable-mdpi、drawable-hdpi、drawable-xhdpi、drawable-xxhdpi,对应的屏幕密度分别是:120dpi、160dpi、240dpi、320dpi、480dpi,美工做好密度不同的图片,通常放置在上述密度不同的文件夹内,在密度不同的设备上显示不同尺寸的图片效果。

dp和dip

dp即density-independent pixel,密度独立像素,有时候也写dip。标准是160dip.即1dp对应1个pixel,计算公式如:px = dp * (dpi / 160),屏幕密度越大,1dp对应 的像素点越多。

屏幕密度为240,即dpi=240,一个dp与px的关系:dp=px*(160/dpi)=px*(160/240)=0.67px

屏幕尺寸

屏幕尺寸的单位是inch,英寸,比如:5.0寸,4.7寸,4.3寸,详情可以参考http://screensiz.es/phone

实战演示

创建Java项目,复制第一步的GenerateValueFiles.java文件,以720x1280为参考分辨率(注意修改GenerateValueFiles.java中的参考值),生成不同分辨率的values值:320x480、480x800、480x854、540x960、600x1024、720x1184、720x1196、720x1280、768x1024、768x1280、800x1280、1080x1812、1080x1920、1440x2560,如下图:

005-重新生成res文件夹

004-修改参考分辨率

美工根据我们确定的参考分辨率设计图纸,以720x1280为参考分辨率设计的图纸,如下图

006-设计图纸

创建Android项目,按照图纸上面的标注进行布局实现,布局结构如下图:

007-布局结构图

common_header.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="50dp"  
  5.     android:background="@drawable/blue_bg" >  
  6.     <ImageView   
  7.         android:id="@+id/back_iv"  
  8.         android:layout_width="28dp"  
  9.         android:layout_height="28dp"  
  10.         android:src="@drawable/head_back"  
  11.         android:layout_marginLeft="@dimen/x23"  
  12.         android:layout_centerVertical="true"/>  
  13.     <TextView   
  14.         android:id="@+id/display_info"  
  15.         android:layout_width="wrap_content"  
  16.         android:layout_height="wrap_content"  
  17.         android:layout_centerInParent="true"  
  18.         android:text="@string/center_str"  
  19.         android:textSize="@dimen/x38"  
  20.         android:textColor="@color/white"/>  
  21.       
  22. </RelativeLayout>  

left_menu.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.     <RelativeLayout  
  7.         android:id="@+id/ll_ren_detail"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:background="@color/bg_color_my_all" >  
  11.   
  12.         <LinearLayout  
  13.             android:id="@+id/head_icon_ll"  
  14.             android:layout_width="match_parent"  
  15.             android:layout_height="wrap_content"  
  16.             android:gravity="center"  
  17.             android:orientation="vertical" >  
  18.   
  19.             <ImageView  
  20.                 android:id="@+id/left_head_image"  
  21.                 android:layout_width="@dimen/x112"  
  22.                 android:layout_height="@dimen/x112"  
  23.                 android:layout_marginBottom="@dimen/x30"  
  24.                 android:layout_marginTop="@dimen/x115"  
  25.                 android:src="@drawable/head_icon" />  
  26.   
  27.             <TextView  
  28.                 android:id="@+id/left_name_tv"  
  29.                 android:layout_width="wrap_content"  
  30.                 android:layout_height="wrap_content"  
  31.                 android:layout_marginBottom="@dimen/x94"  
  32.                 android:text="@string/not_login_str_title"  
  33.                 android:textColor="@color/name_text_textcolor"  
  34.                 android:textSize="@dimen/x24" />  
  35.         </LinearLayout>  
  36.     </RelativeLayout>  
  37.   
  38.     <View  
  39.         android:id="@+id/yy_line_view01"  
  40.         style="@style/viewline"  
  41.         android:layout_below="@+id/ll_ren_detail" />  
  42.   
  43.     <LinearLayout  
  44.         android:layout_width="match_parent"  
  45.         android:layout_height="match_parent"  
  46.         android:layout_below="@+id/yy_line_view01"  
  47.         android:background="@android:color/white"  
  48.         android:orientation="vertical" >  
  49.   
  50.         <LinearLayout  
  51.             android:id="@+id/left_set_person_info"  
  52.             android:layout_width="match_parent"  
  53.             android:layout_height="@dimen/x98"  
  54.             android:gravity="center_vertical"  
  55.             android:orientation="horizontal" >  
  56.   
  57.             <ImageView  
  58.                 android:layout_width="wrap_content"  
  59.                 android:layout_height="wrap_content"  
  60.                 android:layout_marginLeft="@dimen/x58"  
  61.                 android:layout_marginRight="@dimen/x44"  
  62.                 android:src="@drawable/person_info" />  
  63.   
  64.             <TextView  
  65.                 android:id="@+id/left_set_person_editText"  
  66.                 style="@style/left_tv_style"  
  67.                 android:layout_weight="3"  
  68.                 android:gravity="center_vertical"  
  69.                 android:hint="@string/person_info" />  
  70.   
  71.             <include layout="@layout/line_right_image" />  
  72.         </LinearLayout>  
  73.   
  74.         <include layout="@layout/line_left_bg" />  
  75.   
  76.         <LinearLayout  
  77.             android:id="@+id/left_set_my_service"  
  78.             android:layout_width="match_parent"  
  79.             android:layout_height="@dimen/x98"  
  80.             android:gravity="center_vertical"  
  81.             android:orientation="horizontal" >  
  82.   
  83.             <ImageView  
  84.                 android:layout_width="wrap_content"  
  85.                 android:layout_height="wrap_content"  
  86.                 android:layout_marginLeft="@dimen/x58"  
  87.                 android:layout_marginRight="@dimen/x44"  
  88.                 android:src="@drawable/my_service" />  
  89.   
  90.             <TextView  
  91.                 android:id="@+id/left_set_my_editText"  
  92.                 style="@style/left_tv_style"  
  93.                 android:layout_weight="3"  
  94.                 android:gravity="center_vertical"  
  95.                 android:hint="@string/my_service_title" />  
  96.   
  97.             <include layout="@layout/line_right_image" />  
  98.         </LinearLayout>  
  99.   
  100.         <include layout="@layout/line_left_bg" />  
  101.   
  102.         <LinearLayout  
  103.             android:id="@+id/left_set_message"  
  104.             android:layout_width="match_parent"  
  105.             android:layout_height="@dimen/x98"  
  106.             android:gravity="center_vertical"  
  107.             android:orientation="horizontal" >  
  108.   
  109.             <ImageView  
  110.                 android:layout_width="wrap_content"  
  111.                 android:layout_height="wrap_content"  
  112.                 android:layout_marginLeft="@dimen/x58"  
  113.                 android:layout_marginRight="@dimen/x44"  
  114.                 android:src="@drawable/message_center" />  
  115.   
  116.             <TextView  
  117.                 android:id="@+id/left_set_message_editText"  
  118.                 style="@style/left_tv_style"  
  119.                 android:layout_weight="3"  
  120.                 android:gravity="center_vertical"  
  121.                 android:hint="@string/message" />  
  122.   
  123.             <include layout="@layout/line_right_image" />  
  124.         </LinearLayout>  
  125.   
  126.         <include layout="@layout/line_left_bg" />  
  127.     </LinearLayout>  
  128.   
  129. </RelativeLayout>  

left_menu_main.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <include layout="@layout/common_header" />  
  8.   
  9.     <include layout="@layout/left_menu" />  
  10.   
  11. </LinearLayout>  

MainActivity.java

  1. public class MainActivity extends ActionBarActivity {  
  2.   
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.left_menu_main);  
  7.     }  
  8.   
  9.     @Override  
  10.     public boolean onCreateOptionsMenu(Menu menu) {  
  11.         // Inflate the menu; this adds items to the action bar if it is present.  
  12.         getMenuInflater().inflate(R.menu.main, menu);  
  13.         return true;  
  14.     }  
  15.   
  16.     @Override  
  17.     public boolean onOptionsItemSelected(MenuItem item) {  
  18.         // Handle action bar item clicks here. The action bar will  
  19.         // automatically handle clicks on the Home/Up button, so long  
  20.         // as you specify a parent activity in AndroidManifest.xml.  
  21.         int id = item.getItemId();  
  22.         if (id == R.id.action_settings) {  
  23.             return true;  
  24.         }  
  25.         return super.onOptionsItemSelected(item);  
  26.     }  
  27. }  

测试效果图

008-320x480

009-480x800

010-720x1280

011-1080x1920

关注公众号 扫一扫二维码,加我QQ

如果文章对你有帮助,欢迎点击上方按钮关注作者

来源:TeachCourse每周一次,深入学习Android教程,关注(QQ1589359239或公众号TeachCourse)
转载请注明出处: http://teachcourse.cn/android-percent-layout-summary

资源分享

源码下载
夏天适合喝冰凉的水、饮料吗?为什么喝冰凉的水反而不解渴 夏天适合喝冰凉的水、饮料吗?为
初学Android Studio项目结构第一课 初学Android Studio项目结构第
Activity四种启动模式 Activity四种启动模式
一篇文章,学完TeachCourse2016成长笔记 一篇文章,学完TeachCourse201

发表评论

呲牙 憨笑 坏笑 偷笑 色 微笑 抓狂 睡觉 酷 流汗 鼓掌 大哭 可怜 疑问 晕 惊讶 得意 尴尬 发怒 奋斗 衰 骷髅 啤酒 吃饭 礼物 强 弱 握手 OK NO 勾引 拳头 差劲 爱你

表情