Android中多屏适配

基础概念

屏幕尺寸

  • in(inches)

  • 英寸,长度单位,屏幕物理尺寸的基本单位

    屏幕分辨率

  • px( pixel)

  • 平常所说的1920×1080只是像素数量,也就是1920px×1080px,代表手机高度上有1920个像素点,宽度上有1080个像素点。

屏幕像素密度

  • dpi(dots per inch)
  • 即每英寸多少像素来评价屏幕的显示效果**(px/inch)**。android把屏幕分为一下四种: low(ldpi),medium(mdpi),high(hdpi),extrahigh(xhdpi);
  • 一般情况下的普通屏幕:ldpi是120dpi;mdpi是160dpi;hdpi是240dpi; xdpi是320dpi
    对于屏幕来说,dpi越大,屏幕的精细度越高,屏幕看起来越清楚。

密度无关像素

  • 含义:density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关。
  • 单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果
  • dp为当屏幕每英寸有160个像素点(也就是160dpi),dp与px是等价的。如果每英寸240个像素点呢?1dp->1*240/160=1.5px,即1dp与1.5px相等的。

直接来图片来理解dp吧
这里写图片描述

4.sp: scaled pixels(放大像素). 主要用于字体显示best for textsize。



import android.content.Context;
import android.util.TypedValue;

/**
 * Created by vanHua on 2017/3/9.
 *
 * 常用单位转换的辅助类
 *
 * @author vanHua 
 *
 */

public class DensityUtils {
    private DensityUtils() {
		/* cannot be instantiated */
        throw new UnsupportedOperationException("cannot be instantiated");
    }

    /**
     * dp转px
     *
     * @param context
     * @param dpVal
     * @return
     */
    public static int dp2px(Context context, float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
                context.getResources().getDisplayMetrics());
    }

    /**
     * sp转px
     *
     * @param context
     * @param spVal
     * @return
     */
    public static int sp2px(Context context, float spVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,
                context.getResources().getDisplayMetrics());
    }

    /**
     * px转dp
     *
     * @param context
     * @param pxVal
     * @return
     */
    public static float px2dp(Context context, float pxVal) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (pxVal / scale);
    }

    /**
     *
     * @param context
     * @param pxVal
     * @return
     */
    public static float px2sp(Context context, float pxVal) {
        return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
    }
}

在代码里面新加一个带main的java类,事实上它是自动的帮你在原来的values/dimens.xml的基础上自动的帮你把每个dimen乘以你所需要的乘积然后将结果写回对应的dimens.xml里面,这大大的减轻了工作量,以后每次修改dimens.xml只要这样子即可:

在values/dimens.xml里面添加或修改变量
跑一边上述java类自动的生成别的dimens.xml
public class DimenTool {
 
