首页 文章

如何以编程方式获得Android屏幕大小,一劳永逸?

提问于
浏览
128

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

我不愿意将所需的事件/视图单元称为“像素”,因为在我的手机上有各种模式的“像素”概念,并且它们并没有达到一致的故事 .

我看到在stackoverflow和其他地方已经被问到并回答了很多,但在所有模式下,我的手机(droid 4,android 4.1.2)上没有任何答案实际可行:

(哇!)

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


以下是事实:

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

  • 所需单位的屏幕大小,从查看触摸事件和查看测量值,当应用程序处于屏幕比较模式时为360x640,当应用程序未处于屏幕比较模式时为540x960 . 这些是我需要以编程方式找到的数字,而不是用触摸事件或视图来查找它们,但是我很难找到任何会返回这些数字的API .

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

  • 以各种方式获得的配置对象都表示屏幕{宽度,高度} Dp = 360x614(无论是否在屏幕比较模式下) . 我不相信这代表整个屏幕,因为宽高比是错误的 . (我认为这是整个屏幕减去状态栏;我需要整个屏幕 . )我认为可以说整个屏幕是360x640 dp,但我不知道任何返回640的API .

  • 以各种方式获得的DisplayMetrics表示在屏幕比较模式下“密度”为1.0f,在屏幕比较模式下为1.5f .

  • 活动的 getWindow().getAttributes().{width,height} 没有帮助,因为它通常包含 MATCH_PARENT 而不是实际尺寸 . 但我显然可以从一个活动的 getWindow().getDecorView().getMeasured{Width,Height}() 得到所需的答案(这实际上是令人惊讶的,因为活动's window'的decorView看起来不像它占据了屏幕减去状态栏) . 但我根本不参加活动,这显然是错的 .

我理解以下公式应该保持:pixels = dp * density当不在屏幕兼容模式时,这似乎与所有报告的数字((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);
}

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

9 回答

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

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

  • 4

    通过使用DisplayMetrics,您可以获得任何设备屏幕的高度和宽度 . 这是代码 .

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

    在你的onCreate方法中

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

    试试这个 .

  • 1

    在你的#6中,你注意到DecorView似乎提供了你想要的东西,但是你认为它不可行 . 我相信这就像你能来的那样近 . 根据 Window.getDecorView 的文档:

    检索顶级窗口装饰视图(包含标准窗口框架/装饰及其内部的客户端内容),可将其作为窗口添加到窗口管理器 .

    状态栏是那里提到的窗户装饰的一部分 . 软件键盘等叠加层将收到自己的窗口,因此它们不应该精确显示指标,但如果您的应用程序是全屏,则它应该始终是通过兼容性转换器过滤的全屏大小 . 其他应用程序赢得了't have access to your application' s Window ,因此无需担心其他应用程序在您不查看时更改属性 .

    希望有所帮助 .

  • 3

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

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

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

  • 8

    如果您使用的是api level 17或更高版本,请查看Display中的getRealMetrics和getRealSize

    对于api级14,15和16看here

  • 0

    我用毕达哥拉斯定理来找到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

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

    我认为这个功能可以帮助您简单地获得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;
    
        }
    

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

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

    Download source code 并在你的android工作室测试它

  • 40

    对于 Kotlin 中的此解决方案,请尝试以下操作:

    private fun yourFunction(){
       val metrics = DisplayMetrics()
       windowManager.defaultDisplay.getMetrics(metrics)
       val width = metrics.widthPixels
       val height = metrics.heightPixels
    }
    

相关问题