说明:本文仅为简单思路,没有实现项目适用的轮子
通过自定义View做屏幕适配的主要思路是:
以一个特定宽度尺寸的设备为参考,在View的加载过程,根据当前
设备的实际像素换算出目标像素,再作用在控件上。
核心思路为在自定义一个ViewGroup,重写onMeasure()
方法,在onMeasure()
方法中遍历子View,以特定宽高尺寸参考,计算出目标像素,作用在子View上,看下主要代码和备注:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
float scaleX = Utils.getInstance(getContext()).getHorizontalScale();//获取横向百分比
float scaleY = Utils.getInstance(getContext()).getVerticalScale();//获取纵向百分比
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);//获取子View
LayoutParams params = (LayoutParams) child.getLayoutParams();
//重新设置子View的布局属性,再进行View的测量
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);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
贴下完整代码:
public class ScreenAdapterLayout extends RelativeLayout {
private boolean flag;
public ScreenAdapterLayout(Context context) {
super(context);
}
public ScreenAdapterLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScreenAdapterLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!flag){
float scaleX = Utils.getInstance(getContext()).getHorizontalScale();
float scaleY = Utils.getInstance(getContext()).getVerticalScale();
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
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);
}
flag = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
其中用到的Utils
类主要用于,定义设计稿参考宽高,获取屏幕显示宽高,判断横竖屏状态,以及获取状态栏高度,代码如下:
public class Utils {
private static Utils utils;
//这里是设计稿参考宽高
private static final float STANDARD_WIDTH = 1080;
private static final float STANDARD_HEIGHT = 1920;
//这里是屏幕显示宽高
private int mDisplayWidth;
private int mDisplayHeight;
private Utils(Context context){
//获取屏幕的宽高
if(mDisplayWidth == 0 || mDisplayHeight == 0){
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (manager != null){
DisplayMetrics displayMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(displayMetrics);
if (displayMetrics.widthPixels > displayMetrics.heightPixels){
//横屏
mDisplayWidth = displayMetrics.heightPixels;
mDisplayHeight = displayMetrics.widthPixels;
}else{
mDisplayWidth = displayMetrics.widthPixels;
mDisplayHeight = displayMetrics.heightPixels - getStatusBarHeight(context);
}
}
}
}
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;
}
public static Utils getInstance(Context context){
if (utils == null){
utils = new Utils(context.getApplicationContext());
}
return utils;
}
//获取水平方向的缩放比例
public float getHorizontalScale(){
return mDisplayWidth / STANDARD_WIDTH;
}
//获取垂直方向的缩放比例
public float getVerticalScale(){
return mDisplayHeight / STANDARD_HEIGHT;
}
}
网友评论