如何在Android中获取屏幕尺寸作为像素

我创建了一些自定义元素,我想以编程方式将它们放置在右上角(从上边缘n像素,从右边缘m像素)。因此,我需要获取屏幕宽度和屏幕高度,然后设置位置:

int px = screenWidth - m;int py = screenHeight - n;

如何在主活动中获得screenWidthscreenHeight

1213969 次浏览

首先获取视图(例如通过findViewById()),然后您可以在视图本身上使用获取Width()

如果您想要以像素为单位的显示尺寸,您可以使用#0

Display display = getWindowManager().getDefaultDisplay();Point size = new Point();display.getSize(size);int width = size.x;int height = size.y;

如果您不在Activity中,您可以通过WINDOW_SERVICE获得默认的Display

WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display display = wm.getDefaultDisplay();

如果您在一个片段中并且想要完成它,只需使用Active. WindowManager(在Xamarin. Android中)或getActive(). getWindowManager()(在java中)。

在引入getSize之前(在API级别13中),您可以使用现在已弃用的getWidthgetHeight方法:

Display display = getWindowManager().getDefaultDisplay();int width = display.getWidth();  // deprecatedint height = display.getHeight();  // deprecated

但是,对于您正在描述的用例,布局中的边距/填充似乎更合适。

另一种方法是:显示指标

描述有关显示器的一般信息的结构,例如其大小、密度和字体缩放。要访问DisplayMetrics成员,请初始化一个对象,如下所示:

DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);

我们可以使用widthPixels来获取以下信息:

"显示器的绝对宽度(以像素为单位)。"

示例:

Log.d("ApplicationTagName", "Display width in px is " + metrics.widthPixels);

API级别30更新

final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();// Gets all excluding insetsfinal WindowInsets windowInsets = metrics.getWindowInsets();Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()| WindowInsets.Type.displayCutout());
int insetsWidth = insets.right + insets.left;int insetsHeight = insets.top + insets.bottom;
// Legacy size that Display#getSize reportsfinal Rect bounds = metrics.getBounds();final Size legacySize = new Size(bounds.width() - insetsWidth,bounds.height() - insetsHeight);

一种方法是:

Display display = getWindowManager().getDefaultDisplay();int width = display.getWidth();int height = display.getHeight();

它已被弃用,您应该尝试以下代码。前两行代码为您提供了DisplayMetrics对象。此对象包含heightPixelswidthPixels等字段。

DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);      
int height = metrics.heightPixels;int width = metrics.widthPixels;

api级别30更新

final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();// Gets all excluding insetsfinal WindowInsets windowInsets = metrics.getWindowInsets();Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()| WindowInsets.Type.displayCutout());
int insetsWidth = insets.right + insets.left;int insetsHeight = insets.top + insets.bottom;
// Legacy size that Display#getSize reportsfinal Rect bounds = metrics.getBounds();final Size legacySize = new Size(bounds.width() - insetsWidth,bounds.height() - insetsHeight);

它可能无法回答你的问题,但知道(当我遇到这个问题时,我自己也在寻找它)可能会很有用,如果你需要一个View的维度,但是你的代码在其布局尚未布局时执行(例如在onCreate()中),你可以设置一个ViewTreeObserver.OnGlobalLayoutListenerView.getViewTreeObserver().addOnGlobalLayoutListener(),并将需要视图维度的相关代码放在那里。当布局已经布局时,将调用侦听器的回调。

对于使用XML进行动态缩放,有一个名为“android:layout_weight”的属性

下面的示例修改自synic在这个线程上的响应,显示了一个占屏幕75%的按钮(权重=.25)和一个占屏幕剩余25%的文本视图(权重=.75)。

<LinearLayout android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal">
<Button android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight=".25"android:text="somebutton">
<TextView android:layout_width="fill_parent"android:layout_height="Wrap_content"android:layout_weight=".75"></LinearLayout>

我发现这确实起了作用。

Rect dim = new Rect();getWindowVisibleDisplayFrame(dim);

只是增加了弗朗西斯科的答案。如果你想找出窗口中的位置或屏幕中的位置,另一个更合适的观察者是视图树观察者。在预绘制监听器()上