    public static void gen() {
 
        File file = new File("./app/src/main/res/values/dimens.xml");
        BufferedReader reader = null;
        StringBuilder sw480 = new StringBuilder();
        StringBuilder sw600 = new StringBuilder();
        StringBuilder sw720 = new StringBuilder();
        StringBuilder sw800 = new StringBuilder();
        StringBuilder w820 = new StringBuilder();
 
 
        try {
            System.out.println("生成不同分辨率:");
            reader = new BufferedReader(new FileReader(file));
            String tempString;
            int line = 1;
            // 一次读入一行,直到读入null为文件结束
 
            while ((tempString = reader.readLine()) != null) {
 
                if (tempString.contains("</dimen>")) {
                    //tempString = tempString.replaceAll(" ", "");
                    String start = tempString.substring(0, tempString.indexOf(">") + 1);
                    String end = tempString.substring(tempString.lastIndexOf("<") - 2);
                    double num = Double.valueOf(tempString.substring(tempString.indexOf(">") + 1, tempString.indexOf("</dimen>") - 2));
//这里的换算比例现在还不知道为什么是这样,等找到了在更新上来
                    sw480.append(start).append((int) Math.round(num * 0.6)).append(end).append("\n");
                    sw600.append(start).append((int) Math.round(num * 0.75)).append(end).append("\n");
                    sw720.append(start).append((int) Math.round(num * 0.9)).append(end).append("\n");
                    sw800.append(tempString).append("\n");
                    w820.append(tempString).append("\n");
 
                } else {
                    sw480.append(tempString).append("\n");
                    sw600.append(tempString).append("\n");
                    sw720.append(tempString).append("\n");
                    sw800.append(tempString).append("\n");
                    w820.append(tempString).append("\n");
                }
                line++;
            }
            reader.close();
            System.out.println("<!--  sw480 -->");
            System.out.println(sw480);
            System.out.println("<!--  sw600 -->");
            System.out.println(sw600);
 
            System.out.println("<!--  sw720 -->");
            System.out.println(sw720);
            System.out.println("<!--  sw800 -->");
            System.out.println(sw800);
 
            String sw480file = "./app/src/main/res/values-sw480dp-land/dimens.xml";
            String sw600file = "./app/src/main/res/values-sw600dp-land/dimens.xml";
            String sw720file = "./app/src/main/res/values-sw720dp-land/dimens.xml";
            String sw800file = "./app/src/main/res/values-sw800dp-land/dimens.xml";
            String w820file = "./app/src/main/res/values-w820dp/dimens.xml";
            writeFile(sw480file, sw480.toString());
            writeFile(sw600file, sw600.toString());
            writeFile(sw720file, sw720.toString());
            writeFile(sw800file, sw800.toString());
            writeFile(w820file, w820.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
 
    public static void writeFile(String file, String text) {
        PrintWriter out = null;
        try {
            out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            out.println(text);
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        out.close();
    }
 
    public static void main(String[] args) {
        gen();
    }
}

android适配之重要的问题就是 如何让你的应用能在各种终端上运行。首先就要考虑不同的分辨率和尺寸

屏幕适配主要从图片和距离(文字)进行下手,正常的适配是考虑各种各样的分辨率。比如480800;
1280
800;1920*1080等。因此资源文件夹创建很多子文件夹

距离(文字)适配

  
   Configuration config = getResources().getConfiguration();
   int smallestScreenWidth = config.smallestScreenWidthDp;

这个获取出来的值。我们需要建立对应的Values-sw{smallestScreenWidth}dp文件进行适配。这边是对文字和距离尺寸的适配

图片适配

文字和空间宽度适配后,大家可能发现部分的ImageView或者ImageButton部分还有些变大或者变小,有的变模糊了,
这里需要美工提供多套图片,
开发时应该图片以160dpi为基准。同时提供不同的基于baseLine的图片的方法或者缩小

mdpi  120dpi~160dpi
hdpi  160dpi~240dpi
xhdpi  240dpi~320dpi
xxhpi  320dpi~480dpi
xxxhdpi 480dpi~640dpi

对于drawable 比如shape或者selector的xml形式的drawable,它本身不是图片而是一个xml文件。
但是他们都会引用真实的drawable图片。对于这种xnl最好放在无dpi影响的drawable文件中(无后缀)
你至少要提供一个xxxhdpi类型的启动图标,因为Android会帮你自动缩小图标到对应的别的分辨率上(放大是会变模糊的),这样子可以节省些apk size。
land是横屏,port是竖屏。

基本尺寸定义:

  • px:pixel 像素,电子屏幕上组成一幅图画或照片的最基本单位
  • pt:point 点 ,印刷行业常用单位等于1/72英寸
  • ppi:pixel per inch ,每一寸像素数,该数值越高,则屏幕越细腻
  • dpi:dot per inch 每英寸多少点,该数值越高,则图片越细腻
  • dp:dip ,Density-independent pixel 是安卓开发用的长度单位,1dp表示在屏幕像素点密度为160ppi是1px长度
  • sp:scale-independent pixel android开发用的字体大小单位

换算关系

1.pt和px
公式1:1pt=(DPI/72)px
当photoshop中新建画布的分辨率为72ppi( 即 72dpi时 ), 1pt=1px; 当新建画布分辨率为72*2=144ppi时,1pt=2px

2.ppi和dpi
dpi 最初用于衡量打印物上每英寸的点数密度。DPI值越小图片越不精细
公式2:dpi=ppi

3.ppi计算方法
ppi是指屏幕上的像素密度
公式3:ppi=屏幕对角线上的像素点数/对角线长度=√ (屏幕横向像素点^2 +屏幕纵向像素点^2)/对角线长度

加粗样式4.px和dp
dp为安卓开发时的长度单位,根据不同的屏幕分辨率,与px有不同的对应关系。

1dp定义为屏幕密度值为160ppi时的1px,即,在mdpi时,1dp = 1px。 以mdpi为标准,这些屏幕的密度值比为:ldpi : mdpi : hdpi : xhdpi : xxhdpi = 0.75 : 1 : 1.5 : 2 : 3;
即,在xhdpi的密度下,1dp=2px;在hdpi情况下,1dp=1.5px。其他类推。
公式四: 1dp=(屏幕ppi/ 160)px

以WVGA屏为例,该屏幕为480px*800px,按3.8寸屏算,点密度 √ (480^2 + 800^2) / 3.8 = 245,约等于240,对应于hdpi屏幕,所以该屏幕1dp=1.5px

5.dp和sp

dp和sp都是安卓的开发单位,dp是长度单位,sp是字体单位。sp与dp类似,但是可以根据用户的字体大小首选项进行缩放。Android系统允许用户自定义文字尺寸大小(小、正常、大、超大等等),

公式五:当文字尺寸是“正常”时1sp=1dp,而当文字尺寸是“大”或“超大”时,1sp>1dp。

一般情况下可认为sp=dp。

总结:由于做设计时以xhdpi为模板,xhdpi条件下,1dp=2px。若新建画布时,将画布分辨率设为144ppi,则1pt=2px=1dp。此时,即可将pt等同于dp。标注长度的时候,将长度像素除以2即为dp值。

总结

1,使用wrap_content,fill_parent,或者dp来布局,尽量不要使用px,之前看见过利用layout_weight重要度来布局,等分屏幕,这种方式也挺好的。

2,不同分辨率访问不同的文件夹

可以根据屏幕密度,分辨率,大小来命名不同的文件夹,不同的设备会访问不同的文件夹
例如:drawable-mdpi,drawable-hdpi-1280x800,drawable-large
同样layout等文件夹也可以利用这种方式

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值