- 定义
- 常见设备的 dp、px、density 的关系
- 常见适配方法
- 常用适配框架
- 推荐文章
推荐1倍效果图,即采用 720 * 360 大小( 1280 *720:两倍图 \ 1920 * 1080: 三倍图),最主要的原因就是1px = 1dp,效果图标多大的 px,布局就写多大 dp。
定义-
像素 - px: 一个小黑点就是像素。
-
尺寸: 屏幕的对角线的长度。
-
分辨率: 整个屏幕一共有多少个点,也就是像素。
-
像素密度 - dpi:
- 每英寸中的像素数。
- 假如设备分辨率为320*240,屏幕长2英寸宽1.5英寸,dpi=320/2 = 240/1.5 =160。
- 对应于DisplayMetrics类中属性densityDpi的值。
- 当然这种宽和高的dpi都相同的情况现在已经很少见。
-
设备独立像素 - dip - dp: 1.不同设备有不同的显示效果,不依赖像素。 2.dp = px / density 3.dp = px / (dpi / 160) 4.dpi(像素密度)为160 的设备上1dp = 1px。
-
放大像素 - sp: 用于字体显示。
-
dp转px、px转dp
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);
}
}
常见设备的 dp、px、density 的关系
- ldpi:
density:0.75
分辨率:240*320
关系:dp = px / 0.75
- mdpi:
density:1
分辨率:320 * 480
关系:dp = px / 1
- hdpi:
density:1.5
分辨率:480 * 800
关系:dp = px / 1.5
- xhdpi:
density:2.0
分辨率:720 * 1280
关系:dp = px / 2
- xxhdpi:
density:3
分辨率:1080 * 1920
关系:dp = px / 3
- 获取参数
//以1280*720为基准:
//获取手机屏幕的宽和高
int widthPixels = getResources().getDisplayMetrics().widthPixels;
int heightPixels = getResources().getDisplayMetrics().heightPixels;
//density
float density = getResources().getDisplayMetrics().density;
//dpi
int densityDpi = getResources().getDisplayMetrics().densityDpi;
//1dp = 多少px
int px = Dp2Px.dp2px(this, 1);
//1px = 多少dp
int dp = Dp2Px.px2dp(this, 1);
输出结果:
E/MainActivity: widthPixels: 720
E/MainActivity: heightPixels: 1280
E/MainActivity: density: 2.0
E/MainActivity: densityDpi: 320
E/MainActivity: px:2
E/MainActivity: dp:1
常见适配方法
1. 图片适配 1.1 图片的查找顺序
- 注意:一般手机 ldpi120dip
220dip
80dip
2.在布局文件中引用
3.新建需要适配的values-XXX(比如values-1280x720,注意规范大值在前)
4.在新建values-1280x720中的dimens.xml文件中
* 180dp
5.所有手机适配找对应的默认的dimens
* 思考:如何计算dpi?如何计算手机密度比?能够用dp适配所有手机吗?
* dp不能适配所有手机;
* 举个例子:按钮占屏幕宽度一半,把宽度设置成160dp,120px和160px和240px可以占屏幕一半,但是360px则小于屏幕一半;
* 如果把宽度设置成180dp,那么360dp可以占屏幕一半,但其他几个又不行。
* 如果要适配所有手机的控件宽度为屏幕宽度的一半,该怎么做呢?用dimen
常用适配框架
今日头条适配
1) 添加依赖
allprojects { repositories { ... maven { url "https://jitpack.io" } } } ------------------------------------------------------ implementation 'me.jessyan:autosize:1.2.1'
2) 基本使用 AndroidAutoSize 在使用上非常简单,只需要填写设计图尺寸这一步即可接入项目;
... ...
有两种类型的布局单位可以选择,一个是 主单位 (dp、sp),一个是 副单位 (pt、in、mm)
- 主单位: 使用 dp、sp 为单位进行布局,侵入性最低,会影响其他三方库页面、三方库控件以及系统控件的布局效果,但 AndroidAutoSize 也通过这个特性,使用 ExternalAdaptManager 实现了在不修改三方库源码的情况下适配三方库的功能
- 副单位: 使用 pt、in、mm 为单位进行布局,侵入性高,对老项目的支持比较好,不会影响其他三方库页面、三方库控件以及系统控件的布局效果,可以彻底的屏蔽修改 density 所造成的所有未知和已知问题,但这样 AndroidAutoSize 也就无法对三方库进行适配
说明:在使用主单位时,design_width_in_dp 和 design_height_in_dp 的单位必须是 dp,计算公式 dp = px / (DPI / 160) 将 px 尺寸转换为 dp 尺寸,如果实在找不到设备的 DPI 那就直接将 px 尺寸除以 3 或者 2 。
3) 进阶使用 在 AndroidManifest.xml 中填写的设计尺寸,是整个项目的全局设计图尺寸,但是如果某些 Activity 页面由于某些原因,这个页面的设计图尺寸和在 AndroidManifest.xml 中填写的设计图尺寸不一样该怎么办呢?则可以让这个页面的 Activity 实现 CustomAdapt ,CustomAdapt 接口的第一个方法可以修改当前页面的设计尺寸。
- 自定义 Activity
public class CustomAdaptActivity extends AppCompatActivity implements CustomAdapt { /** * 是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只能在宽度和高度之中选择一个作为基准进行适配) * * @return {@code true} 为按照宽度进行适配, {@code false} 为按照高度进行适配 */ @Override public boolean isBaseOnWidth() { return false; } /** * 设计图尺寸为 1080px * 1920px, 高换算成 dp 为 960 (1920px / 2 = 960dp) *
* 返回的设计尺寸, 单位 dp * {@link #getSizeInDp} 须配合 {@link #isBaseOnWidth()} 使用, 规则如下: * 如果 {@link #isBaseOnWidth()} 返回 {@code true}, {@link #getSizeInDp} 则应该返回设计图的总宽度 * 如果 {@link #isBaseOnWidth()} 返回 {@code false}, {@link #getSizeInDp} 则应该返回设计图的总高度 * 如果您不需要自定义设计图上的设计尺寸, 想继续使用在 AndroidManifest 中填写的设计图尺寸, {@link #getSizeInDp} 则返回 {@code 0} * * @return 单位 dp */ @Override public float getSizeInDp() { return 667; } }
如果某个 Activity 想放弃适配,让这个 Activity 实现 CancelAdapt 接口即可。
- 自定义 Fragment Fragment 的自定义方式和 Activity 是一样的,只不过在使用前需要先在 App 初始化时开启对 Fragment 的支持
AutoSizeConfig.getInstance().setCustomFragment(true);
- 实现 CustomAdapt
public class CustomAdaptFragment extends Fragment implements CustomAdapt { @Override public boolean isBaseOnWidth() { return false; } @Override public float getSizeInDp() { return 667; } }
4) 万能解决方案 在任何情况下本来适配正常的布局突然出现适配失效,适配异常等问题,只要重写 Activity 的 getResources() 方法即可,如果是 Dialog、PopupWindow 等控件出现适配失效或适配异常,同样在每次 show() 之前调用 AutoSize#autoConvertDensity() 即可。
推荐文章@Override public Resources getResources() { //需要升级到 v1.1.2 及以上版本才能使用 AutoSizeCompat AutoSizeCompat.autoConvertDensityOfGlobal((super.getResources());//如果没有自定义需求用这个方法 AutoSizeCompat.autoConvertDensity((super.getResources(), 667, false);//如果有自定义需求就用这个方法 return super.getResources(); }
- 【今日头条屏幕适配方案终极版正式发布】
- 一种非常好用的 Android 屏幕适配-- smallestWidth