这也可以用于查找视图的其他属性,这些属性在onCreate()时大多是未知的,例如滚动位置、缩放位置。

在活动中使用以下代码。

DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);int height = metrics.heightPixels;int wwidth = metrics.widthPixels;

查找屏幕的宽度和高度:

width = getWindowManager().getDefaultDisplay().getWidth();height = getWindowManager().getDefaultDisplay().getHeight();

使用它,我们可以获得最新和更高版本的SDK 13。

// New width and heightint version = android.os.Build.VERSION.SDK_INT;Log.i("", " name == "+ version);Display display = getWindowManager().getDefaultDisplay();int width;if (version >= 13) {Point size = new Point();display.getSize(size);width = size.x;Log.i("width", "if =>" +width);}else {width = display.getWidth();Log.i("width", "else =>" +width);}
public class AndroidScreenActivity extends Activity {
@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);
DisplayMetrics dm = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);String str_ScreenSize = "The Android Screen is: "+ dm.widthPixels+ " x "+ dm.heightPixels;
TextView mScreenSize = (TextView) findViewById(R.id.strScreenSize);mScreenSize.setText(str_ScreenSize);}}

(2012回答,可能过时了)如果您想支持前蜂巢,您需要在API 13之前添加向后兼容性。类似:

int measuredWidth = 0;int measuredHeight = 0;WindowManager w = getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {Point size = new Point();w.getDefaultDisplay().getSize(size);measuredWidth = size.x;measuredHeight = size.y;} else {Display d = w.getDefaultDisplay();measuredWidth = d.getWidth();measuredHeight = d.getHeight();}

当然,已弃用的方法最终会从最新的SDK中删除,但尽管我们仍然依赖大多数拥有Android 2.1、2.2和2.3的用户,但这就是我们剩下的。

我有两个函数,一个用于发送上下文,另一个用于获取以像素为单位的高度和宽度:

public static int getWidth(Context mContext){int width=0;WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);Display display = wm.getDefaultDisplay();if(Build.VERSION.SDK_INT>12){Point size = new Point();display.getSize(size);width = size.x;}else{width = display.getWidth();  // Deprecated}return width;}

public static int getHeight(Context mContext){int height=0;WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);Display display = wm.getDefaultDisplay();if(Build.VERSION.SDK_INT>12){Point size = new Point();display.getSize(size);height = size.y;}else{height = display.getHeight();  // Deprecated}return height;}

首先加载XML文件,然后编写以下代码:

setContentView(R.layout.main);Display display = getWindowManager().getDefaultDisplay();final int width = (display.getWidth());final int height = (display.getHeight());

根据您的屏幕分辨率显示宽度和高度。

使用DisplayMetrics(API 1)有一种不建议使用的方法来做到这一点,它避免了try/cat混乱:

 // initialize the DisplayMetrics objectDisplayMetrics deviceDisplayMetrics = new DisplayMetrics();
// populate the DisplayMetrics object with the display characteristicsgetWindowManager().getDefaultDisplay().getMetrics(deviceDisplayMetrics);
// get the width and heightscreenWidth = deviceDisplayMetrics.widthPixels;screenHeight = deviceDisplayMetrics.heightPixels;

这是我用于任务的代码:

// `activity` is an instance of Activity class.Display display = activity.getWindowManager().getDefaultDisplay();Point screen = new Point();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {display.getSize(screen);} else {screen.x = display.getWidth();screen.y = display.getHeight();}

似乎足够干净,然而,照顾弃用。

需要说的是,如果您不在Activity中,而是在View中(或者您的作用域中有View类型的变量),则不需要使用WINDOW_SERVICE。那么您至少可以使用两种方法。

第一:

DisplayMetrics dm = yourView.getContext().getResources().getDisplayMetrics();

第二:

DisplayMetrics dm = new DisplayMetrics();yourView.getDisplay().getMetrics(dm);

我们在这里调用的所有方法都不建议使用。

我尝试了所有可能的“解决方案”都没有成功,我注意到Elliott Hughes的“Dalvik Explorer”应用程序在任何Android设备/操作系统版本上都总是显示正确的维度。我最后看了他的开源项目,可以在这里找到:https://code.google.com/p/enh/

以下是所有相关代码:

WindowManager w = activity.getWindowManager();Display d = w.getDefaultDisplay();DisplayMetrics metrics = new DisplayMetrics();d.getMetrics(metrics);// since SDK_INT = 1;widthPixels = metrics.widthPixels;heightPixels = metrics.heightPixels;try {// used when 17 > SDK_INT >= 14; includes window decorations (statusbar bar/menu bar)widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d);heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d);} catch (Exception ignored) {}try {// used when SDK_INT >= 17; includes window decorations (statusbar bar/menu bar)Point realSize = new Point();Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);widthPixels = realSize.x;heightPixels = realSize.y;} catch (Exception ignored) {}

编辑:稍微改进的版本(避免在不支持的操作系统版本上触发异常):

WindowManager w = activity.getWindowManager();Display d = w.getDefaultDisplay();DisplayMetrics metrics = new DisplayMetrics();d.getMetrics(metrics);// since SDK_INT = 1;widthPixels = metrics.widthPixels;heightPixels = metrics.heightPixels;// includes window decorations (statusbar bar/menu bar)if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)try {widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d);heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d);} catch (Exception ignored) {}// includes window decorations (statusbar bar/menu bar)if (Build.VERSION.SDK_INT >= 17)try {Point realSize = new Point();Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);widthPixels = realSize.x;heightPixels = realSize.y;} catch (Exception ignored) {}

我将像这样包装getsize代码:

@SuppressLint("NewApi")public static Point getScreenSize(Activity a) {Point size = new Point();Display d = a.getWindowManager().getDefaultDisplay();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {d.getSize(size);} else {size.x = d.getWidth();size.y = d.getHeight();}return size;}

这不是一个更好的解决方案吗?显示指标提供了您需要的一切,并从API 1开始工作。

public void getScreenInfo(){DisplayMetrics metrics = new DisplayMetrics();getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
heightPixels = metrics.heightPixels;widthPixels = metrics.widthPixels;density = metrics.density;densityDpi = metrics.densityDpi;}

您还可以使用getRealMetrics获取实际显示(包括屏幕装饰,例如状态栏或软件导航栏),但这仅适用于17+。

我错过了什么吗?

有时你需要知道布局可用空间的精确尺寸,当在活动的onCreate中时。经过一番思考,我想出了这样做的方式。

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);startActivityForResult(new Intent(this, Measure.class), 1);// Return without setting the layout, that will be done in onActivityResult.}
@Overrideprotected void onActivityResult (int requestCode, int resultCode, Intent data) {// Probably can never happen, but just in case.if (resultCode == RESULT_CANCELED) {finish();return;}int width = data.getIntExtra("Width", -1);// Width is now set to the precise available width, and a layout can now be created.            ...}}
public final class Measure extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);// Create a LinearLayout with a MeasureFrameLayout in it.// Just putting a subclass of LinearLayout in works fine, but to future proof things, I do it this way.LinearLayout linearLayout = new LinearLayout(this);LinearLayout.LayoutParams matchParent = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);MeasureFrameLayout measureFrameLayout = new MeasureFrameLayout(this);measureFrameLayout.setLayoutParams(matchParent);linearLayout.addView(measureFrameLayout);this.addContentView(linearLayout, matchParent);// measureFrameLayout will now request this second activity to finish, sending back the width.}
class MeasureFrameLayout extends FrameLayout {boolean finished = false;public MeasureFrameLayout(Context context) {super(context);}
@SuppressLint("DrawAllocation")@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);if (finished) {return;}finished = true;// Send the width back as the result.Intent data = new Intent().putExtra("Width", MeasureSpec.getSize(widthMeasureSpec));Measure.this.setResult(Activity.RESULT_OK, data);// Tell this activity to finish, so the result is passed back.Measure.this.finish();}}}

如果出于某种原因,您不想将另一个活动添加到Android清单中,您可以这样做:

public class MainActivity extends Activity {static Activity measuringActivity;
@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);Bundle extras = getIntent().getExtras();if (extras == null) {extras = new Bundle();}int width = extras.getInt("Width", -2);if (width == -2) {// First time in, just start another copy of this activity.extras.putInt("Width", -1);startActivityForResult(new Intent(this, MainActivity.class).putExtras(extras), 1);// Return without setting the layout, that will be done in onActivityResult.return;}if (width == -1) {// Second time in, here is where the measurement takes place.// Create a LinearLayout with a MeasureFrameLayout in it.// Just putting a subclass of LinearLayout in works fine, but to future proof things, I do it this way.LinearLayout linearLayout = new LinearLayout(measuringActivity = this);LinearLayout.LayoutParams matchParent = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);MeasureFrameLayout measureFrameLayout = new MeasureFrameLayout(this);measureFrameLayout.setLayoutParams(matchParent);linearLayout.addView(measureFrameLayout);this.addContentView(linearLayout, matchParent);// measureFrameLayout will now request this second activity to finish, sending back the width.}}
@Overrideprotected void onActivityResult (int requestCode, int resultCode, Intent data) {// Probably can never happen, but just in case.if (resultCode == RESULT_CANCELED) {finish();return;}int width = data.getIntExtra("Width", -3);// Width is now set to the precise available width, and a layout can now be created....}
class MeasureFrameLayout extends FrameLayout {boolean finished = false;public MeasureFrameLayout(Context context) {super(context);}
@SuppressLint("DrawAllocation")@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);if (finished) {return;}finished = true;// Send the width back as the result.Intent data = new Intent().putExtra("Width", MeasureSpec.getSize(widthMeasureSpec));MainActivity.measuringActivity.setResult(Activity.RESULT_OK, data);// Tell the (second) activity to finish.MainActivity.measuringActivity.finish();}}

如果您不想要Windows管理器、点或显示的开销,您可以获取XML中最顶层View项的高度和宽度属性,前提是它的高度和宽度设置为match_parent。(只要您的布局占用整个屏幕,就可以这样做。)

例如,如果您的XML以这样的方式开头:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/entireLayout"android:layout_width="match_parent"android:layout_height="match_parent" >

然后findViewById(R.id.entireLayout).getWidth()将返回屏幕的宽度,findViewById(R.id.entireLayout).getHeight()将返回屏幕的高度。

这不是OP的答案,因为他想要以实际像素表示的显示尺寸。我想要“设备独立像素”中的尺寸,并将这里的答案https://stackoverflow.com/a/17880012/253938和这里的答案https://stackoverflow.com/a/6656774/253938放在一起,我想到了这个:

    DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();int dpHeight = (int)(displayMetrics.heightPixels / displayMetrics.density + 0.5);int dpWidth = (int)(displayMetrics.widthPixels / displayMetrics.density + 0.5);

对于访问Android设备状态栏的高度,我们更喜欢程序化的方式来获取它:

示例代码

int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");if (resId > 0) {result = getResources().getDimensionPixelSize(resId);}

变量result给出了像素的高度。

为了快速访问

在此输入图片描述

有关Title barNavigation barContent View高度的更多信息,请查看Android设备屏幕大小

对于谁在搜索没有状态栏动作栏可用屏幕尺寸(也感谢Swapnil的回答):

DisplayMetrics dm = getResources().getDisplayMetrics();float screen_w = dm.widthPixels;float screen_h = dm.heightPixels;
int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");if (resId > 0) {screen_h -= getResources().getDimensionPixelSize(resId);}
TypedValue typedValue = new TypedValue();if(getTheme().resolveAttribute(android.R.attr.actionBarSize, typedValue, true)){screen_h -= getResources().getDimensionPixelSize(typedValue.resourceId);}

我有一个以LinearLayout为根视图的启动屏幕活动,其宽度和高度为match_parent。这是该活动onCreate()方法中的代码。我在应用程序的所有其他活动中使用这些措施。

int displayWidth = getRawDisplayWidthPreHoneycomb();int rawDisplayHeight = getRawDisplayHeightPreHoneycomb();int usableDisplayHeight = rawDisplayHeight - getStatusBarHeight();pf.setScreenParameters(displayWidth, usableDisplayHeight);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {LinearLayout myView = (LinearLayout) findViewById(R.id.splash_view);myView.addOnLayoutChangeListener(new OnLayoutChangeListener() {@Overridepublic void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {if (left == 0 && top == 0 && right == 0 && bottom == 0) {return;}int displayWidth = Math.min(right, bottom);int usableDisplayHeight = Math.max(right, bottom);pf.setScreenParameters(displayWidth, usableDisplayHeight);}});}

以下是上面调用的方法的实现:

private int getRawDisplayWidthPreHoneycomb() {WindowManager windowManager = getWindowManager();Display display = windowManager.getDefaultDisplay();DisplayMetrics displayMetrics = new DisplayMetrics();display.getMetrics(displayMetrics);
int widthPixels = displayMetrics.widthPixels;int heightPixels = displayMetrics.heightPixels;
return Math.min(widthPixels, heightPixels);}
private int getRawDisplayHeightPreHoneycomb() {WindowManager w = getWindowManager();Display d = w.getDefaultDisplay();DisplayMetrics metrics = new DisplayMetrics();d.getMetrics(metrics);
int widthPixels = metrics.widthPixels;int heightPixels = metrics.heightPixels;
return Math.max(widthPixels, heightPixels);}
public int getStatusBarHeight() {int statusBarHeight = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");if (resourceId > 0) {statusBarHeight = getResources().getDimensionPixelSize(resourceId);}
return statusBarHeight;}

对于所有API版本和不同类型的设备(手机和平板电脑),这会导致可用显示器的高度和宽度,不包括任何类型的条(状态栏、导航栏)。

遵循以下方法:

public static int getWidthScreen(Context context) {return getDisplayMetrics(context).widthPixels;}
public static int getHeightScreen(Context context) {return getDisplayMetrics(context).heightPixels;}
private static DisplayMetrics getDisplayMetrics(Context context) {DisplayMetrics displayMetrics = new DisplayMetrics();WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);wm.getDefaultDisplay().getMetrics(displayMetrics);return displayMetrics;}
DisplayMetrics dimension = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dimension);int w = dimension.widthPixels;int h = dimension.heightPixels;

简单的功能也与较低版本兼容。

/*** @return screen size int[width, height]** */public int[] getScreenSize(){Point size = new Point();WindowManager w = getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2){w.getDefaultDisplay().getSize(size);return new int[]{size.x, size.y};}else{Display d = w.getDefaultDisplay();//noinspection deprecationreturn new int[]{d.getWidth(), d.getHeight()};}}

要使用:

int width = getScreenSize()[0];int height = getScreenSize()[1];
DisplayMetrics dm = getResources().getDisplayMetrics();float fwidth = dm.density * dm.widthPixels;float fheight = dm.density * dm.heightPixels;

如果getSize由于minSDKVersion而导致错误,并且您不想使用已弃用的方法(getWidthgetHeight),则getMetrics解决方案最初由Balaji. K于2011年发布…… Nik添加了一条注释,解释getDisplayMetrics也考虑了状态栏大小。

其他一些评论提到乘以比例(密度)以获得尺寸的精确浮点值。在Android v2.2(API 8)和v4.0中测试,效果良好,无错误/警告

最简单的方法:

 int screenHeight = getResources().getDisplayMetrics().heightPixels;int screenWidth = getResources().getDisplayMetrics().widthPixels;

此函数返回以英寸为单位的近似屏幕尺寸。

public double getScreenSize(){DisplayMetrics dm = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);int width=dm.widthPixels;int height=dm.heightPixels;int dens=dm.densityDpi;double wi=(double)width/(double)dens;double hi=(double)height/(double)dens;double x = Math.pow(wi,2);double y = Math.pow(hi,2);double screenInches = Math.sqrt(x+y);return screenInches;}

如果Display类不起作用,上面的答案将不起作用,那么您可以通过下面的方法获得宽度和高度。

private static final int WIDTH_INDEX = 0;private static final int HEIGHT_INDEX = 1;
public static int[] getScreenSize(Context context) {int[] widthHeight = new int[2];widthHeight[WIDTH_INDEX] = 0;widthHeight[HEIGHT_INDEX] = 0;
try {WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display display = windowManager.getDefaultDisplay();
Point size = new Point();display.getSize(size);widthHeight[WIDTH_INDEX] = size.x;widthHeight[HEIGHT_INDEX] = size.y;
if (!isScreenSizeRetrieved(widthHeight)){DisplayMetrics metrics = new DisplayMetrics();display.getMetrics(metrics);widthHeight[0] = metrics.widthPixels;widthHeight[1] = metrics.heightPixels;}
// Last defense. Use deprecated API that was introduced in lower than API 13if (!isScreenSizeRetrieved(widthHeight)) {widthHeight[0] = display.getWidth(); // deprecatedwidthHeight[1] = display.getHeight(); // deprecated}} catch (Exception e) {e.printStackTrace();}
return widthHeight;}
private static boolean isScreenSizeRetrieved(int[] widthHeight) {return widthHeight[WIDTH_INDEX] != 0 && widthHeight[HEIGHT_INDEX] != 0;}

要获取屏幕尺寸,请使用显示度量

DisplayMetrics displayMetrics = new DisplayMetrics();if (context != null)WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display defaultDisplay = windowManager.getDefaultDisplay();defaultDisplay.getRealMetrics(displayMetrics);}

获取以像素为单位的高度和宽度

int width  =displayMetrics.widthPixels;int height =displayMetrics.heightPixels;

您可以使用以下命令获取高度大小:

getResources().getDisplayMetrics().heightPixels;

宽度大小使用

getResources().getDisplayMetrics().widthPixels;

这是静态编程语言实现中对上面一些答案的简单改编。它需要如上所述在清单中的winowsSoftInput="调整大小":

class KeyboardWatcher(private val layoutRooView: View) {
companion object {private const val MIN_KEYBOARD_HEIGHT = 200f}
private val displayMetrics: DisplayMetrics = layoutRooView.resources.displayMetricsprivate var stateVisible = false
var observer: ((Boolean) -> Unit)? = null
init {layoutRooView.viewTreeObserver.addOnGlobalLayoutListener {val heightDiff = layoutRooView.rootView.height - layoutRooView.heightif (!stateVisible && heightDiff > dpToPx(MIN_KEYBOARD_HEIGHT)) {stateVisible = trueobserver?.invoke(stateVisible)} else if(stateVisible) {stateVisible = falseobserver?.invoke(stateVisible)}}}
private fun dpToPx(valueInDp: Float): Float {return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, displayMetrics)}}

