134

如何以编程方式以触摸事件和查看测量/布局使用的单位找出我的屏幕尺寸?换句话说,我想要屏幕右下角的坐标,在触摸事件使用的坐标系 getRawX()/getRawY()View.getLocationOnScreen()

我不愿将所需的事件/视图单位称为“像素”,因为在我的手机上显然有多种不同模式下的“像素”概念,它们并没有形成一个一致的故事。

我看到这个问题在stackoverflow和其他地方被问了很多,但是没有一个答案在我的手机(droid 4,android 4.1.2)上在所有模式下都有效:

(哇!)

这适用于无论应用程序是否处于“屏幕兼容模式”(即清单中的 targetSdkVersion<=10)都需要工作的库代码,而且我也不想对位置、大小做出任何假设,或存在状态栏或任何其他类似的屏幕装饰。


以下是事实:

  1. 我的手机(运行 android 4.1.2 的 droid 4)有 540x960 物理像素,即小彩色发光点。

  2. 当应用程序处于屏幕兼容模式时,以所需单位显示的屏幕尺寸为 360x640,当应用程序未处于屏幕兼容模式时为 540x960。这些是我需要以编程方式查找的数字,无需使用触摸事件或视图来查找它们,但我很难找到任何返回这些数字的 API。

  3. 以各种方式获得的 Display 和 DisplayMetrics 对象都声称屏幕尺寸为 540x960“像素”(无论是否在屏幕兼容模式下)。具体来说,以下都是 540x960:DisplayMetrics.{width,height}Pixels, Display.getSize(), Display.getRealSize(), Display.get{Width,Height}(),

  4. 各种方式获得的配置对象都说screen{Width,Height}Dp = 360x614(无论是否在屏幕兼容模式下)。我不相信它代表整个屏幕,因为纵横比是错误的。(我认为是整个屏幕减去状态栏;我需要整个屏幕。)我认为可以肯定地说整个屏幕是 360x640 dp,尽管我不知道任何返回 640 的 API。

  5. DisplayMetrics 以各种方式获得的“密度”在屏幕兼容模式下为 1.0f,在非屏幕兼容模式下为 1.5f。

  6. 该活动 getWindow().getAttributes().{width,height} 没有帮助,因为它通常包含MATCH_PARENT 而不是实际大小。但我显然可以从活动中得到想要的答案 getWindow().getDecorView().getMeasured{Width,Height}() (这实际上令人惊讶,因为活动的窗口的 decorView看起来不像占据整个屏幕;它看起来像是占据了屏幕减去状态栏)。但我不想依赖这个,因为如果窗口被调整大小(出现软键盘?有人调用 window.setAttributes()?或者我根本不在活动中),这显然就是全部错误的。

我理解以下公式应该成立:像素 = dp * 密度这似乎与所有报告的数字(上面的(3),(4),(5))一致,而不是在屏幕兼容模式下:540x960 = 360x640 * 1.5但在屏幕兼容模式下,它不会相加: 540x960 != 360x640 * 1 所以,有些不对劲。

我认为最简单的解释是,上面(3)中列出的方法只是在屏幕兼容模式下对“像素”给出了错误的答案——也就是说,它们旨在返回 360x640 的“像素”,但它们是错误的而是返回 540x960。但可能还有其他看待它的方式。

在任何情况下,无论模式如何,从上述拼图中获得所需的数字肯定是一个棘手的难题。我找到了一种似乎在两种模式下都可以在我的手机上工作的方法,但它非常迂回,并且它依赖于两个看起来仍然相当不稳定的假设(如下面的代码注释中所述)。

这是我的食谱:

/** get screen size in "pixels", i.e. touchevent/view units.
* on my droid 4, this is 360x640 or 540x960
* depending on whether the app is in screen compatibility mode
* (i.e. targetSdkVersion<=10 in the manifest) or not. */
public void getScreenSizePixels(int widthHeightInPixels[/*2*/])
{
    Resources resources = getResources();
    Configuration config = resources.getConfiguration();
    DisplayMetrics dm = resources.getDisplayMetrics();
    // Note, screenHeightDp isn't reliable
    // (it seems to be too small by the height of the status bar),
    // but we assume screenWidthDp is reliable.
    // Note also, dm.widthPixels,dm.heightPixels aren't reliably pixels
    // (they get confused when in screen compatibility mode, it seems),
    // but we assume their ratio is correct.
    double screenWidthInPixels = (double)config.screenWidthDp * dm.density;
    double screenHeightInPixels = screenWidthInPixels * dm.heightPixels / dm.widthPixels;
    widthHeightInPixels[0] = (int)(screenWidthInPixels + .5);
    widthHeightInPixels[1] = (int)(screenHeightInPixels + .5);
}

