【问题标题】:Detect 7 inch and 10 inch tablet programmatically以编程方式检测 7 英寸和 10 英寸平板电脑
【发布时间】:2013-02-24 19:08:08
【问题描述】:

有没有办法以编程方式查找安装应用程序的设备是 7 英寸平板电脑还是 10 英寸平板电脑?

【问题讨论】:

  • 例如:layout-sw600dp 寻找最小宽度尺寸 600dp。
  • 我明白了,但是您要以编程方式寻找什么?
  • 我需要以编程方式获取这些设备。因为有些属性我无法在 xml 中定义。这些属性是在代码本身中定义的。所以如果我简单地输入代码,它将适用于所有设备..但我不想要那个..
  • @Raghav 您是否尝试过使用显示矩阵来获取屏幕尺寸,然后您可以进行比较。虽然它不是一个干净的方式,但你可以使用。
  • 您可以获取屏幕尺寸并从那里开始计算...stackoverflow.com/questions/1016896/…

标签: android android-layout screen


【解决方案1】:

您可以使用DisplayMetrics 获取有关您的应用正在运行的屏幕的大量信息。

首先,我们创建一个DisplayMetrics 指标对象:

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

由此,我们可以得到显示尺寸所需的信息:

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

这将返回以像素为单位的宽度和高度的绝对值,因此 Galaxy SIII、Galaxy Nexus 等为 1280x720。

这本身通常没有帮助,因为当我们在 Android 设备上工作时,我们通常更喜欢在与密度无关的像素中工作,dip。

您再次使用metrics 以设备比例因子的形式获得屏幕的density,它基于mdpi、hdpi 等的Android Design Resources。

float scaleFactor = metrics.density;

根据这个结果,我们可以计算出特定高度或宽度下与密度无关的像素数量。

float widthDp = widthPixels / scaleFactor
float heightDp = heightPixels / scaleFactor

您从中获得的结果将帮助您确定正在使用的屏幕类型以及 Android Configuration examples,它为您提供每种屏幕尺寸的相对 dp:

  • 320dp:典型的手机屏幕(240x320 ldpi、320x480 mdpi、480x800 hdpi 等)。
  • 480dp:类似于 Streak (480x800 mdpi) 的补间平板电脑。
  • 600dp:7 英寸平板电脑 (600x1024 mdpi)。
  • 720dp:10 英寸平板电脑(720x1280 mdpi、800x1280 mdpi 等)。

通过以上信息,我们知道如果设备的最小宽度大于 600dp,则该设备为 7" 平板电脑,如果大于 720dp,则该设备为 10" 平板电脑。

我们可以使用Math类的min函数计算出最小宽度,传入heightDp和widthDp以返回smallestWidth。

float smallestWidth = Math.min(widthDp, heightDp);

if (smallestWidth > 720) {
    //Device is a 10" tablet
} 
else if (smallestWidth > 600) {
    //Device is a 7" tablet
}

但是,这并不总是给您一个完全匹配的结果,尤其是在使用不起眼的平板电脑时,这些平板电脑可能会将其密度错误地表示为 hdpi,而实际上它不是,或者可能只有 800 x 480 像素但仍然在7" 屏幕。

除了这些方法之外,如果您需要知道设备的确切尺寸(以英寸为单位),您也可以使用metrics 方法来计算每英寸屏幕有多少像素。

float widthDpi = metrics.xdpi;
float heightDpi = metrics.ydpi;

您可以根据设备每英寸的像素数以及总像素数来计算设备的英寸数。

float widthInches = widthPixels / widthDpi;
float heightInches = heightPixels / heightDpi;

这将返回设备的高度和宽度(以英寸为单位)。这对于确定它是什么类型的设备并不总是那么有帮助,因为设备的广告尺寸是对角线,我们所拥有的只是高度和宽度。

但是,我们也知道,给定三角形的高度和宽度,我们可以使用勾股定理计算出斜边的长度(在这种情况下,是屏幕对角线的大小)。

//a² + b² = c²

//The size of the diagonal in inches is equal to the square root of the height in inches squared plus the width in inches squared.
double diagonalInches = Math.sqrt(
    (widthInches * widthInches) 
    + (heightInches * heightInches));

由此我们可以判断设备是否是平板电脑:

if (diagonalInches >= 10) {
    //Device is a 10" tablet
} 
else if (diagonalInches >= 7) {
    //Device is a 7" tablet
}

这就是您计算正在使用的设备类型的方式。

