如何以编程方式以触摸事件和查看测量/布局使用的单位找出我的屏幕尺寸?换句话说,我想要屏幕右下角的坐标,在触摸事件使用的坐标系
getRawX()/getRawY()
中View.getLocationOnScreen()
。
我不愿将所需的事件/视图单位称为“像素”,因为在我的手机上显然有多种不同模式下的“像素”概念,它们并没有形成一个一致的故事。
我看到这个问题在stackoverflow和其他地方被问了很多,但是没有一个答案在我的手机(droid 4,android 4.1.2)上在所有模式下都有效:
- 我可以在android应用程序中以编程方式找出屏幕宽度吗?
- 如何在 android 中以编程方式获取 ScreenSize
- Android根据屏幕大小以编程方式设置视图可见性
- 如何在Android中获取屏幕高度?
- 获取Android中的屏幕高度
- https://groups.google.com/forum/#!topic/android-developers/IpxnfvDFrpc
- http://shuklaxyz.blogspot.com/2012/02/how-to-programmatically-figure-out.html
- http://coderock.net/how-to-determine-screen-resolution-programmatically/
- http://www.codeproject.com/Tips/313848/Get-actual-screen-size-for-the-application-layout
- Android 并以 dp 单位编程设置宽度和高度
- http://www.simplecodestuffs.com/how-to-get-screen-dimensions-programmatically-in-android/
- http://www.androidsnippets.com/get-size-and-orientation-of-the-screen
- http://grokbase.com/t/gg/android-developers/127aatfqb6/how-to-determine-screen-resolution-programmatically
(哇!)
这适用于无论应用程序是否处于“屏幕兼容模式”(即清单中的 targetSdkVersion<=10)都需要工作的库代码,而且我也不想对位置、大小做出任何假设,或存在状态栏或任何其他类似的屏幕装饰。
以下是事实:
我的手机(运行 android 4.1.2 的 droid 4)有 540x960 物理像素,即小彩色发光点。
当应用程序处于屏幕兼容模式时,以所需单位显示的屏幕尺寸为 360x640,当应用程序未处于屏幕兼容模式时为 540x960。这些是我需要以编程方式查找的数字,无需使用触摸事件或视图来查找它们,但我很难找到任何返回这些数字的 API。
以各种方式获得的 Display 和 DisplayMetrics 对象都声称屏幕尺寸为 540x960“像素”(无论是否在屏幕兼容模式下)。具体来说,以下都是 540x960:DisplayMetrics.{width,height}Pixels, Display.getSize(), Display.getRealSize(), Display.get{Width,Height}(),
各种方式获得的配置对象都说screen{Width,Height}Dp = 360x614(无论是否在屏幕兼容模式下)。我不相信它代表整个屏幕,因为纵横比是错误的。(我认为是整个屏幕减去状态栏;我需要整个屏幕。)我认为可以肯定地说整个屏幕是 360x640 dp,尽管我不知道任何返回 640 的 API。
DisplayMetrics 以各种方式获得的“密度”在屏幕兼容模式下为 1.0f,在非屏幕兼容模式下为 1.5f。
该活动
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);
}
有没有更好/更清洁的方法来查找屏幕的大小?