众人周知,移动开发分为android和ios,android由于系统是开源,引来大量厂商,在市场上华为,小米,opper,vivo,等等各大手机厂商,由于手机多姿多彩,就引起众人头疼的事,就是屏幕适配问题,在本人以往开发经验,华为适配极其很难适配,有的布局明明在模拟器或者真机运行效果差不多,但是在个别手机就有点极为变态,为了在开发过程中避免这种问题,本人也是在不断的学习,和研究来达到在开发过程中考虑到适配的问题,就写下这篇文章,希望各位捧场。
屏幕适配分为:
屏幕适配常见的方式:
图片资源适配
首先要达到屏幕适配,就先要了解屏幕的有关信息
如 1920×1080,是指在手机屏幕的像素点的个数,单位是px,1px = 1 像素点,一般是纵向像素 × 横向像素,意味着高有 1920
个像素点,宽有 1080 个像素点。
指每英寸上的像素点数,单位是 dpi 像素密度和屏幕尺寸和屏幕分辨率有关,它是由对角线的像素点数除以屏幕的大小得到的关系如下:
dp、dip、dpi、sp、px
屏幕适配
屏幕分辨率限定符适配需要在 res 文件夹下创建各种屏幕分辨率对应的 values-xxx 文件夹,如下图
然后根据一个基准分辨率,例如基准分辨率为 1280x720,将宽度分成 720 份,取值为 1px~720px,将高度分成 1280
份,取值为 1px~1280px,生成各种分辨率对应的 dimens.xml 文件。如下分别为分辨率 1280x720 与1920x1080 所对应的横向dimens.xml 文件:
假设设计图上的一个控件的宽度为 720px,
那么布局中就写android:layout_width="@dimen/x720"
,当运行程序的时候,系统会根据设备的分辨率去寻找对应的 dimens.xml 文件。
例如运行在分辨率为 1280x720 的设备上,系统会自动找到对应的 values-1280x720 文件夹下的 lay_x.xml 文件
由上图可知
x720 对应的值为720.px,可铺满该屏幕宽度。运行在分辨率为 1920x1080 的设备上,系统会自动找到对应的 values-1920x1080 文件夹下的 lay_x.xml 文件,
由上图可知
x720 对应的值为 1080.0px,可铺满该屏幕宽度。这样就达到了屏幕适配的要求!
动态适配大概逻辑思维就是:
参照UI设计师提供的设计稿的比例为参考。
然后获取到屏幕的宽高减去状态栏的高度得到实际的宽高,算出宽高的比例,然后在系统绘画的时候拿出每个子View进行缩放。
//这里是设计稿参考宽高
private static final float STANDARD_WIDTH = 1080;
private static final float STANDARD_HEIGHT = 1920;
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (windowManager != null) {
//宽高获取
DisplayMetrics displayMetrics = new DisplayMetrics();
//如果不是NavigationBar沉浸式(不包含NavigationBar)
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
//获取状态栏高度
public int getStatusBarHeight(Context context) {
int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
return context.getResources().getDimensionPixelSize(resId);//获取具体的像素值
}
return 0;
}
if (displayMetrics.widthPixels > displayMetrics.heightPixels) {
//横屏
mDisplayWidth = displayMetrics.heightPixels;
mDisplayHeight = displayMetrics.widthPixels - getStatusBarHeight(context);
} else {
//竖屏
mDisplayWidth = displayMetrics.widthPixels;
mDisplayHeight = displayMetrics.heightPixels - getStatusBarHeight(context);
}
}
4:最后算出适配的比例:
//获取水平方向的缩放比例
public float getHorizontalScale() {
return mDisplayWidth / STANDARD_WIDTH;
}
//获取垂直方向的缩放比例
public float getVerticalScale() {
return mDisplayHeight / (STANDARD_HEIGHT - getStatusBarHeight(mContext));
}
5:循环拿出每个字View进行等比缩放:
//子View个数
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
进行每个字view同等比缩放
LayoutParams params = (LayoutParams) child.getLayoutParams();
params.width = (int) (params.width * scaleX);
params.height = (int) (params.height * scaleY);
params.leftMargin = (int) (params.leftMargin * scaleX);
params.rightMargin = (int) (params.rightMargin * scaleX);
params.topMargin = (int) (params.topMargin * scaleY);
params.bottomMargin = (int) (params.bottomMargin * scaleY);
child.setPadding((int) (child.getPaddingLeft() * scaleX), (int) (child.getPaddingTop() * scaleY),
(int) (child.getPaddingRight() * scaleX), (int) (child.getPaddingBottom() * scaleY));
最后建议
一般情况下采用普通适配方式就好,在万不得已的情况下,再去使用三方。
屏幕适配常见方式
1、避免写死控件尺寸,使用wrap_content, match_parent
2、LinearLayout xxx:weight="0.5“
3、RelativeLayout xxx:layout_centerInParent=“true” …
4、ContraintLayout xxx:layout_constraintLeft_toLeftOf=“parent”…
5、Percent-support-lib xxx:layout_widthPercent=“30%” …