ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

如何在主 Activity 中获取 screenWidthscreenHeight

使用 dp 而不是 px。因为它会用其他设备扭曲您的布局..
不要忘记乘以 getResources().getDisplayMetrics().density 来说明显示缩放
这证明了投票最多的答案并不总是最好的(并且很多人重复回答代表)。尝试使用 Balaji.K 的 getMetrics,而不是 getSize 和已弃用的 getWidth/getHeight 组合(忽略错误)。 Nik 在他的回答中的评论甚至解释了 getDisplayMetrics 以考虑系统/状态栏的大小。您也可以使用 density 作为 jmaculate 和 LoungeKatt 解释为具有 EXACT 值:DisplayMetrics dm = getResources().getDisplayMetrics(); float fwidth = dm.density * dm.widthPixels; 在 Android v2.2 (API 8) 和 v4.0 中测试,结果良好并且没有错误/警告
DisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); int height = displaymetrics.heightPixels; int 宽度 = displaymetrics.widthPixels;
另一种获取 DisplayMetrics 的方法:Resources.getSystem().getDisplayMetrics()。您不需要 Context 即可获得它们。

t
t0m

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

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();

如果您在片段中并且想要完成此操作,只需使用 Activity.WindowManager(在 Xamarin.Android 中)或 getActivity().getWindowManager()(在 java 中)。

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

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

API 级别 30 更新

final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
 // Gets all excluding insets
 final 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 reports
 final Rect bounds = metrics.getBounds();
 final Size legacySize = new Size(bounds.width() - insetsWidth,
         bounds.height() - insetsHeight);

getWidth() 还是 getSize()?如果我需要我的应用程序在 API <13 和 API >13 上运行,我会使用什么?
尝试 { display.getSize(size);宽度 = 大小.x;高度 = 大小.y; } catch (NoSuchMethodError e) { width = display.getWidth();高度 = display.getHeight(); }
我不明白您为什么要使用 try/catch 进行此类检查?为什么不简单地使用 if (android.os.Build.VERSION.SDK_INT >= 13) 而不抛出任何异常?我认为正常应用流程中的 try/catch 是不好的做法。
@A-Live 那么应用程序也会崩溃(但不会崩溃)。尽管如此,我们开发人员必须预先检查一个新的操作系统版本,这可能只是隐藏了一个问题。同样对于这个论点,人们可以/应该用 try/catch 包围每几行代码,在我看来,正如已经提到的那样,这是不好的做法。
如果您想获得不包括导航栏和/或通知栏的屏幕尺寸怎么办
t
t0m

一种方法是:

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 insets
 final 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 reports
 final Rect bounds = metrics.getBounds();
 final Size legacySize = new Size(bounds.width() - insetsWidth,
         bounds.height() - insetsHeight);

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

它可能无法回答您的问题,但如果您需要 View 的尺寸但您的代码在其布局尚未布局时正在执行,那么了解(当我遇到这个问题时我自己正在寻找它)可能会很有用(例如在 onCreate() 中)您可以使用 View.getViewTreeObserver().addOnGlobalLayoutListener() 设置 ViewTreeObserver.OnGlobalLayoutListener 并将需要视图尺寸的相关代码放在那里。布局布局后,将调用侦听器的回调。


或者只写 view.post
view.post 不能保证工作。这只是一种解决方法。
@marsbear 它在哪里说 View.post() 不能保证工作?我很好奇,因为我也依靠这种方法在布局后获取视图的大小并且不知道它不可靠。
@Turbo我说:p我们之前使用过这种解决方法,但结果证明它不可靠。该解决方法基于这样的假设,即初始布局是在与初始化相同的 UIThread 轮次内完成的。因此,您可以通过 post() 安排您的代码在下一个 UI 转之前运行,并且没问题。事实证明,在某些情况下布局可能需要更长的时间,并且在发布的代码运行时视图仍然没有布局。我现在要做的是在 onCreate 中添加 ViewTreeObserver 并在第一个 onLayout 之后将其删除。在第一个 onLayout 期间初始化你的东西。
@marsbear 您从哪个 View 获得 ViewTreeObserver 重要吗?还是他们都共享同一个?
d
digiphd

(2012 回答,可能已过时)如果您想支持 pre Honeycomb,则需要在 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,但这就是我们剩下的。


是的,这是2012年的事了。
抱歉,请允许我澄清一下我的意思。截至 2015 年 6 月 22 日,任何人都不太可能支持 API <14
d
dakshbhatt21

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

这是此处唯一考虑到窗口装饰(状态栏/菜单栏)的帖子。对我来说很好。
太棒了,但是您永远不应该期望业务逻辑会触发异常。异常触发(即使被捕获)对性能来说是可怕的。另外,如果 SDK_INT > 13,您所做的工作将超出所需。相反,您应该在 Build.VERSION.SDK_INT 上添加一些 if。
@Erik B,我同意。我添加了改进版本。我仍然留下了“自 SDK 1 以来”的部分,以防在 try/catch 中出现问题(我在 Android 中看到了很多不好的事情,尤其是当你认为不可能出现问题时,所以我喜欢保证它的安全 :)) .无论如何,不应该有太多的开销,因为这个计算应该只进行一次(例如,值可以保存在一些静态属性中)。
请注意,此代码在 GPL v3 下获得许可,这对在生产应用程序中使用有影响。
GPL 并依赖于反射来调用未来 Android 版本中可能不存在的方法。嗯嗯
Z
Zelleriation

