Android 软件屏幕适配

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/quejing1992/article/details/82910369

在项目中,之前使用的是分辨率为1280*800的7寸屏幕,由于业务需要,现在更换为1024*600分辨率的7寸屏。更换完成后,由于之前的Android软件没有做屏幕的适配,从而导致软件界面显示不完整。因此需要进行屏幕适配。
此次适配需要达到的目标是在这两种分辨率下,显示的界面相同。

1. 基础知识

在进行屏幕适配之前,先要了解一下与屏幕有关的几个概念:屏幕尺寸、屏幕分辨率、像素密度。

1.1 屏幕尺寸

屏幕尺寸指的是屏幕的对角线长度,单位一般使用英寸(inch)表示。1英寸=2.54厘米。

1.2 屏幕分辨率

屏幕分辨率指的是屏幕上面像素的的总和,单位一般采用px(pixel),通常使用横向上的像素数*竖向上的像素数表示,如上面的1280*800,表示横向上有1280个像素,竖向上有800个像素,总共有1280*800个像素,即屏幕的分辨率为1280*800。

1.3 像素密度

像素密度指的是每英寸上有几个像素点,单位采用dpi(dots per inch)。由于我们一般都知道屏幕尺寸和分辨率,因此,采用对角线上的像素点数除以屏幕尺寸得到相应屏幕的像素密度。

根据像素密度不同,可以将设备分为以下几种类型:

像素密度(dpi) 密度类型
120 低密度(ldpi)
160 中密度(mdpi)
240 高密度(hdpi)
320 超高密度(xhdpi)
480 超超高密度(xxhdpi)

1.4 密度无关像素

密度无关像素是Android中特有的一个概念,单位是dp。它的作用是以160dpi屏幕为基准,根据不同的像素密度,1dp代表不同的像素数量,如下表所示。

像素密度 密度类型 换算关系
120 低密度(ldpi) 1dp=0.75px
160 中密度(mdpi) 1dp=1px
240 高密度(hdpi) 1dp=1.5px
320 超高密度(xhdpi) 1dp=2px
480 超超高密度(xxhdpi) 1dp=3px

2. 屏幕适配思路

参考张鸿洋的博客,他里面提到了一种利用百分比的方式进行适配。

其基本思路是:

  • 首先选取一种分辨率作为基准,如480*320

  • 然后其他分辨率的屏幕都以该分辨率为基准,进行长宽的比例换算,博客中使用800*480比例进行换算,得到两个文件,部分内容如下:

      <?xml version="1.0" encoding="utf-8"?>
      <resources>
          <dimen name="x1">1.5px</dimen>
          <dimen name="x2">3px</dimen>
          <dimen name="x3">4.5px</dimen>
          <dimen name="x4">6px</dimen>
          ...
          ...
    
  • 接着在编写布局文件时,使用长度采用

      @dimen/x160
      @dimen/y50
    

使用这种方法后,我们相当于只要针对了基准分辨率的屏幕进行了界面绘制。当采用不同分辨率后,会调用对应的文件,将之前绘制的界面进行缩放,从而实现各个控件所占的百分比相同。

3. 适配文件生成

上面说到基于基准分辨率需要编写待适配的换算文件。每个文件都有几百行,一个一个文件手动编写显然是不科学的,谁也不愿意干。上文提到的博客中有提供生成该文件的源码。下面是我自己编写的一段简单生成相关文件的代码。

建立一个GeneralScreenAdapterFile类,其中的方法如下:

public class GeneralScreenAdapterFile {

        private int[] needAdapterX;
        private int[] needAdapterY;
        private int baseX=480;
        private int baseY=320;
        
        private final String xFileName="x_size_file.xml";
        private final String yFileName="y_size_file.xml";
        private final String rootDirectory="adapterFile/";
        
        /**
        * 设置基准分辨率,默认基准分辨率为480*320
        * @param baseX 横向
        * @param baseY 纵向
        */
        public void setBaseAdapter(int baseX, int baseY) {
                if(baseX >0 && baseY>0) {
                        this.baseX=baseX;
                        this.baseY=baseY;
                }
        }
        
