概要
百分比屏幕适配方案的原理:布局文件首先确定一个参考的屏幕分辨率,例如:720x1280,然后其他屏幕分辨率的设备计算每个控件在参考分辨率设备上占据的百分比,百分比包括控件的长、宽、margin距离、padding距离,根据分辨率计算在当前设备所占的比例,最后自动选择values文件夹下最接近当前分辨率dimen值
一个简单的例子
在activity_main.xml布局中放置一个Button按钮,参考的分辨率是480x800,美工会以参考分辨率设计图纸,图纸上面标注按钮的宽120px,高50px,然后与父容器底部对齐水平居中,在分辨率不同的480x800、720x1280、1080x1920设备上显示按钮占据的宽和高在当前分辨率上的比例是一样的,显示出来的效果如下图:
百分比屏幕适配方案开发步骤
第一步:确定参考的分辨率
参考分辨率确定百分比屏幕适配的比例参数,美工MM会根据你确定的参考分辨率开始设计图纸,在图纸上标注布局控件的位置、尺寸大小,单位是px(像素),根据参考分辨率调用鸿洋博客《Android 屏幕适配方案》中提供的工具GenerateValueFiles.java,代码如下:
- package cn.teachcourse.hongyang;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.PrintWriter;
- /*
- @date 创建于:2016-2-1
- */
- 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";
- /**
- * {0}-HEIGHT
- */
- private final static String VALUE_TEMPLATE = "values-{0}x{1}";
- 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());
- }
- /**
- * @param supportStr
- * w,h_...w,h;
- * @return
- */
- 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) {
- 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();
- }
- }
第二步:利用GenerateValueFiles.java工具生成不同的values值
布局中的控件宽、高、margin、padding在参考分辨率中按照占据的份额,调用GenerateValueFiles.java工具在项目上一级目录中自动生成res文件夹,里面包含不同分辨率的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,如下图:
美工根据我们确定的参考分辨率设计图纸,以720x1280为参考分辨率设计的图纸,如下图
创建Android项目,按照图纸上面的标注进行布局实现,布局结构如下图:
common_header.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="50dp"
- android:background="@drawable/blue_bg" >
- <ImageView
- android:id="@+id/back_iv"
- android:layout_width="28dp"
- android:layout_height="28dp"
- android:src="@drawable/head_back"
- android:layout_marginLeft="@dimen/x23"
- android:layout_centerVertical="true"/>
- <TextView
- android:id="@+id/display_info"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:text="@string/center_str"
- android:textSize="@dimen/x38"
- android:textColor="@color/white"/>
- </RelativeLayout>
left_menu.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <RelativeLayout
- android:id="@+id/ll_ren_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@color/bg_color_my_all" >
- <LinearLayout
- android:id="@+id/head_icon_ll"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:orientation="vertical" >
- <ImageView
- android:id="@+id/left_head_image"
- android:layout_width="@dimen/x112"
- android:layout_height="@dimen/x112"
- android:layout_marginBottom="@dimen/x30"
- android:layout_marginTop="@dimen/x115"
- android:src="@drawable/head_icon" />
- <TextView
- android:id="@+id/left_name_tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/x94"
- android:text="@string/not_login_str_title"
- android:textColor="@color/name_text_textcolor"
- android:textSize="@dimen/x24" />
- </LinearLayout>
- </RelativeLayout>
- <View
- android:id="@+id/yy_line_view01"
- style="@style/viewline"
- android:layout_below="@+id/ll_ren_detail" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@+id/yy_line_view01"
- android:background="@android:color/white"
- android:orientation="vertical" >
- <LinearLayout
- android:id="@+id/left_set_person_info"
- android:layout_width="match_parent"
- android:layout_height="@dimen/x98"
- android:gravity="center_vertical"
- android:orientation="horizontal" >
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/x58"
- android:layout_marginRight="@dimen/x44"
- android:src="@drawable/person_info" />
- <TextView
- android:id="@+id/left_set_person_editText"
- style="@style/left_tv_style"
- android:layout_weight="3"
- android:gravity="center_vertical"
- android:hint="@string/person_info" />
- <include layout="@layout/line_right_image" />
- </LinearLayout>
- <include layout="@layout/line_left_bg" />
- <LinearLayout
- android:id="@+id/left_set_my_service"
- android:layout_width="match_parent"
- android:layout_height="@dimen/x98"
- android:gravity="center_vertical"
- android:orientation="horizontal" >
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/x58"
- android:layout_marginRight="@dimen/x44"
- android:src="@drawable/my_service" />
- <TextView
- android:id="@+id/left_set_my_editText"
- style="@style/left_tv_style"
- android:layout_weight="3"
- android:gravity="center_vertical"
- android:hint="@string/my_service_title" />
- <include layout="@layout/line_right_image" />
- </LinearLayout>
- <include layout="@layout/line_left_bg" />
- <LinearLayout
- android:id="@+id/left_set_message"
- android:layout_width="match_parent"
- android:layout_height="@dimen/x98"
- android:gravity="center_vertical"
- android:orientation="horizontal" >
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/x58"
- android:layout_marginRight="@dimen/x44"
- android:src="@drawable/message_center" />
- <TextView
- android:id="@+id/left_set_message_editText"
- style="@style/left_tv_style"
- android:layout_weight="3"
- android:gravity="center_vertical"
- android:hint="@string/message" />
- <include layout="@layout/line_right_image" />
- </LinearLayout>
- <include layout="@layout/line_left_bg" />
- </LinearLayout>
- </RelativeLayout>
left_menu_main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <include layout="@layout/common_header" />
- <include layout="@layout/left_menu" />
- </LinearLayout>
MainActivity.java
- public class MainActivity extends ActionBarActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.left_menu_main);
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
- if (id == R.id.action_settings) {
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
- }
测试效果图
当前文章价值3.91元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)
你可能感兴趣的文章
转载请注明出处: https://www.teachcourse.cn/android-percent-layout-summary ,谢谢支持!