1.系统屏幕密度
系统定义了几个标准dpi值
密度 | 密度值 | 分辨率 |
---|---|---|
ldpi | 120 | 240X320 |
mdpi | 160 | 320X480 |
hdpi | 240 | 480X800 |
xhdpi | 320 | 720X1280 |
xxhdpi | 480 | 1080X1920 |
xxxhdpi | 640 | 3840X2160 |
2.独立像素密度dp
android系统使用mdpi即密度值为160的屏幕作为标准,在这个屏幕上1px=1dp
各个分辨率直接的换算比例:
- ldpi:mdpi:xhdpi:xxhdpi:xxxhdpi=3:4:6:8:12:16
- ldpi:1dp=0.75px
- mdpi:1dp=1px
- hdpi:1dp=1.5px
- xhdpi:1dp=2px
- xxhdpi:1dp=3px
- xxxhdpi:1dp=4px
3.单位转换
public class UIHelper {
/**
* dip转px
*/
public static int dipToPx(Context context, float dip) {
return (int) (dip * context.getResources().getDisplayMetrics().density + 0.5f);
}
/**
* px转dip
*/
public static int pxToDip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 将sp值转换为px值
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
/**
* 将sp值转换为px值
*/
public static int px2sp(Context context, float pxValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
}
其中density就是前面所说的换算比例,这里使用的是公式换算方法进行转换,同时系统也提供了TypedValue帮助我们转换
/**
* dp2px
* @param dp
* @return
*/
protected int dp2px(int dp){
return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,getResources().getDisplayMetrics());
}
/**
* sp2px
* @param dp
* @return
*/
protected int sp2px(int sp){
return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,sp,getResources().getDisplayMetrics());
}
4.常用屏幕工具类
/**
* 获取屏幕分辨率:宽
*/
public static int getScreenPixWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
/**
* 获取屏幕分辨率:高
*/
public static int getScreenPixHeight(Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}
/**
* 获取状态栏的高度
*/
public static int getStatusHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "包名");//包名:com.example.application
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
public static int getStatusHeightFromAndroid(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
public static int getTitleHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("title_bar_height", "dimen", "包名");//包名:com.example.application
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
@TargetApi(14)
public static int getNavigationBarHeight(Activity activity) {
return getNavigationBarHeight((Context) activity);
}
//通过此方法获取navigation bar的高度
@TargetApi(14)
private static int getNavigationBarHeight(Context context) {
Resources res = context.getResources();
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (hasNavBar(context)) {
String key;
boolean mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
if (mInPortrait) {
key = "navigation_bar_height";
} else {
key = "navigation_bar_height_landscape";
}
return getInternalDimensionSize(res, key);
}
}
return result;
}
//通过此方法判断是否存在navigation bar
@TargetApi(14)
private static boolean hasNavBar(Context context) {
Resources res = context.getResources();
int resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android");
if (resourceId != 0) {
boolean hasNav = res.getBoolean(resourceId);
// 查看是否有通过系统属性来控制navigation bar。
if ("1".equals(getNavBarOverride())) {
hasNav = false;
} else if ("0".equals(getNavBarOverride())) {
hasNav = true;
}
return hasNav;
} else {
//可通过此方法来查看设备是否存在物理按键(menu,back,home键)。
return !ViewConfiguration.get(context).hasPermanentMenuKey();
}
}
// 安卓系统允许修改系统的属性来控制navigation bar的显示和隐藏,此方法用来判断是否有修改过相关属性。
// (修改系统文件,在build.prop最后加入qemu.hw.mainkeys=1即可隐藏navigation bar)
// 相关属性模拟器中有使用。
// 当返回值等于"1"表示隐藏navigation bar,等于"0"表示显示navigation bar。
@TargetApi(19)
private static String getNavBarOverride() {
String isNavBarOverride = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
Class c = Class.forName("android.os.SystemProperties");
Method m = c.getDeclaredMethod("get", String.class);
m.setAccessible(true);
isNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
} catch (Throwable e) {
isNavBarOverride = null;
}
}
return isNavBarOverride;
}
//通过此方法获取资源对应的像素值
private static int getInternalDimensionSize(Resources res, String key) {
int result = 0;
int resourceId = res.getIdentifier(key, "dimen", "android");
if (resourceId > 0) {
result = res.getDimensionPixelSize(resourceId);
}
return result;
}