并使用:

val activityRootView = findViewById<ViewGroup>(R.id.activityRoot)KeyboardWatcher(activityRootView).observer = { visible ->if (visible) do something here ...}

我使用了上述建议并为我们的问题创建了一个kotlin版本。希望这能为使用kotlin的人提供一些额外的帮助:

private val screenDimensions: Int by lazy {val display = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplayPoint().also { size ->when {Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> display.getRealSize(size)else -> display.getSize(size)}}}
screenDimensions.x // widthscreenDimensions.y // height

静态编程语言

fun getScreenHeight(activity: Activity): Int {val metrics = DisplayMetrics()activity.windowManager.defaultDisplay.getMetrics(metrics)return metrics.heightPixels}
fun getScreenWidth(activity: Activity): Int {val metrics = DisplayMetrics()activity.windowManager.defaultDisplay.getMetrics(metrics)return metrics.widthPixels}

我想这是最简单的

private fun checkDisplayResolution() {val displayMetrics = DisplayMetrics().also {windowManager.defaultDisplay.getMetrics(it)}
Log.i(TAG, "display width: ${displayMetrics.widthPixels}")Log.i(TAG, "display height: ${displayMetrics.heightPixels}")Log.i(TAG, "display width dpi: ${displayMetrics.xdpi}")Log.i(TAG, "display height dpi: ${displayMetrics.ydpi}")Log.i(TAG, "display density: ${displayMetrics.density}")Log.i(TAG, "display scaled density: ${displayMetrics.scaledDensity}")}

