在Android中获取屏幕宽度和高度

634

我该如何获取屏幕宽度和高度,并在代码中使用这个值:

@Override protected void onMeasure(int widthSpecId, int heightSpecId) {
    Log.e(TAG, "onMeasure" + widthSpecId);
    setMeasuredDimension(SCREEN_WIDTH, SCREEN_HEIGHT - 
        game.findViewById(R.id.flag).getHeight());
}

2
请参见以下链接:https://dev59.com/hnNA5IYBdhLWcg3wUL5Y - Will Tate
2
这个回答解决了你的问题吗?如何在Android中获取屏幕尺寸作为像素 - AdamHurwitz
更新正确答案:https://dev59.com/Vm445IYBdhLWcg3wq8Pp#67691009 - Rasoul Miri
36个回答

1222

使用以下代码可以获取运行时显示器的宽度和高度:

DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
在视图中,您需要像这样做:
((Activity) getContext()).getWindowManager()
                         .getDefaultDisplay()
                         .getMetrics(displayMetrics);
在某些情况下,在设备具有导航栏的情况下,您需要在运行时进行检查:
public boolean showNavigationBar(Resources resources)
{
    int id = resources.getIdentifier("config_showNavigationBar", "bool", "android");
    return id > 0 && resources.getBoolean(id);
}

如果设备具有导航栏,则计算其高度:

private int getNavigationBarHeight() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int usableHeight = metrics.heightPixels;
        getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
        int realHeight = metrics.heightPixels;
        if (realHeight > usableHeight)
            return realHeight - usableHeight;
        else
            return 0;
    }
    return 0;
}

因此,设备的最终高度为:

int height = displayMetrics.heightPixels + getNavigationBarHeight();

41
如果设备旋转,宽度和高度会交换吗? - Madeyedexter
16
@Madeyedexter 是的,它会。 - Parag Chauhan
1
但是现在你不能再假设你正在使用默认显示器了。 - satur9nine
7
您可以直接使用以下代码进行计算屏幕纵横比:getResources().getDisplayMetrics().heightPixels / getResources().getDisplayMetrics().widthPixels无需额外操作,该代码可直接返回屏幕的纵横比。 - Alex
18
getDefaultDisplay()和getMetrics已被弃用。 - Greelings
显示剩余12条评论

390

有一个非常简单的答案,不需要上下文。

public static int getScreenWidth() {
    return Resources.getSystem().getDisplayMetrics().widthPixels;
}

public static int getScreenHeight() {
    return Resources.getSystem().getDisplayMetrics().heightPixels;
}

注意:如果您想要包括导航栏的高度,请使用下面的方法

WindowManager windowManager =
        (WindowManager) BaseApplication.getApplication().getSystemService(Context.WINDOW_SERVICE);
    final Display display = windowManager.getDefaultDisplay();
    Point outPoint = new Point();
    if (Build.VERSION.SDK_INT >= 19) {
        // include navigation bar
        display.getRealSize(outPoint);
    } else {
        // exclude navigation bar
        display.getSize(outPoint);
    }
    if (outPoint.y > outPoint.x) {
        mRealSizeHeight = outPoint.y;
        mRealSizeWidth = outPoint.x;
    } else {
        mRealSizeHeight = outPoint.x;
        mRealSizeWidth = outPoint.y;
    }

3
如何获取屏幕的总高度?此版本的getScreenHeight方法不包括所有的状态栏和导航栏。 - Jaydev
1
这在大多数情况下都有效,但如果导航栏可见,则无法获取真实的屏幕高度。高度不包括栏的高度。 - L. Swifter
这在横屏模式下对我产生了不寻常的结果。 - Carson Holzheimer
1
这将在具有多个显示屏(可折叠屏幕、Chrome OS笔记本电脑)的屏幕上引起麻烦。 - EpicPandaForce
导航栏的高度在Android 4.4中不包括。 - Hemant Aggarwal
display.getRealSize 已经解决了问题,只有它返回了屏幕的真实尺寸而没有插图! - StayCool

47

仅仅是为了更新parag和SpK的答案,以便与当前SDK的向后兼容性保持一致,弃用了一些方法:

