题 以像素为单位获取屏幕尺寸


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

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

如何得到 screenWidth 和 screenHeight 在主要活动?


1672
2018-06-19 08:25


起源


使用dp而不是px。因为它会扭曲你的布局与其他设备.. - Nepster
不要忘记乘以getResources()。getDisplayMetrics()。density以考虑显示缩放 - jmaculate
这证明了最高投票的答案并不总是最好的(许多人重复代表的答案)。尝试使用Balaji.K代替getSize并弃用getWidth / getHeight组合(忽略错误) getMetrics。 Nik在他的回答中的评论甚至解释道 getDisplayMetrics 考虑系统/状态栏的大小。你也可以使用 密度 正如jmaculate和LoungeKatt所解释的那样 精确 值:DisplayMetrics dm = getResources().getDisplayMetrics(); float fwidth = dm.density * dm.widthPixels; 在Android v2.2(API 8)和v4.0中测试,效果很好 没有错误/警告。 - Armfoot
DisplayMetrics displaymetrics = new DisplayMetrics(); 。getWindowManager()getDefaultDisplay()getMetrics(displaymetrics)。 int height = displaymetrics.heightPixels; int width = displaymetrics.widthPixels; - Azahar


答案:


如果您想要显示尺寸(以像素为单位),您可以使用 getSize

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

如果你不在 Activity 你可以得到默认值 Display 通过 WINDOW_SERVICE

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

之前 getSize 介绍(在API级别13),您可以使用 getWidth 和 getHeight 现已弃用的方法:

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

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

另一种方式是: DisplayMetrics

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

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

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

“显示器的绝对宽度,以像素为单位。”

例:

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

3328
2018-06-19 08:41



developer.android.com/reference/android/view/Display.html - gcb
getWidth()或getSize()?如果我需要我的应用程序在API <13以及API> 13上运行,我会使用什么? - Carol
试试{display.getSize(size); width = size.x; height = size.y; } catch(NoSuchMethodError e){width = display.getWidth(); height = display.getHeight(); } - Arnaud
我不明白你为什么要用 try/catch 这样的支票?为什么不简单地使用 if (android.os.Build.VERSION.SDK_INT >= 13) 没有任何抛出的异常?我想 try/catch 在正常的app-flow中作为不好的做法。 - CipherCom
如果您想获得除导航栏和/或通知栏之外的屏幕尺寸,该怎么办? - android developer


一种方法是:

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

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

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

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

350
2018-01-31 02:01



请注意,度量(宽度,高度)会根据设备的旋转而变化。 - Tony Chan
度量标准将返回显示的大小,但HoneyComb及以上,您的活动将比系统栏返回的空间少。 - Guy
@Guy取决于你的实施。您可以隐藏状态栏:requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow()。setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); - Hagai L
也存在这种方式:getContext()。getResources()。getDisplayMetrics()。widthPixels - Nik
final float scale = getResources()。getDisplayMetrics()。density; int width =(int)(metrics.widthPixels * scale + 0.5f); - 这样做时必须考虑设备密度。 - Abandoned Cart


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


111
2018-04-06 21:23



或者只是写view.post - Lukas Hanacek
快速实施的要点:) gist.github.com/doridori/9208247 - Dori
view.post不保证可以工作。这只是一种解决方法。 - marsbear
@marsbear在哪里说 View.post() 不能保证工作?我很好奇,因为我也依赖这种方法在布局后获得View的大小并且不知道它不可靠。 - Tony Chan
@Turbo我说:p我们之前使用过这种解决方法,结果证明它不可靠。该解决方法基于以下假设:初始布局在与初始化相同的UIThread转弯内完成。因此,您可以通过post()安排您的代码在下一个UI转向之前运行并且没问题。事实证明,在某些情况下布局可能需要更长时间,并且当发布的代码运行时,视图仍然没有布局。我现在做的是在onCreate中添加ViewTreeObserver并在第一个onLayout之后删除它。在第一次onLayout期间启动你的东西。 - marsbear


(2012年回答,可能已过期)如果你想支持precomb,你需要在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的用户,这就是我们留下的。


103
2017-07-24 03:14



是的,这是在2012年。 - digiphd
对不起,请允许我澄清一下我的意思。 2015年6月22日,任何人都不太可能支持API <14 - sudocoder


我尝试了所有可能的“解决方案”并没有成功,我注意到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) {
}

62
2018-03-29 08:15



这是此处唯一考虑窗口装饰(状态栏/菜单栏)的帖子。对我来说很棒。 - Andy Cochrane
太棒了,但是你应该永远不会有预期的业务逻辑火灾异常。射击异常(即使被抓住)对于表现也是可怕的。另外,如果SDK_INT> 13,那么你所做的工作量超过了需要。相反,你应该在Build.VERSION.SDK_INT上添加一些ifs。 - Erik B
@Erik B,我同意。我添加了改进版本。我仍然离开了部分“自SDK 1”以防万一在try / catch中出现问题(我在Android中看到很多不好的东西,特别是当你认为不可能出错时所以我想保证它安全:)) 。无论如何,不​​应该有太多的开销,因为这个计算应该只进行一次(例如,值可以保留在一些静态属性中)。 - Dragan Marjanović
请注意,此代码是根据GPL v3许可的,这对在生产应用程序中使用有影响。 - TalkLittle
GPL并依赖于反映来调用未来Android版本中可能不存在的方法。 Mhhh - Michel


要访问Android设备状态栏的高度,我们更喜欢以编程方式获取它:

示例代码

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

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

快速访问

Enter image description here

有关高度的更多信息 Title barNavigation bar 和 Content View,请好好看看 Android设备屏幕大小


43
2017-08-27 13:12



正是我需要的! getResources().getDisplayMetrics().heightPixels + result 给出实际的全屏高度。 DraganMarjanović的答案也有效,但我更喜欢这个更短更简单的解决方案。 - Michel
从Android Marshmallow开始,这种方法已经过时了。状态栏高度可以从设备或Android版本更改。更好用 OnApplyWindowInsetsListener。 - Heinrich


最简单的方法:

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

42
2017-11-26 10:47



此外,所有这些解决方案中唯一一个对我有用 - ShadowGod
这就是方法。 (Y) - Ahsan Sher
做同样的简单功能..看这篇文章 whats-online.info/science-and-tutorials/121/... - Daniel Nyamasyo


首先得到观点(例如,通过 findViewById())然后你可以使用 的getWidth() 在视图本身。


28
2018-06-19 08:38



这实际上就是文档告诉你这样做的方法......但如果你不使用视图,那就没有多大意义了。你可能正在使用其他东西,例如mglsurfaceview。 - gcb
这是更好的,因为父视图可能不是显示的大小。但请确保在您查询大小的视图已经布局的位置完成此操作,这通常不在onCreate()中。您可以使用onWindowFocusChanged(boolean hasFocus)中的自定义回调函数,该函数将在测量完所有视图后调用,等等,确保您不会收到您感兴趣的视图的错误尺寸... - Dori


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

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

24
2017-10-17 14:44



你需要添加 @SuppressLint("NewApi") 就在函数签名之上,以便能够编译。 - Adil Malik
我认为最好一次性获取高度和宽度,而不是单独调用API,因为否则它们可能会不同步。如果在代码运行时屏幕方向发生变化,则可能会发生这种情况。 - Sam


对于使用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>

17
2017-12-22 06:11





这是我用于任务的代码:

// `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();
}

看起来足够干净但是,请注意弃用。


17
2017-12-27 14:31