【讨论】:

  • 优秀的提示肖恩。我曾经用 px 检查平板电脑,但在某些情况下会出现问题(Galaxy 3、4、Note,px 等于或大于 Nexus 7)。现在我也可以检查英寸。以下是许多流行设备屏幕规格的列表:en.wikipedia.org/wiki/List_of_displays_by_pixel_density
  • 不要使用 xdpi 或 ydpi。这些是可选的,将由制造商设置,而不是计算。它们通常未使用或不准确。
  • 使用你的方法来获取 dpi 的宽度,我会根据方向得到不同的结果。例如对于 Nexus 7:肖像:最小宽度 = 600.9;景观:最小宽度= 552.8;这是什么原因?
  • if (smallestWidth > 600) { /* 7" */ } else if (smallestWidth > 720) { /* 10" */ } 的逻辑有缺陷:10" 平板电脑被识别为 7"。我冒昧地解决了这个问题。
  • 最终我选择了DeeV's answer 中的resources.getConfiguration().smallestScreenWidthDp,这是在我的 Nexus 7 (600dp) 上在纵向和横向上提供相同值的唯一方法。它是在 API 级别 13 中添加的。
【解决方案2】:

没有任何内容表明 7" 或 10" AFAIK。大致有两种方法可以获得系统在解码位图时使用的屏幕尺寸等等。它们都可以在应用程序的 Resources 对象中找到,该对象位于 Context 中。

首先是Configuration对象,可以通过getContext().getResources().getConfiguration()获取。在里面你有:

Configuration#densityDpi - 渲染到的目标屏幕密度,对应于密度资源限定符。

Configuration#screenHeightDp - 可用屏幕空间的当前高度,以dp为单位,对应屏幕高度资源限定符。

Configuration#screenWidthDp - 可用屏幕空间的当前宽度,以dp为单位,对应屏幕宽度资源限定符。

Configuration#smallestScreenWidthDp - 应用程序在正常操作中看到的最小屏幕尺寸,对应于最小屏幕宽度资源限定符。

这样,您几乎可以使用屏幕指南来确定您的设备是否从相应的专用资源文件夹(hdpi、xhdpi、large、xlarge 等)中提取。

请记住,这些是一些桶:

  • xlarge 屏幕至少为 960dp x 720dp
  • 大屏幕至少为 640dp x 480dp
  • 普通屏幕至少为 470dp x 320dp
  • 小屏幕至少为 426dp x 320dp

  • 320dp:典型的手机屏幕(240x320 ldpi、320x480 mdpi、480x800 hdpi 等)。

  • 480dp:类似于 Streak (480x800 mdpi) 的补间平板电脑。
  • 600dp:7 英寸平板电脑 (600x1024 mdpi)。
  • 720dp:10 英寸平板电脑(720x1280 mdpi、800x1280 mdpi 等)。

More info

第二个是getContext().getResources().getDisplayMetrics()得到的DisplayMetrics对象。因为你有:

DisplayMetrics#density - 显示的逻辑密度。

DisplayMetrics#densityDpi - 以每英寸点数表示的屏幕密度。

DisplayMetrics#heightPixels - 显示的绝对高度,以像素为单位。

DisplayMetrics#widthPixels - 显示的绝对宽度,以像素为单位。

DisplayMetrics#xdpi - X 维度上每英寸屏幕的精确物理像素。

DisplayMetrics#ydpi - Y 维度上每英寸屏幕的精确物理像素。

如果您需要屏幕的精确像素数而不是密度,这很方便。但是,请务必注意,这是所有屏幕的像素。不仅仅是您可以使用的。

【讨论】:

  • +1,我使用smallestScreenWidthDp 获得了最好的结果。与其他解决方案不同,它在我的 Nexus 7 (600dp) 上提供相同的值无论方向如何。作为奖励,它也是最简单的代码!
  • 我认为这仍然是最好的方法,因为它应该与资源路径上的 sw???dp 表示法匹配。一致性很重要。
【解决方案3】:

将此方法放在onResume()中即可查看。

public double tabletSize() {

     double size = 0;
        try {

            // Compute screen size

            DisplayMetrics dm = context.getResources().getDisplayMetrics();

            float screenWidth  = dm.widthPixels / dm.xdpi;

            float screenHeight = dm.heightPixels / dm.ydpi;

            size = Math.sqrt(Math.pow(screenWidth, 2) +

                                 Math.pow(screenHeight, 2));

        } catch(Throwable t) {

        }

        return size;

    }

通常平板电脑在 6 英寸大小后开始。

【讨论】:

  • 这个不适用于三星新设备,如 S20 Ultra。此计算还会为平板电脑选择这些设备。
【解决方案4】:

在切换纵向与横向时,上述方法并不总是有效。

如果您的目标是 API 级别 13+,如上所述很容易 - 使用 Configuration.smallestScreenWidthDp,然后进行相应的测试:

resources.getConfiguration().smallestScreenWidthDp

否则,如果您负担得起,请使用以下方法,通过让系统告诉您,这是一种非常准确的方法来检测 600dp(如 6")与 720dp(如 10"):