有没有更好/更清洁的方法来查找屏幕的大小?

4

10 回答 10

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

现在您可以以像素为单位测量屏幕尺寸,这是比厘米更好的测量单位,因为所有按钮、文本视图等都是以该单位测量的。我正常使用的那个

于 2013-09-10T06:52:33.523 回答
9

通过使用 DisplayMetrics,您可以获得任何设备屏幕的高度和宽度。请注意,宽度和高度对旋转很敏感。这是代码。

DisplayMetrics metrics; 
int width = 0, height = 0;

在你的 onCreate 方法中

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

 height = Math.min(metrics.widthPixels, metrics.heightPixels); //height
 width = Math.max(metrics.widthPixels, metrics.heightPixels); //width

尝试这个。

于 2013-07-05T05:11:17.130 回答
8

在您的 #6 中,您注意到 DecorView 似乎提供了您想要的东西,但您认为它不可靠。我相信这是尽可能接近的。根据以下文档Window.getDecorView

检索顶层窗口装饰视图(包含标准窗口框架/装饰和其中的客户端内容),它可以作为窗口添加到窗口管理器。

状态栏是那里提到的窗口装饰的一部分。软件键盘和其他覆盖将接收自己的窗口,因此它们不应干扰相关值。正确的不是精确的显示指标,但如果您的应用程序是全屏的,它应该始终是通过兼容性转换器过滤的全屏尺寸。其他应用程序将无法访问您的应用程序Window,因此无需担心其他应用程序会在您不查看时更改属性。

希望有帮助。

于 2013-09-08T03:56:25.337 回答
5

我应该将此作为评论,但我没有代表。
这可能不是一个完全正确的答案,但是当我在 DisplayMetrics 方法中切换高度和宽度时,我得到了我的尺寸。

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

正如我所说,这可能不正确,但我不知道为什么,但它对我有用。

于 2014-03-27T17:01:11.923 回答
3

如果您使用 api 级别 17 或更高,请查看显示中的 getRealMetrics 和getRealSize

对于 api 级别 14,15 和 16 看这里

于 2013-09-07T23:02:54.600 回答
3

我已经使用毕达哥拉斯定理找到了 Android 手机/平板电脑屏幕的对角线尺寸,同样的原理可以应用于 iPhone 或黑莓屏幕。

DisplayMetrics met = new DisplayMetrics();                
this.getWindowManager().getDefaultDisplay().getMetrics(met);// get display metrics object
String strSize = 
new DecimalFormat("##.##").format(Math.sqrt(((met.widthPixels / met.xdpi) *
(met.widthPixels / met.xdpi)) +
((met.heightPixels / met.ydpi) * (met.heightPixels / met.ydpi))));
// using Dots per inches with width and height

毕达哥拉斯一定是个天才,他多年前就知道智能手机编程:p

于 2013-09-23T19:30:17.830 回答
1

我使用下面的方法来获取设备的宽度:

public static int getDeviceWidth(Context context){
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    int width=display.getWidth();
    return width;
}
于 2016-03-17T07:30:08.407 回答
0

我认为此功能将帮助您简单地获取 android 屏幕尺寸的宽度和高度。该函数将宽度和高度作为整数数组返回,如下所示

private int[] getScreenSIze(){
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int h = displaymetrics.heightPixels;
        int w = displaymetrics.widthPixels;

        int[] size={w,h};
        return size;

    }

并在您的创建方法上输出您的宽度和高度,如下所示

 int[] screenSize= getScreenSIze();
        int width=screenSize[0];
        int height=screenSize[1];
        screenSizes.setText("Phone Screen sizes \n\n  width = "+width+" \n Height = "+height);

下载源代码并在您的 android studio 上进行测试

于 2017-01-20T07:33:57.877 回答
0

这对我有用:

int width = Resources.getSystem().getDisplayMetrics().widthPixels;

int height = Resources.getSystem().getDisplayMetrics().heightPixels;

我用它在水平回收器视图中更新我的项目的宽度。(根据我的要求)希望它对某人有所帮助!

于 2019-10-07T04:53:37.990 回答
-1

对于Kotlin中的这个解决方案,试试这个:

private fun yourFunction(){
   val metrics = DisplayMetrics()
   windowManager.defaultDisplay.getMetrics(metrics)
   val width = metrics.widthPixels
   val height = metrics.heightPixels
}
于 2018-07-27T08:55:48.607 回答