关于android:以像素为单位获取屏幕尺寸

Get screen dimensions in pixels

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

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

如何在主Activity中获得screenWidthscreenHeight


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

1
2
3
4
5
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

如果您不在Activity中,则可以通过WINDOW_SERVICE获取默认Display

1
2
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();

如果你在一个片段中想要完成它,只需使用Activity.WindowManager(在Xamarin.Android中)或getActivity()。getWindowManager()(在java中)。

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

1
2
3
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();  // deprecated
int height = display.getHeight();  // deprecated

但是,对于您正在描述的用例,布局中的边距/填充似乎更合适。

另一种方法是:DisplayMetrics

A structure describing general information about a display, such as its size, density, and font scaling. To access the DisplayMetrics members, initialize an object like this:

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

我们可以使用widthPixels获取以下信息:

"The absolute width of the display in pixels."

例:

1
Log.d("ApplicationTagName","Display width in px is" + metrics.widthPixels);


一种方法是:

1
2
3
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();

它已弃用,您应该尝试使用以下代码。前两行代码为您提供DisplayMetrics对象。此对象包含heightPixelswidthPixels等字段。

1
2
3
4
5
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

int height = metrics.heightPixels;
int width = metrics.widthPixels;


它可能无法回答你的问题,但知道(当我提出这个问题时我自己正在寻找它)可能是有用的,如果你需要一个View的维度,但你的代码在布局尚未布局时正在执行(例如在onCreate()中)您可以使用View.getViewTreeObserver().addOnGlobalLayoutListener()设置ViewTreeObserver.OnGlobalLayoutListener并将需要视图维度的相关代码放在那里。布局布局后将调用侦听器的回调。


(2012年回答,可能已过时)如果你想支持precomb,你需要在API 13之前提供向后兼容性。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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的用户,这就是我们留下的。


我尝试了所有可能的"解决方案"并没有成功,我注意到Elliott Hughes的"Dalvik Explorer"应用程序总是在任何Android设备/操作系统版本上显示正确的尺寸。我最后看了他的开源项目,可以在这里找到:https://code.google.com/p/enh/

这是所有相关代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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) {
}

编辑:稍微改进版本(避免在不支持的操作系统版本上触发异常):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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) {
}


最简单的方法:

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

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

示例代码

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

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

快速访问

Enter image description here

有关Title barNavigation barContent View高度的更多信息,请查看Android设备屏幕大小。


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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}


这是我用于任务的代码:

1
2
3
4
5
6
7
8
9
// `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();
}

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


这不是一个更好的解决方案吗? DisplayMetrics提供您需要的一切,并且可以在API 1中使用。

1
2
3
4
5
6
7
8
9
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+。

我错过了什么吗?


对于使用XML动态扩展,有一个名为"android:layout_weight"的属性

以下示例,根据synic在此线程上的响应进行修改,显示占据屏幕75%(重量= .25)的按钮,以及占据屏幕剩余25%(重量= .75)的文本视图。

1
2
3
4
5
6
7
8
9
10
11
12
13
<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>

找到屏幕的宽度和高度:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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);
}

只是添加到Francesco的答案。另一个更贴切的观察者,如果你想找到窗口中的位置或屏幕中的位置是
ViewTreeObserver.OnPreDrawListener()

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


1
2
3
4
DisplayMetrics dimension = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dimension);
int w = dimension.widthPixels;
int h = dimension.heightPixels;

在Activity中使用以下代码。

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

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

第一:

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

第二:

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

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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);
    }
}

我发现这就行了。

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


要获取屏幕尺寸,请使用显示矩阵

1
2
3
4
5
6
DisplayMetrics displayMetrics = new DisplayMetrics();
if (context != null)
      WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
      Display defaultDisplay = windowManager.getDefaultDisplay();
      defaultDisplay.getRealMetrics(displayMetrics);
    }

获取高度和宽度(以像素为单位)

1
2
int width  =displayMetrics.widthPixels;
int height =displayMetrics.heightPixels;

这不是OP的答案,因为他想要实际像素的显示尺寸。我想要"与设备无关的像素"中的维度,并从这里汇总答案https://stackoverflow.com/a/17880012/253938和这里https://stackoverflow.com/a/6656774/253938我出现了有了这个:

1
2
3
    DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
    int dpHeight = (int)(displayMetrics.heightPixels / displayMetrics.density + 0.5);
    int dpWidth = (int)(displayMetrics.widthPixels / displayMetrics.density + 0.5);