        /**
        * 将需要生产的分辨率导入,分辨率采用字符串形式,利用*分割,格式如:480*320
        * @param needAdapterResolution 需要生成的文件的分辨率
        * @return true 导入成功;false 分辨率有误
        */
        public boolean setResolution(String[] needAdapterResolution) {
                needAdapterX=null;
                needAdapterY=null;
                if(needAdapterResolution == null) {
                        return false;
                }
                int length=needAdapterResolution.length;
                if(length != 0) {
                        needAdapterX=new int[length];
                        needAdapterY=new int[length];
                        for(int i=0;i<length;i++) {
                                String tempResolution=needAdapterResolution[i];
                                String[] temp=tempResolution.split("\\*");
                                if(temp.length != 2) {
                                        return false;
                                }
                                try {
                                        needAdapterX[i]=Integer.parseInt(temp[0]);
                                        needAdapterY[i]=Integer.parseInt(temp[1]);
                                }catch (Exception e) {
                                        // TODO: handle exception
                                        e.printStackTrace();
                                        return false;
                                }
                        }
                }
                return true;
        }

        /**
        * 生成对应的适配文件
        * @return true生成成功;false生成失败
        */
        public boolean generateAdapterFiles() {
                if(needAdapterX == null || needAdapterY == null) {
                        return false;
                }
                int length=needAdapterX.length;
                //生成基准分辨率适配文件
                createFile(baseX, baseY);
                //生成其他分辨率适配文件
                for(int i=0;i<length;i++) {
                        if(!createFile(needAdapterX[i], needAdapterY[i]))
                                return false;
                }
                return true;
        }
        
        /**
        * 生成指定分辨率的适配文件
        * @param x 横向分辨率
        * @param y 纵向分辨率
        * @return true生成成功;false生成失败
        */
        private boolean createFile(int x, int y) {
                //生成分辨率对应的文件夹
                String directoryName="values-"+x+"x"+y+"\\";
                File directoryFile=new File(rootDirectory+directoryName);
                if(!directoryFile.exists()) {
                        directoryFile.mkdirs();
                }
                //生成X适配文件
                try {
                        float factorX=(float)x/baseX;
                        File nowXFile=new File(rootDirectory+directoryName+"/"+xFileName);
                        FileWriter xFileWriter=new FileWriter(nowXFile);
                        xFileWriter.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
                        xFileWriter.write("<resources>\n");
                        xFileWriter.flush();
                        for(int j=1;j<=baseX;j++) {
//				float tempValue=(int)(factorX*j*100)/100f;//保留两位小数
                                float tempValue=(int)(factorX*j+0.5);//四舍五入
                                xFileWriter.write("\t<dimen name=\"x"+j+"\">"+tempValue+"px</dimen>\n");
                                xFileWriter.flush();
                        }
                        xFileWriter.write("</resources>\n");
                        xFileWriter.flush();
                        xFileWriter.close();
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                        return false;
                }
                
                //生成Y适配文件
                try {
                        float factorY=(float)y/baseY;
                        File nowYFile=new File(rootDirectory+directoryName+"/"+yFileName);
                        FileWriter yFileWriter=new FileWriter(nowYFile);
                        yFileWriter.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
                        yFileWriter.write("<resources>\n");
                        yFileWriter.flush();
                        for(int j=1;j<=baseY;j++) {
//				float tempValue=(int)(factorY*j*100)/100f;
                                float tempValue=(int)(factorY*j+0.5);
                                yFileWriter.write("\t<dimen name=\"y"+j+"\">"+tempValue+"px</dimen>\n");
                                yFileWriter.flush();
                        }
                        yFileWriter.write("</resources>\n");
                        yFileWriter.flush();
                        yFileWriter.close();
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                        return false;
                }	
                return true;
        }
}

使用过程中,首先使用setResolution()方法设置待生成的分辨率;如果需要的话可以只用setBaseAdapter()方法设置基准分辨率(默认分辨率为480*320);最后使用generateAdapterFiles()方法生成对应的适配文件。

public static void main(String[] args) {
	GeneralScreenAdapterFile generalScreenAdapterFile=new eneralScreenAdapterFile();
	String[] needAdapterResolution=new String[]{"1280*800", "1024*600"};//设置待生成的分辨率数组,使用*分割
	if(generalScreenAdapterFile.setResolution(needAdapterResolution)) {
		generalScreenAdapterFile.generateAdapterFiles();
	}
}

通过以上方法,在工程的更目录下会出现“adapterFile”文件夹,该文件夹中根据分辨率不同会出现不同的子文件夹,例如:values-1280x800,values-1024*600等,这些子文件夹中就是需要的适配文件。将这些子文件夹拷贝到Android程序的res文件夹下,即可适配不同分辨率屏幕。

利用上述方法可以比较好的解决我这次需要适配的两个屏幕。

猜你喜欢

转载自blog.csdn.net/quejing1992/article/details/82910369
今日推荐