创建静态编程语言扩展函数来获取屏幕宽度和高度-

fun Context?.screenWidthInPx(): Int {if (this == null) return 0val dm = DisplayMetrics()val wm = this.getSystemService(Context.WINDOW_SERVICE) as WindowManagerwm.defaultDisplay.getMetrics(dm)return dm.widthPixels}//commentfun Context?.screenHeightInPx(): Int {if (this == null) return 0val dm = DisplayMetrics()val wm = this.getSystemService(Context.WINDOW_SERVICE) as WindowManagerwm.defaultDisplay.getMetrics(dm)return dm.heightPixels}

以上代码已在API级别30中弃用。现在你可以使用以下代码

 val width = windowManager.currentWindowMetrics.bounds.width()val height = windowManager.currentWindowMetrics.bounds.height()

此方法报告包括所有系统栏区域的窗口大小,而Display#getSize(Point)报告不包括导航栏和显示剪切区域的区域。Display#getSize(Point)报告的值可以通过使用以下方法获得:

 val metrics = windowManager.currentWindowMetrics// Gets all excluding insetsval windowInsets = metrics.windowInsetsvar insets: Insets = windowInsets.getInsets(WindowInsets.Type.navigationBars())val cutout = windowInsets.displayCutoutif (cutout != null) {val cutoutSafeInsets = Insets.of(cutout.safeInsetLeft, cutout.safeInsetTop, cutout.safeInsetRight, cutout.safeInsetBottom)insets = Insets.max(insets, cutoutSafeInsets)}