最简单的方法:

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

C
Community

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

示例代码

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

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

为了快速访问

https://i.stack.imgur.com/1HxlM.png

有关 Title barNavigation barContent View 高度的更多信息,请查看 Android Device Screen Sizes


正是我需要的! getResources().getDisplayMetrics().heightPixels + result 给出实际的全屏高度。 Dragan Marjanović 的回答也有效,但我更喜欢这个更短更简单的解决方案。
从 Android Marshmallow 开始,这种方法已经过时。状态栏高度可以根据设备或 Android 版本而变化。更好地使用 OnApplyWindowInsetsListener
A
Anik Islam Abhi

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


这实际上是文档告诉您执行此操作的方式……但是如果您不使用视图,那将毫无意义。您可能正在使用其他东西,例如 mglsurfaceview。
这更好,因为父视图可能不是显示器的大小。但是请确保这是在您查询大小的视图已经布置好的地方完成的,这通常不会在 onCreate() 中。您可以使用来自 onWindowFocusChanged(boolean hasFocus) 的自定义回调,该回调将在测量完所有视图等之后调用,以确保您不会收到您感兴趣的视图的错误尺寸...
P
Peter Mortensen

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

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

您需要在函数签名上方添加 @SuppressLint("NewApi") 才能编译。
我认为最好一次性获得高度和宽度,而不是单独调用 API,否则它们可能会不同步。如果在您的代码运行时屏幕方向发生变化,则可能会发生这种情况。
C
Community

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

下面的示例根据 synic 对 this thread 的响应进行了修改,显示了一个占据 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>

P
Pijusn

这是我用于该任务的代码:

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

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


D
David Corsalini

这不是更好的解决方案吗? DisplayMetrics 包含您需要的一切,并且可以通过 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+。

我错过了什么吗?


它不会为屏幕控件(例如平板电脑或 Nexus 设备)减少空间。此外,我在 10 英寸平板电脑上得到不同的值(750 与 800),具体取决于计算完成时 Activity 是否处于活动状态。但就我的目的而言,这已经很好了。谢谢!
p
pellucide

只是添加到弗朗切斯科的答案。如果您想找出窗口中的位置或屏幕中的位置,另一个更合适的观察者是 ViewTreeObserver.OnPreDrawListener()

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


V
Vinothkumar Arputharaj

在活动中使用以下代码。

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

P
Peter Mortensen

查找屏幕的宽度和高度:

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

使用它,我们可以获得最新及以上的 SDK 13。

// New width and height
int 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);
}

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

J
Justin

我发现这可以解决问题。

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

很酷,但是在源代码中这个方法有一个可怕的地方:this comment
S
Sergei Pikalev

需要说明的是,如果您不在 Activity 中,而是在 View 中(或在您的范围内有 View 类型的变量),则不需要使用 WINDOW_SERVICE。那么你至少可以使用两种方式。

第一的:

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

第二:

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

我们在这里调用的所有这些方法都没有被弃用。


P
Peter Mortensen
public class AndroidScreenActivity extends Activity {

    @Override
    public 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);
    }
}

M
Mohamed Nageh

要获取屏幕尺寸,请使用显示指标

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;

C
Community

这不是 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);

J
Jéwôm'

您可以使用以下方法获取高度大小:

getResources().getDisplayMetrics().heightPixels;

和宽度大小使用

getResources().getDisplayMetrics().widthPixels; 

p
paulrehkugler

使用 DisplayMetrics (API 1) 有一种不被弃用的方法,可以避免 try/catch 混乱:

 // initialize the DisplayMetrics object
 DisplayMetrics deviceDisplayMetrics = new DisplayMetrics();

 // populate the DisplayMetrics object with the display characteristics
 getWindowManager().getDefaultDisplay().getMetrics(deviceDisplayMetrics);

 // get the width and height
 screenWidth = deviceDisplayMetrics.widthPixels;
 screenHeight = deviceDisplayMetrics.heightPixels;

S
Simon

我会像这样包装 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;
}

这会在运行 Android 4.0 (API 14) 的模拟器上崩溃。
F
Francesco Vadicamo

对于谁正在搜索没有状态栏和操作栏的可用屏幕尺寸(也感谢 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);
}

C
Community

科特林

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
}

P
Peter Mortensen

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

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

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


P
Peter Mortensen

请遵循以下方法:

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

S
Steve Waring

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

public class MainActivity extends Activity {
    @Override
    protected 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.
    }

    @Override
    protected 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 {
    @Override
    protected 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")
        @Override
        protected 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;

    @Override
    protected 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.
        }
    }

    @Override
    protected 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")
    @Override
    protected 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();
    }
}    

显然,您也可以传回捆绑包中的高度。
c
christinac

如果您不想要 WindowManagers、Points 或 Displays 的开销,您可以获取 XML 中最顶层 View 项的 height 和 width 属性,前提是它的 height 和 width 设置为 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() 将返回屏幕的高度。