android 面试题 谈谈屏幕适配

本文介绍了Android屏幕适配的原因,如设备碎片化,然后详细解释了屏幕尺寸、分辨率、像素密度等概念,并提供了四种适配方案:限定符适配、自定义像素适配、百分比适配和修改density适配。其中,自定义像素适配被指出为最佳实践,文章还深入解析了适配的实现原理,并给出了实际应用中的注意事项。
摘要由CSDN通过智能技术生成

面试问你屏幕适配,那么你要知道为什么Android要做屏幕适配,因为Android是开源的, 各大厂商不仅可以对软件定制,还可以对硬件定制,这样就造成市场上不同分辨率的手机超多,现在估计得有几万或者几十万种,这就导致android设备的碎片化很严重。所以还是做ios很辛福啊,下面对一些概念弄清楚

屏幕尺寸:指屏幕的对角线的长度,单位是英寸,1英寸=2.54厘米

屏幕分辨率:是指横纵上的像素点 单位是px   1px = 1个像素点  一般是以纵向像素*横向像素  比如1920*1080   一个屏幕分辨率越高 显示效果就越好

 

屏幕像素密度:是指每英寸上的像素点数  单位是dpi 是dot per inch 的缩写,屏幕像素密度与屏幕尺寸以及屏幕分辨率有关

以Google的Nexus5为例,它的分辨率是1920*1080  它的屏幕尺寸是4.95inch  屏幕像素密度是445 这是怎么计算出来的呢?

1920*1920+1080*1080这值是4852800 然后开根号再除以4.95就得到是445.03175153177745

 

像素:构成图像的最小单位   美工或者设计师使用

dip:density independent pixels   是指密度 与像素无关以160dpi为基准,1dip = 1px  和dp一样

加入有二个设备 一个480*320 密度是160dpi.   另外一台是800*480像素密度是240dpi

比如你要在这二个屏幕上要TextView的宽度充满横屏除了使用match_parent还可以使用如下:

我们知道480*320 它的宽度是320px,它是以160dpi为基准的,1px = 1dip  那么它的宽度就是320px就可以 但是在800*480也就是说它的宽度是480px,该如何计算呢?这个也很简单,240/160=1/x;  求这x是多少1.5 相当于1dp = 1.5px  那么它的宽度就是320*1.5 其实这就是我们做屏幕适配使用到的核心技术,想要适配所有手机都是这么适配的。

 

我们在创建Android项目的时候 系统会帮助我们生成

drawable_mdpi

drawable_hdpi

drawable_xdpi

drawable_xxdpi

drawable_xxxdpi

对应的密度如下:

上面是讲了基本的概念, 下面谈谈如何去适配?

第一种方案:限定符适配

分辨率限定符  drawable-hdpi  drawable-xdpi   drawable-xxdpi  

尺寸限定符layout-small  layout-large

最小宽度限定符:values-sw360dp values-sw384dp

屏幕方向限定符:layout_port layout-land

这种方案几乎不用,除非在一些很小公司 做出来的app没啥人用, 大点的额公司肯定不用这套方案,比如我一张图片要放在不同的分辨率下  不但给美工同事添加了工作量,app打包后体积一定会增大,维护起来很麻烦。

 

第二种方案:自定义像素适配

这种适配目前是最好的,几乎能适配市面上所有的适配  当初在上面公司 交给test in 一个三方的测试公司, 测试了600多设备  都没出现问题,所以这种很靠谱

实现方案:以美工的设计尺寸为原始尺寸,根据不同设备的密度  计算出宽和高  

代码如下:

public class UIAdapter {
    private static volatile  UIAdapter instance = null;
    //设计师的参考尺寸
    private static final float defaultWidth = 1080;
    private static final float defaultHeight = 1920;
    //屏幕的真实尺寸
    private int screenWidth;
    private int screenHeight;
    private UIAdapter(){

    }
    public static UIAdapter getInstance(){
        if(null==instance){
            synchronized (UIAdapter.class){
                if(null==instance){
                    instance = new UIAdapter();
                }
            }
        }
        return instance;
    }
    public void init(Context context) {
        if(null==context){
            return;
        }
        WindowManager wm = (WindowManager) context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(displayMetrics);
        if(displayMetrics.widthPixels>displayMetrics.heightPixels){//横屏
            screenWidth = displayMetrics.heightPixels;
            screenHeight = displayMetrics.widthPixels;
        }else{
            screenWidth = displayMetrics.widthPixels;
            screenHeight = displayMetrics.heightPixels-getStatusBarHeight(context);
        }
    }
    /**
     * 获取状态栏高度
     * @param context
     * @return
     */
    public static int getStatusBarHeight(Context context) {
        Resources resources = context.getResources();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        int height = resources.getDimensionPixelSize(resourceId);
        return height;
    }
    public  float scaleX(){
        return screenWidth/defaultWidth;
    }
    public  float scaleY(){
        return screenHeight/defaultHeight;
    }
    public void scaleView(View v, int w, int h, int l, int t, int r, int b) {
        if(v==null){
            return;
        }
        w = (int) (w*scaleX());
        h = (int) (h*scaleY());
        l = (int) (l*scaleX());
        t = (int) (t*scaleY());
        r = (int) (r*scaleX());
        b = (int) (b*scaleY());
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
        if (params != null) {
            params.width = w;
            params.height = h;
            params.setMargins(l, t, r, b);
        }
    }
}

记得在Application初始化下:


public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        UIAdapter.getInstance().init(this);
    }
}

使用:

 UIAdapter.getInstance().scaleView(textview,540,200,0,0,0,0);

如果想显示屏幕的1/3的话就是360了宽度,是根据设计师给出来的宽度进行设置

第三种方案: 百分比适配

这是Google 提出来的一个解决适配方案,想要使用必须添加依赖:

 implementation 'com.android.support:percent:28.0.0'

主要就二个类:

PercentRelativeLayout
PercentFrameLayout
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值