val insetsWidth = insets.right + insets.leftval insetsHeight = insets.top + insets.bottom
// Legacy size that Display#getSize reportsval legacySize =  Size(metrics.bounds.width() - insetsWidth, metrics.bounds.height() - insetsHeight)

来源:窗口管理器#获取当前窗口度量()

现在在api 30水平上,应该这样做

final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();// Gets all excluding insetsfinal WindowInsets windowInsets = metrics.getWindowInsets();Insets insets = windowInsets.getInsetsIgnoreVisibility(WindowInsets.Type.navigationBars()| WindowInsets.Type.displayCutout());
int insetsWidth = insets.right + insets.left;int insetsHeight = insets.top + insets.bottom;
// Legacy size that Display#getSize reportsfinal Rect bounds = metrics.getBounds();final Size legacySize = new Size(bounds.width() - insetsWidth,bounds.height() - insetsHeight);

Kotlin Version通过Extension Property

在android中有多种方法可以实现屏幕尺寸,但我认为最好的解决方案可能独立于Context实例,因此你可以在代码中的任何地方使用它。在这里,我通过kotlin扩展属性提供了一个解决方案,它可以很容易地知道屏幕尺寸(以像素为单位)以及dp


DimensionUtils.kt

import android.content.res.Resourcesimport android.graphics.Rectimport android.graphics.RectFimport android.util.DisplayMetricsimport kotlin.math.roundToInt
/*** @author aminography*/
private val displayMetrics: DisplayMetrics by lazy { Resources.getSystem().displayMetrics }
val screenRectPx: Rectget() = displayMetrics.run { Rect(0, 0, widthPixels, heightPixels) }
val screenRectDp: RectFget() = displayMetrics.run { RectF(0f, 0f, widthPixels.px2dp, heightPixels.px2dp) }
val Number.px2dp: Floatget() = this.toFloat() / displayMetrics.density
val Number.dp2px: Intget() = (this.toFloat() * displayMetrics.density).roundToInt()