1) 向 layout-sw600dp 和 layout-sw720dp(以及如果适用的话其横向)添加一个具有适当 ID 的不可见视图,例如:

对于 720,在 layout-sw720dp 上:

<View android:id="@+id/sw720" android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/>

对于 600,在 layout-sw600dp 上:

<View android:id="@+id/sw600" android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/>

2)然后在代码上,例如Activity,进行相应的测试:

private void showFragment() {
    View v600 = (View) findViewById(R.id.sw600);
    View v720 = (View) findViewById(R.id.sw720);
    if (v600 != null || v720 !=null)
        albumFrag = AlbumGridViewFragment.newInstance(albumRefresh);
    else
        albumFrag = AlbumListViewFragment.newInstance(albumRefresh);
    getSupportFragmentManager()
        .beginTransaction()
        .replace(R.id.view_container, albumFrag)
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
        .commit();
}

【讨论】:

  • 你不需要创建一个单独的布局,我相信你可以有一个基于大小的单独的strings.xml,通过不同的值文件夹,比如values-sw600dp等。有一个字符串在 sw600dp 文件夹中定义 600dp 等。它甚至不必是字符串,它可以在 ints.xml 或 dimens.xml 中。
【解决方案5】:

很好的信息,正是我想要的!但是,在尝试了这个之后,我发现使用此处提到的指标时,Nexus 7(2012 型号)报告的尺寸为 1280x736。我还有一个运行 Jelly Bean 的摩托罗拉 Xoom,它错误地报告了 1280x752 的分辨率。我偶然发现了这篇帖子here 证实了这一点。基本上,在 ICS/JB 中,使用上述指标的计算似乎排除了导航栏的尺寸。更多的研究使我找到了Frank Nguyen's answer here,它使用不同的方法为您提供屏幕的原始(或真实)像素尺寸。我的初始测试表明,来自 Frank correclty 的以下代码报告了 Nexus 7(运行 JB 的 2012 型号)和运行 JB 的摩托罗拉 Xoom 的尺寸:

int width = 0, height = 0;
final DisplayMetrics metrics = new DisplayMetrics();
Display display = getWindowManager().getDefaultDisplay();
Method mGetRawH = null, mGetRawW = null;

