自定义像素适配

Fawziya ·
更新时间:2024-11-10
· 829 次阅读

文章目录一、简述二、实现2.1 通过单例获取当前设备的宽高2.2 获取屏幕的宽高2.3 获取状态栏高度2.4 计算缩放比例三、使用四、完整代码五、注意 一、简述

自定义像素适配,就是以一个特定宽度尺寸的设备为基准,在view的加载过程中,根据当前设备的实际像素换算出目标像素,再作用于控件上。

二、实现 2.1 通过单例获取当前设备的宽高 // 获取单例方法 public static Utils getInstance(Context context){ if (utils == null){ utils = new Utils(context.getApplicationContext()); } return utils; }

当然,单例模式的实现有很多种。这部分是灵活的。

2.2 获取屏幕的宽高

首先得创建屏幕信息显示对象DisplayMetrics,通过它来获取屏幕的宽高,如:displayMetrics.widthPixels

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); } } } }

当然,这里还得注意横竖屏的问题。需要在此进行判断、处理。

2.3 获取状态栏高度

在计算高度时,需要对状态栏的高度按需减去。

//获取状态栏高度,计算高度时需减去状态栏高度 public int getStatusBarHeight(Context context){ // 系统内部定义的获取状态栏高度的方法 int resID = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resID > 0){//如果能取到资源id,就返回 return context.getResources().getDimensionPixelSize(resID); } return 0; }

通过资源id获取,这是系统内部定义的获取状态栏高度的方法。涉及到的几个参数,分别表示获取的状态栏高度、类型、哪个包下

2.4 计算缩放比例

这里还需要兼顾参考设备的宽高,计算缩放比例

//获取水平方向的缩放比例 public float getHorizontalScale(){ return mDisplayWidth / STANDARD_WIDTH; } //获取垂直方向的缩放比例 public float getVerticalScale(){ return mDisplayHeight / STANDARD_HEIGHT; } 三、使用

在自定义view中的onMeasure方法中,重新换算目标值。在该方法中,会遍历所有的子view,对子view的布局属性重新设置、赋值

@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的布局属性,再进行view的测量 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); }

这里需要注意一点,由于onMeasure方法会被多次调用,所以需要加入标志位来确保只会被计算一次。

四、完整代码

Utils .java

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){//如果能取到资源id,就返回 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; } }

ScreenAdapterLayout .java

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的布局属性,再进行view的测量 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); } } 五、注意

单位都得是px!


作者:墨玉浮白



自定义 像素

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章