用法:

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)
val widthPx = screenRectPx.width()val heightPx = screenRectPx.height()println("[PX] screen width: $widthPx , height: $heightPx")
val widthDp = screenRectDp.width()val heightDp = screenRectDp.height()println("[DP] screen width: $widthDp , height: $heightDp")}}

结果:

当设备处于#0方向时:

[PX] screen width: 1440 , height: 2392[DP] screen width: 360.0 , height: 598.0

当设备处于#0方向时:

[PX] screen width: 2392 , height: 1440[DP] screen width: 598.0 , height: 360.0


如果您不是Kotlin的粉丝,请使用Java版本:

import android.content.res.Resources;import android.graphics.Rect;import android.graphics.RectF;import android.util.DisplayMetrics;
/*** @author aminography*/public class DimensionUtils {
private static DisplayMetrics displayMetrics;
private static DisplayMetrics getDisplayMetrics() {if (displayMetrics == null) {displayMetrics = Resources.getSystem().getDisplayMetrics();}return displayMetrics;}
public static Rect screenRectPx() {return new Rect(0, 0, getDisplayMetrics().widthPixels, getDisplayMetrics().heightPixels);}
public static RectF screenRectDp() {return new RectF(0f, 0f, px2dp(getDisplayMetrics().widthPixels), px2dp(getDisplayMetrics().heightPixels));}
public static float px2dp(int value) {return value / getDisplayMetrics().density;}
public static int dp2px(float value) {return (int) (value * getDisplayMetrics().density);}}

