如何在Android中运行时以dp或dip来确定屏幕宽度?

226

我需要使用dip/dp(在java文件中)编写android小部件的布局。 在运行时,如果我编码:

    int pixel = this.getWindowManager().getDefaultDisplay().getWidth();

这将返回屏幕宽度(以像素为单位px)。 要将其转换为dp,我编码了:

            int dp = pixel /(int)getResources()。getDisplayMetrics()。density;

这似乎没有返回正确的答案。 我制作了WVGA800仿真器,其屏幕分辨率为480 x 800。 当运行仿真器并让代码打印pixel和dp的值时,两者都变成了320。 这个仿真器是240dpi,其比例因子将是0.75。

12个回答

412

如 @Tomáš Hubálek 所提到的;
尝试类似以下的方法:

DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();    
float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;

或者

尝试旧的答案:

Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);
         
float density  = getResources().getDisplayMetrics().density;
float dpHeight = outMetrics.heightPixels / density;
float dpWidth  = outMetrics.widthPixels / density;

94
为什么需要调用WindowManager?这段代码是做什么的?DisplayMetrics displayMetrics = resources.getDisplayMetrics(); float screenWidthDp = displayMetrics.widthPixels / displayMetrics.density; 这段代码是获取屏幕宽度并以dp为单位进行测量,需要调用WindowManager来获取DisplayMetrics对象。 - Tomáš Hubálek
2
这在我使用高密度屏幕时没有起作用。就好像它只获取了屏幕的一小部分。这个解决方案对我有用:https://dev59.com/Juo6XIcBkEYKwwoYNBdQ#18712361Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); int width = size.x; int height = size.y; - marienke
1
@dsdsdsdsd:context 是 Context 类的任何实例。特别是,Activity 是 Context 的子类(因此在 Activity 中使用 this,在 Fragment 中使用 getActivity())。Application 和 Service 也是 Context 的子类。 - François POYER
在可折叠和其他多屏设备上使用 Resources.getSystem() 不起作用。还请参阅 http://developer.android.com/guide/practices/screens_support.html#dips-pels - EpicPandaForce

128

我通过谷歌发现了这个问题,后来我找到了一个适用于API >= 13的简单解决方案。

供以后参考:

Configuration configuration = yourActivity.getResources().getConfiguration();
int screenWidthDp = configuration.screenWidthDp; //The current width of the available screen space, in dp units, corresponding to screen width resource qualifier.
int smallestScreenWidthDp = configuration.smallestScreenWidthDp; //The smallest screen size an application will see in normal operation, corresponding to smallest screen width resource qualifier.

请参阅Configuration类引用

编辑:如Nick Baicoianu所指出,此方法返回屏幕的可用宽度/高度(在大多数情况下应该是最有用的)。如果您需要实际显示尺寸,请使用上面的答案。


28
使用 Configuration 的 screenWidthDp/screenHeightDp 和 DisplayMetrics 的 widthPixels/heightPixels 之间的一个重要区别是,Configuration 返回的是可用显示尺寸(减去状态栏等),而 DisplayMetrics 返回的是全屏尺寸。 - Nick Baicoianu
仅适用于API Level 13及以上。 - ono
补充@NickBaicoianu的评论,getConfiguration()和getDisplayMetrics()方法都可以在多窗口模式下使用,即尺寸反映窗口大小,而不是屏幕大小。 - nmw

31

2023年 Kotlin 的简化回答:

val widthDp = resources.displayMetrics.run { widthPixels / density }
val heightDp = resources.displayMetrics.run { heightPixels / density }
作为一行代码:
val (height, width) = resources.displayMetrics.run { heightPixels/density to widthPixels/density }

对于 Jetpack Compose:

val (height, width) = LocalConfiguration.current.run { screenHeightDp.dp to screenWidthDp.dp }

但是密度在哪里?我猜还需要更多的代码行。 - mcfly soft
“density”来自于run块内的“DisplayMetrics”。 - Frid

11

用这个会怎样呢?