int Measuredwidth = 0;  
int Measuredheight = 0;  
Point size = new Point();
WindowManager w = getWindowManager();

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)    {
    w.getDefaultDisplay().getSize(size);
    Measuredwidth = size.x;
    Measuredheight = size.y; 
}else{
    Display d = w.getDefaultDisplay(); 
    Measuredwidth = d.getWidth(); 
    Measuredheight = d.getHeight(); 
}

7
@digiphd,Parang的代码能够在所有API版本上运行吗?所有的方法都是在API 8级之前引入的,并且我在Android开发者网站上没有找到它们被弃用的信息。 - Sufian
@Sufian 我在三星Galaxy Mini(API 10)上使用getSize实现时遇到了无法获取非0返回值的问题,但是这个答案中的弃用方法可以正确返回。因此,这对于旧版本的Android很有用。 - Damien Diehl
@Sufian,我们可以设置屏幕宽度和高度的新尺寸吗? - Srishti Roy
1
这个现在已经过时了 :( - cegprakash
废弃:对某些术语、功能、设计或实践的不鼓励使用,通常是因为它已被取代或不再被认为是高效或安全的,但并未完全删除或禁止使用。 折旧:资产公允价值的实际减少,或将资产的原始成本在会计报表中分配到使用资产的期间。 - undefined

32

为什么不呢

DisplayMetrics displaymetrics = getResources().getDisplayMetrics();

然后使用

displayMetrics.widthPixels

displayMetrics.heightPixels

在某些设备上,FragmentonViewCreated()中的widthPixelsheightPixels返回0。如果您想计算GridLayoutManager的跨度计数,这真的很烦人。 - Bram Stoker
2
因为它在大多数设备上无法给出真实的屏幕尺寸。 - JacksOnF1re
你需要添加系统栏的WindowInsets才能在大多数设备上获得真实的像素大小。 - backspace83

31

在安卓系统中,这非常容易:

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

2
这在模拟器上返回0。 - jonadv
它无法在大多数设备上提供真实的屏幕尺寸,而只能提供没有窗口插图的区域。我在Google Pixel 4a上尝试了一下,得到的高度为2138px,而不是真实的2340px。您需要添加系统栏的WindowInsets。 - backspace83

27

您可以从 context 中获取宽度和高度。

Java:

  int width= context.getResources().getDisplayMetrics().widthPixels;
  int height= context.getResources().getDisplayMetrics().heightPixels;

Kotlin

    val width: Int = context.resources.displayMetrics.widthPixels
    val height: Int = context.resources.displayMetrics.heightPixels

1
是可用像素吗,还是匹配分辨率,或者其他什么原因? - android developer

22

• 通过扩展属性获取 Kotlin 版本

如果您想要获取屏幕的像素大小以及 dp,使用这些扩展属性可以很方便地实现:


DimensionUtils.kt

import android.content.Context
import android.content.res.Resources
import android.graphics.Rect
import android.graphics.RectF
import android.os.Build
import android.util.DisplayMetrics
import android.view.WindowManager
import kotlin.math.roundToInt

/**
 * @author aminography
 */

private val displayMetrics: DisplayMetrics by lazy { Resources.getSystem().displayMetrics }

/**
 * Returns boundary of the screen in pixels (px).
 */
val screenRectPx: Rect
    get() = displayMetrics.run { Rect(0, 0, widthPixels, heightPixels) }

/**
 * Returns boundary of the screen in density independent pixels (dp).
 */
val screenRectDp: RectF
    get() = screenRectPx.run { RectF(0f, 0f, right.px2dp, bottom.px2dp) }

/**
 * Returns boundary of the physical screen including system decor elements (if any) like navigation
 * bar in pixels (px).
 */
val Context.physicalScreenRectPx: Rect
    get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        (applicationContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager)
            .run { DisplayMetrics().also { defaultDisplay.getRealMetrics(it) } }
            .run { Rect(0, 0, widthPixels, heightPixels) }
    } else screenRectPx

/**
 * Returns boundary of the physical screen including system decor elements (if any) like navigation
 * bar in density independent pixels (dp).
 */
val Context.physicalScreenRectDp: RectF
    get() = physicalScreenRectPx.run { RectF(0f, 0f, right.px2dp, bottom.px2dp) }

/**
 * Converts any given number from pixels (px) into density independent pixels (dp).
 */
val Number.px2dp: Float
    get() = this.toFloat() / displayMetrics.density

/**
 * Converts any given number from density independent pixels (dp) into pixels (px).
 */