科特林

fun getScreenHeight(activity: Activity): Int {val metrics = DisplayMetrics()activity.windowManager.defaultDisplay.getMetrics(metrics)return metrics.heightPixels}
fun getScreenWidth(activity: Activity): Int {val metrics = DisplayMetrics()activity.windowManager.defaultDisplay.getMetrics(metrics)return metrics.widthPixels}

java

DisplayMetrics dimension = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dimension);int w = dimension.widthPixels;int h = dimension.heightPixels;

以下是API 30以下/以上代码的静态编程语言扩展函数:

fun Activity.getScreenWidth(): Int {return if (Build.VERSION.SDK_INT < 30) {val displayMetrics = DisplayMetrics()windowManager.defaultDisplay.getMetrics(displayMetrics)displayMetrics.widthPixels} else {val metrics = windowManager.currentWindowMetricsval insets = metrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())metrics.bounds.width() - insets.left - insets.right}}
fun Activity.getScreenHeight(): Int {return if (Build.VERSION.SDK_INT < 30) {val displayMetrics = DisplayMetrics()windowManager.defaultDisplay.getMetrics(displayMetrics)displayMetrics.heightPixels} else {val metrics = windowManager.currentWindowMetricsval insets = metrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())metrics.bounds.height() - insets.top - insets.bottom}}

对应的Java辅助方法:

public int getScreenWidth(Activity activity) {if (Build.VERSION.SDK_INT < 30) {DisplayMetrics displayMetrics = new DisplayMetrics();activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);return displayMetrics.widthPixels;} else {WindowMetrics metrics = activity.getWindowManager().getCurrentWindowMetrics();Insets insets = metrics.getWindowInsets().getInsetsIgnoringVisibility(WindowInsets.Type.systemBars());return metrics.getBounds().width() - insets.left - insets.right;}}

public int getScreenHeight(Activity activity) {if (Build.VERSION.SDK_INT < 30) {DisplayMetrics displayMetrics = new DisplayMetrics();activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);return displayMetrics.heightPixels;} else {WindowMetrics metrics = activity.getWindowManager().getCurrentWindowMetrics();Insets insets = metrics.getWindowInsets().getInsetsIgnoringVisibility(WindowInsets.Type.systemBars());return metrics.getBounds().height() - insets.bottom - insets.top;}}

创建一个类和一个方法,如下所示:

public MyPoint getScreenDimensionsAsPixel(Context context){WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display display = windowManager.getDefaultDisplay();
Point point = new Point();display.getSize(point);
return new MyPoint(point.x, point.y);}
public class MyPoint{private int width;private int height;
public MyPoint(int width, int height) {this.width = width;this.height = height;}
public int getWidth() {return width;}
public void setWidth(int width) {this.width = width;}
public int getHeight() {return height;}
public void setHeight(int height) {this.height = height;}}

然后在您的代码中使用它们:

MyPoint myPoint = getScreenDimensionsAsPixel(MainActivity.this);Toast.makeText(MainActivity.this, "width: " + String.valueOf(myPoint.getWidth()) + "|" +"height: " + String.valueOf(myPoint.getHeight()), Toast.LENGTH_LONG).show();

静态编程语言更简单。

val displayMetrics = Resources.getSystem().displayMetricsdisplayMetrics.heightPixelsdisplayMetrics.widthPixels