final DisplayMetrics displayMetrics=getResources().getDisplayMetrics();
final float screenWidthInDp=displayMetrics.widthPixels/displayMetrics.density;
final float screenHeightInDp=displayMetrics.heightPixels/displayMetrics.density;

8
你缺少默认密度值160。
    2 px = 3 dip if dpi == 80(ldpi), 320x240 screen
    1 px = 1 dip if dpi == 160(mdpi), 480x320 screen
    3 px = 2 dip if dpi == 240(hdpi), 840x480 screen

换句话说,如果你在竖屏模式下将布局设计为宽度等于160dip,那么在所有ldpi/mdpi/hdpi设备上(除了平板电脑,我认为),它将占据屏幕的一半。

你所回答的是我问题背后的逻辑推理,我理解了。那么我该如何在Java中编写代码,以便在运行时无论屏幕分辨率如何,代码都能选择正确的dpi宽度? - Khushboo
希望这次我能翻译正确:)在Activity中使用DisplayMetrics outMetrics = null; getWindowManager().getDefaultDisplay().getMetrics(outMetrics);。然后,outMetrics.density将给出当前设备的比例因子,如文档所述。 - Mykhailo Gaidai

7
DisplayMetrics displayMetrics = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

int width_px = Resources.getSystem().getDisplayMetrics().widthPixels;

int height_px =Resources.getSystem().getDisplayMetrics().heightPixels;

int pixeldpi = Resources.getSystem().getDisplayMetrics().densityDpi;


int width_dp = (width_px/pixeldpi)*160;
int height_dp = (height_px/pixeldpi)*160;

9
考虑提供一些解释。 - bigbounty
在可折叠屏幕和其他多屏设备上使用 Resources.getSystem() 不太好用。 - EpicPandaForce

5

Kotlin的答案:

  context?.let {
        val displayMetrics = it.resources.displayMetrics
        val dpHeight = displayMetrics.heightPixels / displayMetrics.density
        val dpWidth = displayMetrics.widthPixels / displayMetrics.density
    }

3
在新的Compose世界中,一行搞定。
val (height, width) = LocalConfiguration.current.run { screenHeightDp.dp to screenWidthDp.dp }

2
这是一个可以根据之前的回复进行复制和粘贴使用的函数。
  /**
     * @param context
     * @return the Screen height in DP
     */
    public static float getHeightDp(Context context) {
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
        return dpHeight;
    }

    /**
     * @param context
     * @return the screnn width in dp
     */
    public static float getWidthDp(Context context) {
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
        return dpWidth;
    }

2

使用一些好的修饰获取屏幕宽度和高度的DP值:

步骤1:创建接口

public interface ScreenInterface {

   float getWidth();

   float getHeight();

}

步骤2:创建实现类
public class Screen implements ScreenInterface {
    private Activity activity;

    public Screen(Activity activity) {
        this.activity = activity;
    }

    private DisplayMetrics getScreenDimension(Activity activity) {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics;
    }

    private float getScreenDensity(Activity activity) {
        return activity.getResources().getDisplayMetrics().density;
    }

    @Override
    public float getWidth() {
        DisplayMetrics displayMetrics = getScreenDimension(activity);
        return displayMetrics.widthPixels / getScreenDensity(activity);
    }

    @Override
    public float getHeight() {
        DisplayMetrics displayMetrics = getScreenDimension(activity);
        return displayMetrics.heightPixels / getScreenDensity(activity);
    }
} 

步骤三:在活动中获取宽度和高度:

Screen screen = new Screen(this); // Setting Screen
screen.getWidth();
screen.getHeight();

这会返回像素或 dp 中的高度和宽度吗? - Taslim Oseni
1
作为被调用的.density,这就是为什么它以dp形式呈现给您的原因。 - Ali Azaz Alam
我认为在应用程序中添加大量代码来解决简单任务并不是一个好主意。 - Ruslan Berozov
1
先生,您可以选择实现类或直接编写代码。从定义的类中,您可以轻松提取用于直接实现的代码。 - Ali Azaz Alam

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