我会像这样包装getSize代码:

1
2
3
4
5
6
7
8
9
10
11
12
@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;
}


你可以使用以下方法获得身高:

1
getResources().getDisplayMetrics().heightPixels;

和宽度大小使用

1
getResources().getDisplayMetrics().widthPixels;

使用DisplayMetrics(API 1)有一种不推荐的方法可以避免try / catch杂乱:

1
2
3
4
5
6
7
8
9
 // 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;


对于谁在没有状态栏和操作栏的情况下搜索可用的屏幕尺寸(也感谢Swapnil的回答):

1
2
3
4
5
6
7
8
9
10
11
12
13
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);
}

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

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

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


请遵循以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}


如果您不需要WindowManagers,Points或Displays的开销,则可以获取XML中最顶层View项的height和width属性,前提是它的高度和宽度设置为match_parent。 (只要您的布局占用整个屏幕,这都是正确的。)

例如,如果您的XML以这样的内容开头:

1
2
3
4
5
6
<?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()将返回屏幕的高度。


在活动的onCreate中,有时您需要知道布局的可用空间的精确尺寸。
经过一番思考后,我就这样做了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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清单中添加其他活动,则可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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();
    }
}


我有一个启动画面活动,其中LinearLayout作为根视图,其宽度和宽度都有match_parent;高度。这是该活动的onCreate()方法中的代码。我在应用程序的所有其他活动中使用这些度量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int displayWidth = getRawDisplayWidthPreHoneycomb();
int rawDisplayHeight = getRawDisplayHeightPreHoneycomb();
int usableDisplayHeight = rawDisplayHeight - getStatusBarHeight();
pf.setScreenParameters(displayWidth, usableDisplayHeight);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    LinearLayout myView = (LinearLayout) findViewById(R.id.splash_view);
    myView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
            if (left == 0 && top == 0 && right == 0 && bottom == 0) {
                return;
            }
            int displayWidth = Math.min(right, bottom);
            int usableDisplayHeight = Math.max(right, bottom);
            pf.setScreenParameters(displayWidth, usableDisplayHeight);
        }
    });
}

以下是您在上面看到的方法的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private int getRawDisplayWidthPreHoneycomb() {
    WindowManager windowManager = getWindowManager();
    Display display = windowManager.getDefaultDisplay();
    DisplayMetrics displayMetrics = new DisplayMetrics();
    display.getMetrics(displayMetrics);

    int widthPixels = displayMetrics.widthPixels;
    int heightPixels = displayMetrics.heightPixels;

    return Math.min(widthPixels, heightPixels);
}

private int getRawDisplayHeightPreHoneycomb() {
    WindowManager w = getWindowManager();
    Display d = w.getDefaultDisplay();
    DisplayMetrics metrics = new DisplayMetrics();
    d.getMetrics(metrics);

    int widthPixels = metrics.widthPixels;
    int heightPixels = metrics.heightPixels;

    return Math.max(widthPixels, heightPixels);
}

public int getStatusBarHeight() {
    int statusBarHeight = 0;

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

    return statusBarHeight;
}

这导致可用显示器的高度和宽度,不包括任何类型的条(状态栏,导航栏),适用于所有API版本和不同类型的设备(手机和平板电脑)。


科特林

1
2
3
4
5
6
7
8
9
10
11
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
}

