屏幕像素参数相关信息表格
屏幕级别 像素密度 每英寸像素数 通常分辨率 分辨率别称 默认图标大小
xxhdpi 3 480 1080*1920 1080P 144*144 重点关注xhdpi 2 320 720*1280 720P 96*96 适配基准hdpi 1.5 240 480*800 WVGA 72*72mdpi 1.0 160 320*480 HVGA 48*48 基准ldpi 0.75 120 240*320 QVGA 36*36
System.out.println(Math.sqrt(Math.pow(1920, 2) + Math.pow(1080, 2)) / 5);//440.58
System.out.println(Math.sqrt(Math.pow(1920, 2) + Math.pow(1080, 2)) / 5.5);//400.53
System.out.println(Math.sqrt(Math.pow(1920, 2) + Math.pow(1080, 2)) / 6.0);//367.15
主流Android手机分辨率
屏幕级别 倍数/比例 像素密度范围 主流分辨率/宽高比 分辨率别称 标准图标大小
xxxhdpi 4 480-640 2560*1440/16:9 2K 192*192
3840*2160/16:9 4K
xxhdpi 3 320-480 1920*1080/16:9 1080P 144*144
xhdpi 2 240-320 1280*720/16:9 720P 96*96
960*540 QHD
hdpi 1.5 160-240 800*480/5:3 WVGA 72*72
854*480/16:9 FWVGA
640*480/4:3 VGA
800*600/4:3 SVGA
mdpi 1.0 120-160 320*480 HVGA 48*48
ldpi 0.75 120 240*320 QVGA 36*36
iPhone系列手机的分辨率
iPhone 3G/3GS 480 x 320
iPhone 4/4S 960 x 640
iPhone 5/5s/5c 1136 x 640
iPhone 6/6s/7 1334*750
iPhone 6p/6sp/7p 1920*1080
名词解释
名词解释
- Px(像素Pixel)
- px即像素,一个像素则表明在屏幕上的一个点,一个显示单位。
- 不同设备上显示时像素数不会变,比如指定控件的长度是100px,那不管分辨率是多少控件长度都是100px。也正是因为如此才产生了屏幕适配问题。
- Screen Size(屏幕的尺寸)
一般所说的手机屏幕大小如5.0英寸,都是指的手机屏幕对角线的长度,而不是手机面积。 - Resolution(屏幕的分辨率)
- 在屏幕上显示的物理像素总和,单位是px,1px=1个像素点。
- 一般以纵向像素*横向像素表示,比如分辨率是1280*720,则指设备垂直方向有1280个像素点,水平方向有720个像素点。
- 需要注意的是:分辨率并不意味着具体的屏幕高宽比,比如分辨率为1280*720的手机屏幕宽高比不一定是1280*720(16:9)。但是为了显示效果和谐,两者一般都是一致的(或者有一丢丢的差距)。
- Dpi(像素密度dots per inch)
- 即“dot per inch”的缩写,指每英寸中的像素数。
- 屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大。
- DisplayMetrics类中属性density的值即为此值,可用于px与dip的互相转换
- dp是一个与密度无关的像素,在不同的像素密度的设备上会自动适配,在逻辑尺寸上,与一个位于像素密度为 160DPI 的屏幕上的像素是一致的,在运行的时候,平台会以目标屏幕的密度作为基准,处理所有需要的DIP缩放操作。假定设备分辨率为320*240,屏幕长2英寸宽1.5英寸,dpi=320/2=240/1.5=160,此160dpi表示手机水平或垂直方向上每英寸距离有160个像素点。
- Dip(设备独立像素Device-independent pixel)
- dp和dip是一个意思,翻译为设备独立像素,或是密度无关像素
- 在Android中,规定以160dpi为基准,此时1dip=1px;如果像素密度是320dpi,则1dip=2px
- 要把DIP像素转换为屏幕像素,可以用这样一个简单的公式: pixels = dips * (density / 160)。
- Sp(放大像素ScaledPixels)
主要用于字体显示(best for textsize)。根据 google 的建议,TextView 的字号最好使用 sp 做单位,而且查看TextView的源码可知 Android 默认使用 sp 作为字号单位。
屏幕适配方法
1、使用不同套图适配
使用套图适配目前来说是针对图片适配的最好适配方法,可以防止图片的失真以及变形。
但针对不同手机进行不同的套图适配,会对UI人员施加过大的工作压力以及对我们app本身也会造成冗余的影响。
2、9path适配
9path图片作为特殊的png图片,可以在特定的情况下对不同机型进行适配,而达到图片不失真的情况。
3、布局适配
使用权重适配。在格局比较明朗的页面中,如果我们能少用具体大小dp值,多用权重,可以在不同的分辨率下都能做到完美适配。
4、使用dimens适配
根据不同values下的dimens进行适配,android项目会自动找寻相适应的dimens,我们可以在多种不同的values下建立dimens文件。
在使用dimens的时候,我们可以在dimens文件中,用px为单位,这样就能达到完美适配。
5、代码适配
我们也可以在java文件中,使用java代码并结合dimens进行适配,相比较xml的话,此种适配方法更迅捷。
Activity
public class MainActivity extends Activity {
private TextView tv_info;
public static final String FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv_info = new TextView(this);
setContentView(tv_info);
tv_info.setText("" + DensityUtils.getStatusBarHeight(this));//状态栏高度。奇酷72。华为75
tv_info.append("
" + DensityUtils.getDisplayMetrics(this));//像素密度。奇酷2.875。华为3.0
tv_info.append("
" + DensityUtils.dp2px(this, 10.3f));
tv_info.append("
" + DensityUtils.px2dp(this, 10.3f));
tv_info.append("
" + DensityUtils.sp2px(this, 10.3f));
tv_info.append("
" + DensityUtils.px2sp(this, 10.3f));
tv_info.append("
" + DensityUtils.getScreenWidth(this) + "-" + DensityUtils.getScreenWidth2(this));
tv_info.append("
屏幕高度:" + DensityUtils.getScreenHeight(this));//奇酷1920。华为1794
tv_info.append("
状态栏高度:" + DensityUtils.getStatusBarHeight(this));//奇酷72。华为75
//需要 root 权限,且可能会被360报毒
// DensityUtils.saveBitmap2Pic(DensityUtils.snapShotWithStatusBar(this), FILE_PATH + "1.png");
// DensityUtils.saveBitmap2Pic(DensityUtils.snapShotWithoutStatusBar(this), FILE_PATH + "2.png");
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
tv_info.append("
标题栏高度:" + DensityUtils.getTitleBarHeight(this));//奇酷161。华为168
}
}
}
演示效果奇酷1080P 华为1080P 华为720P状态栏高度25dp*3=75 25dp*2=50 25dp*2.875=71.875
工具类
package com.bqt.pop;
import java.lang.reflect.Method;
import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Display;
import android.view.Window;
import android.view.WindowManager;
public class DensityUtils {
//******************************************************************************************
// 单位转换
//******************************************************************************************
/**像素密度*/
public static float getDisplayMetrics(Context context) {
return context.getResources().getDisplayMetrics().density;
}
/** dp 转成为 px */
public static int dp2px(Context context, float dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.getResources().getDisplayMetrics());
}
/** px 转成为 dp */
public static int px2dp(Context context, float pxValue) {
return (int) (pxValue / getDisplayMetrics(context) + 0.5f);
}
/** sp转px */
public static int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, context.getResources().getDisplayMetrics());
}
/** px转sp */
public static float px2sp(Context context, float pxVal) {
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
//******************************************************************************************
// 屏幕宽高
//******************************************************************************************
/** 获取屏幕宽 */
public static int getScreenWidth(Context context) {
DisplayMetrics metric = new DisplayMetrics();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metric);
return metric.widthPixels;
}
/** 获取屏幕高,包含状态栏,但不包含某些手机最下面的【HOME键那一栏】,如1920屏幕只有1794 */
public static int getScreenHeight(Context context) {
DisplayMetrics metric = new DisplayMetrics();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metric);
return metric.heightPixels;
}
/** 获取屏幕宽 */
public static int getScreenWidth2(Context context) {
Point point = new Point();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(point);
return point.x;
}
/** 获取屏幕高,包含状态栏,但不包含某些手机最下面的【HOME键那一栏】,如1920屏幕只有1794 */
public static int getScreenHeight2(Context context) {
Point point = new Point();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(point);
return point.y;
}
/** 获取屏幕原始尺寸高度,包括状态栏以及虚拟功能键高度 */
public static int getAllScreenHeight(Context context) {
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
try {
DisplayMetrics displayMetrics = new DisplayMetrics();
Method method = Class.forName("android.view.Display").getMethod("getRealMetrics", DisplayMetrics.class);
method.invoke(display, displayMetrics);
return displayMetrics.heightPixels;
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
//******************************************************************************************
// 状态栏、标题栏、虚拟按键
//******************************************************************************************
/** 状态栏高度,单位px,一般为25dp */
public static int getStatusBarHeight(Context context) {
int height = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
height = context.getResources().getDimensionPixelSize(resourceId);
}
return height;
}
/** 状态栏高度,单位px,【注意】要在onWindowFocusChanged中获取才可以 */
public static int getStatusBarHeight2(Activity activity) {
Rect rect = new Rect();
//DecorView是Window中的最顶层view,可以从DecorView获取到程序显示的区域,包括标题栏,但不包括状态栏。所以状态栏的高度即为显示区域的top坐标值
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
return rect.top;
}
/**标题栏的高度,【注意】要在onWindowFocusChanged中获取才可以*/
public static int getTitleBarHeight(Activity activity) {
int contentTop = activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
return contentTop - getStatusBarHeight(activity);
}
/**获取 虚拟按键的高度 */
public static int getBottomBarHeight(Context context) {
return getAllScreenHeight(context) - getScreenHeight(context);
}
}
2017-7-27
奇酷1080P 华为1080P 华为720P
状态栏高度25dp*3=75 25dp*2=50 25dp*2.875=71.875
package com.bqt.pop;
import java.lang.reflect.Method;
import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Display;
import android.view.Window;
import android.view.WindowManager;
public class DensityUtils {
//******************************************************************************************
// 单位转换
//******************************************************************************************
/**像素密度*/
public static float getDisplayMetrics(Context context) {
return context.getResources().getDisplayMetrics().density;
}
/** dp 转成为 px */
public static int dp2px(Context context, float dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.getResources().getDisplayMetrics());
}
/** px 转成为 dp */
public static int px2dp(Context context, float pxValue) {
return (int) (pxValue / getDisplayMetrics(context) + 0.5f);
}
/** sp转px */
public static int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, context.getResources().getDisplayMetrics());
}
/** px转sp */
public static float px2sp(Context context, float pxVal) {
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
//******************************************************************************************
// 屏幕宽高
//******************************************************************************************
/** 获取屏幕宽 */
public static int getScreenWidth(Context context) {
DisplayMetrics metric = new DisplayMetrics();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metric);
return metric.widthPixels;
}
/** 获取屏幕高,包含状态栏,但不包含某些手机最下面的【HOME键那一栏】,如1920屏幕只有1794 */
public static int getScreenHeight(Context context) {
DisplayMetrics metric = new DisplayMetrics();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metric);
return metric.heightPixels;
}
/** 获取屏幕宽 */
public static int getScreenWidth2(Context context) {
Point point = new Point();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(point);
return point.x;
}
/** 获取屏幕高,包含状态栏,但不包含某些手机最下面的【HOME键那一栏】,如1920屏幕只有1794 */
public static int getScreenHeight2(Context context) {
Point point = new Point();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(point);
return point.y;
}
/** 获取屏幕原始尺寸高度,包括状态栏以及虚拟功能键高度 */
public static int getAllScreenHeight(Context context) {
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
try {
DisplayMetrics displayMetrics = new DisplayMetrics();
Method method = Class.forName("android.view.Display").getMethod("getRealMetrics", DisplayMetrics.class);
method.invoke(display, displayMetrics);
return displayMetrics.heightPixels;
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
//******************************************************************************************
// 状态栏、标题栏、虚拟按键
//******************************************************************************************
/** 状态栏高度,单位px,一般为25dp */
public static int getStatusBarHeight(Context context) {
int height = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
height = context.getResources().getDimensionPixelSize(resourceId);
}
return height;
}
/** 状态栏高度,单位px,【注意】要在onWindowFocusChanged中获取才可以 */
public static int getStatusBarHeight2(Activity activity) {
Rect rect = new Rect();
//DecorView是Window中的最顶层view,可以从DecorView获取到程序显示的区域,包括标题栏,但不包括状态栏。所以状态栏的高度即为显示区域的top坐标值
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
return rect.top;
}
/**标题栏的高度,【注意】要在onWindowFocusChanged中获取才可以*/
public static int getTitleBarHeight(Activity activity) {
int contentTop = activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
return contentTop - getStatusBarHeight(activity);
}
/**获取 虚拟按键的高度 */
public static int getBottomBarHeight(Context context) {
return getAllScreenHeight(context) - getScreenHeight(context);
}
}
2017-7-27