面试问你屏幕适配,那么你要知道为什么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