如果Display类不起作用,则上面的答案将无效,那么您可以通过以下方法获得宽度和高度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private static final int WIDTH_INDEX = 0;
private static final int HEIGHT_INDEX = 1;

    public static int[] getScreenSize(Context context) {
        int[] widthHeight = new int[2];
        widthHeight[WIDTH_INDEX] = 0;
        widthHeight[HEIGHT_INDEX] = 0;

        try {
            WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            Display display = windowManager.getDefaultDisplay();

            Point size = new Point();
            display.getSize(size);
            widthHeight[WIDTH_INDEX] = size.x;
            widthHeight[HEIGHT_INDEX] = size.y;

            if (!isScreenSizeRetrieved(widthHeight))
            {
                DisplayMetrics metrics = new DisplayMetrics();
                display.getMetrics(metrics);
                widthHeight[0] = metrics.widthPixels;
                widthHeight[1] = metrics.heightPixels;
            }

            // Last defense. Use deprecated API that was introduced in lower than API 13
            if (!isScreenSizeRetrieved(widthHeight)) {
                widthHeight[0] = display.getWidth(); // deprecated
                widthHeight[1] = display.getHeight(); // deprecated
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return widthHeight;
    }

    private static boolean isScreenSizeRetrieved(int[] widthHeight) {
        return widthHeight[WIDTH_INDEX] != 0 && widthHeight[HEIGHT_INDEX] != 0;
    }

简单的功能也兼容较低版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * @return screen size int[width, height]
 *
 * */
public int[] getScreenSize(){
    Point size = new Point();
    WindowManager w = getWindowManager();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2){
        w.getDefaultDisplay().getSize(size);
        return new int[]{size.x, size.y};
    }else{
        Display d = w.getDefaultDisplay();
        //noinspection deprecation
        return new int[]{d.getWidth(), d.getHeight()};
    }
}

使用:

1
2
int width = getScreenSize()[0];
int height = getScreenSize()[1];

此函数返回以英寸为单位的近似屏幕尺寸。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public double getScreenSize()
{
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int width=dm.widthPixels;
        int height=dm.heightPixels;
        int dens=dm.densityDpi;
        double wi=(double)width/(double)dens;
        double hi=(double)height/(double)dens;
        double x = Math.pow(wi,2);
        double y = Math.pow(hi,2);
        double screenInches = Math.sqrt(x+y);
        return screenInches;
}

以下是Kotlin实现中上述一些答案的简单改编。如上所述,它需要清单中的windowsSoftInput ="adjustResize":

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class KeyboardWatcher(private val layoutRooView: View) {

    companion object {
        private const val MIN_KEYBOARD_HEIGHT = 200f
    }

    private val displayMetrics: DisplayMetrics = layoutRooView.resources.displayMetrics
    private var stateVisible = false

    var observer: ((Boolean) -> Unit)? = null

    init {
        layoutRooView.viewTreeObserver.addOnGlobalLayoutListener {
            val heightDiff = layoutRooView.rootView.height - layoutRooView.height
            if (!stateVisible && heightDiff > dpToPx(MIN_KEYBOARD_HEIGHT)) {
                stateVisible = true
                observer?.invoke(stateVisible)
            } else if(stateVisible) {
                stateVisible = false
                observer?.invoke(stateVisible)
            }
        }
    }

    private fun dpToPx(valueInDp: Float): Float {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, displayMetrics)
    }
}

并使用:

1
2
3
4
val activityRootView = findViewById<ViewGroup>(R.id.activityRoot)
KeyboardWatcher(activityRootView).observer = { visible ->
    if (visible) do something here ...
}

请注意,这些API返回的高度将低于设备的物理高度,因为减去了按钮栏的高度。

例如:在Moto X4上,它返回正确的widthPixels(1080)但它返回的高度为1776,即使设备的屏幕高度为1920像素。


1
2
3
DisplayMetrics dm = getResources().getDisplayMetrics();
float fwidth = dm.density * dm.widthPixels;
float fheight = dm.density * dm.heightPixels;

如果getSize因minSDKVersion而导致错误,并且您不想使用弃用的方法(getWidth&amp; getHeight),那么getMetrics解决方案最初是由Balaji.K于2011年发布的... Nik添加了一条评论,解释getDisplayMetrics也考虑了状态栏的大小。

其他一些注释指的是乘以比例(密度)以获得尺寸的精确浮点值。在Android v2.2(API 8)和v4.0中测试,结果良好,没有错误/警告。


我使用了上面的提案并为我们的问题创建了一个kotlin版本。希望这为使用kotlin的人提供一些额外的帮助:

1
2
3
4
5
6
7
8
9
10
11
12
13
private val screenDimensions: Int by lazy {
    val display = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
    Point()
        .also { size ->
            when {
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> display.getRealSize(size)
                else -> display.getSize(size)
            }
        }
}

screenDimensions.x // width
screenDimensions.y // height

我认为这是最简单的

1
2
3
4
5
6
7
8
9
10
11
12
private fun checkDisplayResolution() {
    val displayMetrics = DisplayMetrics().also {
        windowManager.defaultDisplay.getMetrics(it)
    }

    Log.i(TAG,"display width: ${displayMetrics.widthPixels}")
    Log.i(TAG,"display height: ${displayMetrics.heightPixels}")
    Log.i(TAG,"display width dpi: ${displayMetrics.xdpi}")
    Log.i(TAG,"display height dpi: ${displayMetrics.ydpi}")
    Log.i(TAG,"display density: ${displayMetrics.density}")
    Log.i(TAG,"display scaled density: ${displayMetrics.scaledDensity}")
}