Android开发面试题

android屏幕适配

2017-11-28  本文已影响160人  古都旧城

1、基础概念

屏幕尺寸

目前市面常见的有5.0、5.5、5.7等尺寸。

屏幕分辨率

屏幕像素密度

/**
     * px转dp
     *
     * @param context
     * @param pxValue
     * @return
     */
    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

dp 介绍

sp 介绍

public static float applyDimension(int unit, float value, DisplayMetrics metrics){
    switch (unit) {    
        case COMPLEX_UNIT_PX:        
            return value;    
        case COMPLEX_UNIT_DIP://------->>dp 基于 density      
            return value * metrics.density;  
        case COMPLEX_UNIT_SP://------->>sp  基于 scaledDensity     
            return value * metrics.scaledDensity;   
        case COMPLEX_UNIT_PT:        
            return value * metrics.xdpi * (1.0f/72);    
        case COMPLEX_UNIT_IN:        
            return value * metrics.xdpi;    
        case COMPLEX_UNIT_MM:        
            return value * metrics.xdpi * (1.0f/25.4f);    
    }    
    return 0;
}

从代码上看 dp 和 sp的差别就是 density 和 scaleDensity的区别,关于这两个字段在源码中可以看到注释scaledDensity会收到用户配置的影响,而density是基于屏幕dpi的,不会受到用户配置影响。
这也就是为什么设置sp单位时字体大小会受到用户配置系统字体的影响.

关于字体大小到底什么时候用dp 什么时候用sp

贴几张图:(系统设置文字变大)
比如下面的父控件限死高度的,导致展示不全、文字过大自动换行、没有设置相关关系导致的重叠。
整体来说需要根据实际需求具体调整,尽量在保证业务逻辑正常的情况下,调优展示效果。


image.png

屏幕尺寸大小、分辨率、像素密度之间的关系:

<span id="jump1">像素密度计算方法</span>

实际像素密度算法

image.png

计算结果不一致?

DPI(dots per inch)和 PPI(pixels per inch)这两个措辞的差别,表面上看来只在于是在谈「dot」还是「pixel」。
* 但实际上 dot 可以指半调印刷的墨点,可以指喷墨打印的墨点,可以指扫描仪的采样点,可以指数字图像的最小单位(即 pixel),可以指屏幕的物理像素,可以指操作系统的抽象像素……在不同的语境下可以指不同的概念。
* 而 pixel 也可以指数字图像的数据 pixel,可以指屏幕物理像素,也可以指代操作系统的抽象像素……在不同语境下的意义也不同。
* 两者经常混用,所以关于dpi和ppi的区别,在不同的用途上面,意思也不同。

结论:在安卓机上面,我们可以理解ppi就是安卓机的真实像素密度,而dpi则是系统的一个内置的值,它接近真实值,但并不是真实的像素密度,它的存在就是为了换算dp、sp的 。

2、适配方案

布局适配

多套布局

针对不同的屏幕尺寸,如果差异过大的话,就需要考虑多套布局的方式来处理

定义布局时候注意事项

一般提前生成一套dimens文件,例如0-400dp,0-30sp,方便使用。

dp sp 适配

dp sp能够让同一数值在不同的分辨率展示出大致相同的尺寸大小。但是当设备差异较大的时候,就无能为力了。适配的问题还需要我们自己去做,一般是生成带标识符的多套dimens文件。

图片适配

使用点九图

范例:


image.png

具体参考:点九图的制作

多套图片

注意事项:

代码动态适配

某些布局要求严格宽高比的地方,可以考虑代码的动态设置宽高;或者为了保持美观又防止过高的一些pop、dialog也需要代码动态按照当前屏幕比例动态设置宽高。

view.getLayoutParams().height = Utils.getRealHeight(mContext, 720, 300);

  /**
     * 获取控件准确的高度(针对满屏的情况)
     *
     * @param context
     * @param width   宽度(可以是相对值,仅仅用来计算宽高比例)
     * @param height  高度(可以是相对值,仅仅用来计算宽高比例)
     * @return 真正的高度
     */
    public static int getRealHeight(Context context, int width, int height) {
        //宽高比
        float aspectRatio = (float) width / (float) height;
        return (int) (Utils.getScreenWidth(context) / aspectRatio);
    }

 /**
     * 根据当前宽度基准算真实高度
     *
     * @param context
     * @param height     宽度基准下的高度
     * @param totalWidth 宽度基准
     * @return
     */
    public static int getRealHeightWithBenchmark(Context context, float height, float totalWidth) {
        return (int) ((Utils.getScreenWidth(context) / totalWidth) * height);
    }


//布局渲染完成后回调设置,防止获取不到宽高度
ViewTreeObserver vto = mRecyclerView.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mRecyclerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                if (mRecyclerView.getHeight() > Utils.getScreenHeight(mContext) / 2) {
                    mRecyclerView.getLayoutParams().height = Utils.getScreenHeight(mContext) / 2;
                }
            }
        });

3、实际适配过程

参考文章:http://blog.csdn.net/wangwangli6/article/details/63258270

上一篇 下一篇

猜你喜欢

热点阅读