try {
    // For JellyBeans and onward
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
        display.getRealMetrics(metrics);

        width = metrics.widthPixels;
        height = metrics.heightPixels;
    } else {
        mGetRawH = Display.class.getMethod("getRawHeight");
        mGetRawW = Display.class.getMethod("getRawWidth");

        try {
            width = (Integer) mGetRawW.invoke(display);
            height = (Integer) mGetRawH.invoke(display);
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
} catch (NoSuchMethodException e3) {
    e3.printStackTrace();
}

【讨论】:

    【解决方案6】:

    我有两个分辨率相同的安卓设备

    Device1 -> 分辨率 480x800 屏幕对角线尺寸 -> 4.7 英寸

    Device2 -> 分辨率 480x800 屏幕对角线尺寸 -> 4.0 英寸

    它提供了两个设备的屏幕对角线尺寸 -> 5.8

    您的问题的解决方案是..

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

    见details here..

    【讨论】:

      【解决方案7】:

      Android 指定screen sizes 的方式是通过四种通用尺寸:small、normal、large 和 xlarge em>。

      虽然 Android documentation 声明尺寸组已弃用

      ...这些尺寸组已被弃用,取而代之的是一种基于 可用的屏幕宽度。如果您正在为 Android 3.2 和 更大,请参阅 [为 Android 3.2 声明平板电脑布局]( hdpi(高)~240dpi)更多 信息。

      通常,尺寸限定符 large 指定 7" 平板电脑。尺寸限定符 xlarge 指定 10" 平板电脑:

      触发大小限定符的好处是,您可以保证您的资产和代码在使用哪个资产或激活代码路径上是一致的。

      要在代码中检索大小限定符,请进行以下调用:

      int sizeLarge = SCREENLAYOUT_SIZE_LARGE // For 7" tablet
      boolean is7InchTablet = context.getResources().getConfiguration()
          .isLayoutSizeAtLeast(sizeLarge);
      
      int sizeXLarge = SCREENLAYOUT_SIZE_XLARGE // For 10" tablet
      boolean is10InchTablet = context.getResources().getConfiguration()
          .isLayoutSizeAtLeast(sizeXLarge);
      

      【讨论】:

        【解决方案8】:

        您可以使用以下方法获取以英寸为单位的屏幕尺寸, 基于此,您可以简单地检查设备是哪个平板电脑或手机。

        private static double checkDimension(Context context) {
        
            WindowManager windowManager = ((Activity)context).getWindowManager();
            Display display = windowManager.getDefaultDisplay();
            DisplayMetrics displayMetrics = new DisplayMetrics();
            display.getMetrics(displayMetrics);
        
            // since SDK_INT = 1;
            int mWidthPixels = displayMetrics.widthPixels;
            int mHeightPixels = displayMetrics.heightPixels;
        
            // includes window decorations (statusbar bar/menu bar)
            try
            {
                Point realSize = new Point();
                Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize);
                mWidthPixels = realSize.x;
                mHeightPixels = realSize.y;
            }
            catch (Exception ignored) {}
        
            DisplayMetrics dm = new DisplayMetrics();
            windowManager.getDefaultDisplay().getMetrics(dm);
            double x = Math.pow(mWidthPixels/dm.xdpi,2);
            double y = Math.pow(mHeightPixels/dm.ydpi,2);
            double screenInches = Math.sqrt(x+y);
            Log.d("debug","Screen inches : " + screenInches);
            return screenInches;
        }
        

        【讨论】:

          【解决方案9】:

          我在 values 文件夹中存储了一个值,它给我的屏幕是 7 英寸或 10 英寸,但我们可以使用 values 文件夹为任何设备做到这一点。

          例如为不同的 2 设备创建不同的 2 值文件夹。但这东西要看需求。

          【讨论】:

            【解决方案10】:

            您必须使用DisplayMetrics 类提供的数据进行一些计算。

            你有 heightPixel 和 widthPixels(以像素为单位的屏幕分辨率)

            您需要对角线,因为“​​英寸屏幕尺寸”总是描述对角线长度。 您可以以像素为单位获取屏幕对角线(使用 pythagore)

            diagonalPixel = √(heightPixel² + widthPixels² )

            然后您可以通过 densityDPI 值将像素值转换为英寸:

            inchDiag = 对角像素 / 密度 DPI。

            我希望我没有在这里犯错,请注意,您从 DisplayMetrics 类中获得的值是由构造函数给出的,看起来(在极少数情况下)它们没有根据物理材料很好地设置。 ..

            这将为您提供物理屏幕尺寸,但它可能不是管理多个布局的更好方法。 More on this topics

            【讨论】:

              【解决方案11】:

              另一种方式:

              • 再创建 2 个文件夹:values-large + values-xlarge

              • 将:&lt;string name="screentype"&gt;LARGE&lt;/string&gt; 放入 values-large 文件夹 (strings.xml)

              • 将:&lt;string name="screentype"&gt;XLARGE&lt;/string&gt; 放入 values-xlarge 文件夹 (strings.xml)

              • 在代码中:

                String mType = getString(R.string.screentype);

                if (mType != null && mType.equals("LARGE") {

                //从4~7英寸

                } else if (mType != null && mType.equals("XLARGE") {

                //从7~10英寸

                }

              【讨论】:

                【解决方案12】:

                瞧! ? 这就是区分平板电脑和手机所需的全部内容

                1.获取屏幕宽度的辅助函数:

                private float getScreenWidth() {
                    DisplayMetrics metrics = new DisplayMetrics();
                    getWindowManager().getDefaultDisplay().getMetrics(metrics);
                    return Math.min(metrics.widthPixels, metrics.heightPixels) / metrics.density;
                }
                

                2.判断设备是否为平板电脑的函数

                boolean isTablet() {
                    return getScreenWidth() >= 600;
                }
                

                3.最后,如果您希望针对不同的设备尺寸执行不同的操作:

                boolean is7InchTablet() {
                    return getScreenWidth() >= 600 && getScreenWidth() < 720;
                }
                
                boolean is10InchTablet() {
                    return getScreenWidth() >= 720;
                }
                

                【讨论】:

                  【解决方案13】:

                  这里有一些有用的 kotlin 扩展:

                      
                      fun DisplayMetrics.isTablet(): Boolean {
                          return getScreenWidth() >= 600
                      }
                      
                      fun DisplayMetrics.is7InchTablet(): Boolean {
                          return getScreenWidth() >= 600 && getScreenWidth() < 720
                      }
                      
                      fun DisplayMetrics.is10InchTablet(): Boolean {
                          return getScreenWidth() >= 720
                      }
                      
                      fun DisplayMetrics.getScreenWidth(): Float {
                          return widthPixels.coerceAtMost(heightPixels) / density
                      }
                  
                  

                  【讨论】:

                  • 行得通!但是您应该使用正确的 DisplayMetrics,例如来自 Resources in Context: resources.displayMetrics.isTablet() 或来自存储在 Activity 中的 WindowManager: val displayMetrics = DisplayMetrics() windowManager.defaultDisplay.getMetrics(displayMetrics) displayMetrics.isTablet()
                  猜你喜欢
                  • 2013-11-01
                  • 2013-06-18
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-08-18
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多