val Number.dp2px: Int
    get() = (this.toFloat() * displayMetrics.density).roundToInt()

使用方法:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val widthPx = screenRectPx.width()
        val heightPx = screenRectPx.height()
        println("[PX] screen width: $widthPx , height: $heightPx")

        val widthDp = screenRectDp.width()
        val heightDp = screenRectDp.height()
        println("[DP] screen width: $widthDp , height: $heightDp")

        println()
        
        val physicalWidthPx = physicalScreenRectPx.width()
        val physicalHeightPx = physicalScreenRectPx.height()
        println("[PX] physical screen width: $physicalWidthPx , height: $physicalHeightPx")

        val physicalWidthDp = physicalScreenRectDp.width()
        val physicalHeightDp = physicalScreenRectDp.height()
        println("[DP] physical screen width: $physicalWidthDp , height: $physicalHeightDp")
    }
}

结果:

当设备处于竖屏方向时:

[PX] screen width: 1440 , height: 2392
[DP] screen width: 360.0 , height: 598.0

[PX] physical screen width: 1440 , height: 2560
[DP] physical screen width: 360.0 , height: 640.0
设备处于横屏模式时:
[PX] screen width: 2392 , height: 1440
[DP] screen width: 598.0 , height: 360.0

[PX] physical screen width: 2560 , height: 1440
[DP] physical screen width: 640.0 , height: 360.0

1
这段代码没有考虑到导航栏的高度。 - Johann
1
@AndroidDev:感谢您报告此问题。请使用Context.physicalScreenRectPxContext.physicalScreenRectDp来获取屏幕的真实尺寸。 - aminography

15

API Level 31中,包括Display.getRealMetrics()Display.getRealSize()在内的一些用于检索屏幕大小的方法已不推荐使用。从API Level 30开始,我们可以使用WindowManager#getCurrentWindowMetrics()。获取屏幕大小的正确方法是创建一些兼容类,例如:

object ScreenMetricsCompat {
    private val api: Api =
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) ApiLevel30()
        else Api()

    /**
     * Returns screen size in pixels.
     */
    fun getScreenSize(context: Context): Size = api.getScreenSize(context)

    @Suppress("DEPRECATION")
    private open class Api {
        open fun getScreenSize(context: Context): Size {
            val display = context.getSystemService(WindowManager::class.java).defaultDisplay
            val metrics = if (display != null) {
                DisplayMetrics().also { display.getRealMetrics(it) }
            } else {
                Resources.getSystem().displayMetrics
            }
            return Size(metrics.widthPixels, metrics.heightPixels)
        }
    }

    @RequiresApi(Build.VERSION_CODES.R)
    private class ApiLevel30 : Api() {
        override fun getScreenSize(context: Context): Size {
            val metrics: WindowMetrics = context.getSystemService(WindowManager::class.java).currentWindowMetrics
            return Size(metrics.bounds.width(), metrics.bounds.height())
        }
    }
}

通过在Activity中调用ScreenMetricsCompat.getScreenSize(this).height,我们可以获取屏幕高度。


在 Api 类中,您可以使用 ContextCompat.getSystemService(context, WindowManager::class.java)?.defaultDisplay 而不是 context.getSystemService(WindowManager::class.java).defaultDisplay 来安全地针对低于 23 的 API。 - Islam Khaled

14

请尝试以下代码:

1.

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

2.

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

3.

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

metrics.heightPixels;
metrics.widthPixels;

3
你不觉得2等于4吗? - Trikaldarshiii
你的第二种方法等同于第四种方法。 - Trikaldarshiii
是否可以获取设备的“自然”分辨率?这意味着无论屏幕旋转,您都将获得相同的宽度和高度值,并且如果是横向使用的平板电脑,则会将宽度返回为较大的值而不是高度。 - android developer

12

我建议你创建扩展函数。

/**
 * Return the width and height of the screen
 */
val Context.screenWidth: Int
  get() = resources.displayMetrics.widthPixels

val Context.screenHeight: Int
  get() = resources.displayMetrics.heightPixels

/**
 * Pixel and Dp Conversion
 */
val Float.toPx get() = this * Resources.getSystem().displayMetrics.density
val Float.toDp get() = this / Resources.getSystem().displayMetrics.density

val Int.toPx get() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Int.toDp get() = (this / Resources.getSystem().displayMetrics.density).toInt()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接