版权声明:本文为HaiyuKing原创文章,转载请注明出处!html
这里只是根据参考资料整理下,具体内容请阅读参考资料。git
推荐1倍效果图,即采用 720 * 360 大小( 1280 *720:两倍图 \ 1920 * 1080: 三倍图),最主要的缘由就是1px = 1dp,效果图标多大的px,布局就写多大dp。github
1. 每英寸中的像素数(假如设备分辨率为320*240,屏幕长2英寸宽1.5英寸,dpi=320/2 = 240/1.5 =160)
2. 对应于DisplayMetrics类中属性densityDpi的值;
3. 固然这种宽和高的dpi都相同的状况如今已经不多见,因此实际计算方式见下图;app
像素密度(dpi)、屏幕尺寸、分辨率三者关系:ide
举例说明:屏幕分辨率为:1920*1080,屏幕尺寸为5吋的话,那么dpi为440:svg
1. 每平方英寸中的像素数(density = dpi / 160 );
3. 对应于DisplayMetrics类中属性density的值;
4. 可用于px与px与dip的互相转换 :dp = px / density ;工具
720P,和1080P的手机,dpi是不一样的,这也就意味着,不一样的分辨率中,1dp对应不一样数量的px(720P中,1dp=2px,1080P中1dp=3px)。布局
1.不一样设备有不一样的显示效果,不依赖像素(dp = px / density = px / (dpi / 160) )
2.dpi(像素密度)为160 的设备上1dp = 1px。字体
public class Dp2Px { public static int dp2px(Context context, int dp) { return (int) (dp * context.getResources().getDisplayMetrics().density + 0.5); } public static int px2dp(Context context, int px) { return (int) (px / context.getResources().getDisplayMetrics().density + 0.5); } }
说明:0.5 是为了不损失精度。this
在AndroidStudio的资源目录res下有五个层级图片文件夹,分别用来存放不一样分辨率的图片:
在对应的文件夹下放置不一样分辨率的图片就能够很好的对图片进行适配。
随着屏幕愈来愈大,推荐xxdpi的一套切图,这样就能够向下和向上兼容,节省资源。
建议图标使用svg格式,图片仍然使用png格式,svg的图标大小约是png的1/4,在很大的项目中,图标有不少,这个时候svg的优点就凸显无疑了。
在layout以外,根据不一样分辨率,建立不一样的布局文件夹:
手机会根据分辨率去找设定的不一样大小的layout的布局。实际开发中这种使用的状况很是少,由于占用太多资源,慎用。
当两个或者更多布局占满屏幕宽或高的时候,子布局可使用权重适配,常见于LinearLayout线性布局中。
详细内容请阅读参考资料。如下内容均是引用!
这基本是最原始的Android适配方案。
wrap_content,match_parent,layout_weight等,咱们就要绝不犹豫的使用,并且在高这个维度上,咱们要依照状况设计为可滑动的方式,或者match_parent,尽可能不要写死。总之,全部的适配方案都不是用来取代match_parent,wrap_content的,而是用来完善他们的。
(1)这只能保证咱们写出来的界面适配绝大部分手机,部分手机仍然须要单独适配;
为何dp只解决了90%的适配问题,由于并非全部的1080P的手机dpi都是480,好比Google 的Pixel2(1920*1080)的dpi是420,也就是说,在Pixel2中,1dp=2.625px,这样会致使相同分辨率的手机中,这样,一个100dp*100dp的控件,在通常的1080P手机上,可能都是300px,而Pixel 2 中 ,就只有262.5px,这样控件的实际大小会有所不一样。
(2)这种方式没法快速高效的把设计师的设计稿实现到布局代码中,经过dp直接适配,咱们只能让UI基本适配不一样的手机,可是在设计图和UI代码之间的鸿沟,dp是没法解决的,由于dp不是真实像素。并且,设计稿的宽高每每和Android的手机真实宽高差异极大,以咱们的设计稿为例,设计稿的宽高是375px*750px,而真实手机可能广泛是1080*1920;那么在平常开发中咱们是怎么跨过这个鸿沟的呢?基本都是经过百分比啊,或者经过估算,或者设定一个规范值等等。总之,当咱们拿到设计稿的时候,设计稿的ImageView是128px*128px,当咱们在编写layout文件的时候,却不能直接写成128dp*128dp。在把设计稿向UI代码转换的过程当中,咱们须要耗费至关的精力去转换尺寸,这会极大的下降咱们的生产力,拉低开发效率。
根据市面上手机分辨率的占比分析,咱们选定一个占比例值大的(好比1280*720)设定为一个基准,而后其余分辨率根据这个基准作适配。
基准的意思(好比320*480的分辨率为基准)是:
宽为320,将任何分辨率的宽度分为320份,取值为x1到x320
长为480,将任何分辨率的高度分为480份,取值为y1到y480
例如对于800 * 480的分辨率设备来说,须要在项目中values-800x480目录下的dimens.xml文件中的以下设置(固然了,能够经过工具自动生成):
<?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="x1">1.5px</dimen> <dimen name="x2">3.0px</dimen> <dimen name="x3">4.5px</dimen> <dimen name="x4">6.0px</dimen> <dimen name="x5">7.5px</dimen>
能够看到x1 = 480 / 基准 = 480 / 320 = 1.5 ;它的意思就是一样的1px,在320/480分辨率的手机上是1px,在480/800的分辨率的手机上就是1*1.5px,px会根据咱们指定的不一样values文件夹自动适配为合适的大小。
第一,Android不一样分辨率的手机实在太多了,可能你说主流就能够,的确小公司主流就能够,淘宝这种App确定不能只适配主流手机。
第二,控件在设计图上显示的大小以及控件之间的间隙在小分辨率和大分辨率手机上天壤之别,你会发现大屏幕手机上控件超级大。可能你会以为正常,毕竟分辨率不一样。但实际效果大的有些夸张。
第三,设计图(好比360640)上的内容占据屏幕的2/3,按照这种适配,特长手机(29601440 S8)上的内容也会占据2/3,这确定不合理,控件之间的间隙会特别大,一看就不符合设计效果,手机长,内容占据低于2/3才正常,好比可能占据1/3.第四,占据资源大:好几百KB,甚至多达1M或跟多。
这种适配依据的是最小宽度限定符。指的是Android会识别屏幕可用高度和宽度的最小尺寸的dp值(其实就是手机的宽度值),而后根据识别到的结果去资源文件中寻找对应限定符的文件夹下的资源文件。这种机制和上文提到的宽高限定符适配原理上是同样的,都是系统经过特定的规则来选择对应的文件。
举个例子,小米5的dpi是480,横向像素是1080px,根据px=dp(dpi/160),横向的dp值是1080/(480/160),也就是360dp,系统就会去寻找是否存在value-sw360dp的文件夹以及对应的资源文件。
这套方案对老项目是不太友好的,由于修改了系统的density值以后,整个布局的实际尺寸都会发生改变,若是想要在老项目文件中使用,恐怕整个布局文件中的尺寸均可能要从新按照设计稿修改一遍才行。所以,若是你是在维护或者改造老项目,使用这套方案就要三思了。
经过修改density值,强行把全部不一样尺寸分辨率的手机的宽度dp值改为一个统一的值,这样就解决了全部的适配问题。
好比,设计稿宽度是360px,那么开发这边就会把目标dp值设为360dp,在不一样的设备中,动态修改density值,从而保证(手机像素宽度)px/density这个值始终是360dp,这样的话,就能保证UI在不一样的设备上表现一致了。
UI设计图是按屏幕宽度为360dp来设计的,那么在上述设备上,屏幕宽度其实为1080/(440/160)=392.7dp,也就是屏幕是比设计图要宽的。这种状况下, 即便使用dp也是没法在不一样设备上显示为一样效果的。 同时还存在部分设备屏幕宽度不足360dp,这时就会致使按360dp宽度来开发实际显示不全。加上16:九、4:3甚至其余宽高比层出不穷,宽高比不一样,显示彻底一致就不可能了。
一般下,咱们只须要以宽或高一个维度去适配,好比咱们Feed是上下滑动的,只须要保证在全部设备中宽的维度上显示一致便可,再好比一个不支持上下滑动的页面,那么须要保证在高这个维度上都显示一致,尤为不能存在某些设备上显示不全的状况。
今日头条的适配方式,今日头条适配方案默认项目中只能以高或宽中的一个做为基准,进行适配。
px = dp * density(dp是360dp),想要px正好是屏幕宽度的话,只能修改density。
/** * 适配:修改设备密度 */ private static float sNoncompatDensity; private static float sNoncompatScaledDensity; public static void setCustomDensity(@NonNull Activity activity, @NonNull final Application application) { DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics(); if (sNoncompatDensity == 0) { sNoncompatDensity = appDisplayMetrics.density; sNoncompatScaledDensity = appDisplayMetrics.scaledDensity; // 防止系统切换后不起做用 application.registerComponentCallbacks(new ComponentCallbacks() { @Override public void onConfigurationChanged(Configuration newConfig) { if (newConfig != null && newConfig.fontScale > 0) { sNoncompatScaledDensity = application.getResources().getDisplayMetrics().scaledDensity; } } @Override public void onLowMemory() { } }); } float targetDensity = appDisplayMetrics.widthPixels / 360; // 防止字体变小 float targetScaleDensity = targetDensity * (sNoncompatScaledDensity / sNoncompatDensity); int targetDensityDpi = (int) (160 * targetDensity); appDisplayMetrics.density = targetDensity; appDisplayMetrics.scaledDensity = targetScaleDensity; appDisplayMetrics.densityDpi = targetDensityDpi; final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics(); activityDisplayMetrics.density = targetDensity; activityDisplayMetrics.scaledDensity = targetScaleDensity; activityDisplayMetrics.densityDpi = targetDensityDpi; }
只须要在baseActivity中添加一句话便可。适配就是这么简单。
DisplayUtil.setCustomDensity(this, getApplication());