有没有一种方法可以检查用户使用的是平板电脑还是电话?我的倾斜功能和新平板电脑(变形金刚)出现问题
有没有一种方法可以检查用户使用的是平板电脑还是电话?我的倾斜功能和新平板电脑(变形金刚)出现问题
Answers:
如前所述,您不想检查该设备是平板电脑还是电话,但想了解该设备的功能,
通常,平板电脑和手机之间的区别在于屏幕尺寸,这就是为什么要使用不同的布局文件的原因。这些文件存储在res/layout-<qualifiers>
目录中。您可以在目录中res/values-<same qualifiers>
为每个布局创建一个XML文件,并将int / bool / string资源放入其中,以区分所使用的布局。
文件res/values/screen.xml
(假设res/layout/
包含手机的布局文件)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="screen_type">phone</string>
</resources>
文件res/values-sw600dp/screen.xml
(假设res/layout-sw600dp/
包含用于Nexus 7等小型平板电脑的布局文件)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="screen_type">7-inch-tablet</string>
</resources>
文件res/values-sw720dp/screen.xml
(假设res/layout-sw720dp/
包含大型平板电脑(如Nexus 10)的布局文件):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="screen_type">10-inch-tablet</string>
</resources>
现在可以通过R.string.screen_type
常量访问屏幕类型。
要检测设备是否为平板电脑,请使用以下代码:
public boolean isTablet(Context context) {
boolean xlarge = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE);
boolean large = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE);
return (xlarge || large);
}
大型和超大型屏幕尺寸由制造商根据要使用的距眼睛的距离来确定(因此就是平板电脑的概念)。
更多信息:http : //groups.google.com/group/android-developers/browse_thread/thread/d6323d81f226f93f
Configuration.SCREENLAYOUT_SIZE_XLARGE
,因此您不必使用常量,可以使用>= LARGE
。
这篇文章对我有很大帮助,
不幸的是,我没有足够的声誉来评估对我有帮助的所有答案。
我需要确定我的设备是平板电脑还是手机,这样我才能实现屏幕逻辑。在我的分析中,平板电脑的MDPI开始必须大于7英寸(Xlarge)。
这是下面的代码,这些代码是根据这篇文章创建的。
/**
* Checks if the device is a tablet or a phone
*
* @param activityContext
* The Activity Context.
* @return Returns true if the device is a Tablet
*/
public static boolean isTabletDevice(Context activityContext) {
// Verifies if the Generalized Size of the device is XLARGE to be
// considered a Tablet
boolean xlarge = ((activityContext.getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK) ==
Configuration.SCREENLAYOUT_SIZE_XLARGE);
// If XLarge, checks if the Generalized Density is at least MDPI
// (160dpi)
if (xlarge) {
DisplayMetrics metrics = new DisplayMetrics();
Activity activity = (Activity) activityContext;
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
// MDPI=160, DEFAULT=160, DENSITY_HIGH=240, DENSITY_MEDIUM=160,
// DENSITY_TV=213, DENSITY_XHIGH=320
if (metrics.densityDpi == DisplayMetrics.DENSITY_DEFAULT
|| metrics.densityDpi == DisplayMetrics.DENSITY_HIGH
|| metrics.densityDpi == DisplayMetrics.DENSITY_MEDIUM
|| metrics.densityDpi == DisplayMetrics.DENSITY_TV
|| metrics.densityDpi == DisplayMetrics.DENSITY_XHIGH) {
// Yes, this is a tablet!
return true;
}
}
// No, this is not a tablet!
return false;
}
为什么不计算屏幕对角线的大小,并以此来确定设备是手机还是平板电脑?
private boolean isTablet()
{
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
display.getMetrics(displayMetrics);
int width = displayMetrics.widthPixels / displayMetrics.densityDpi;
int height = displayMetrics.heightPixels / displayMetrics.densityDpi;
double screenDiagonal = Math.sqrt( width * width + height * height );
return (screenDiagonal >= 9.0 );
}
当然,可以争论阈值是否应为9英寸或更小。
没有区别。您应该定义自己认为的区别,然后进行检查。银河标签是手机吗?或平板电脑?为什么呢?
您应该定义要查找的特定功能,并为此编写代码。
看来您正在寻找“倾斜”。我认为这与加速度计是一样的(是一个词吗?)。您可以使用以下方法检查设备是否支持:
public class Accel extends Activity implements SensorListener {
...
SensorManager sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
boolean accelSupported = sensorMgr.registerListener(this,
SENSOR_ACCELEROMETER,
SENSOR_DELAY_UI);
...
}
(来自http://stuffthathappens.com/blog/2009/03/15/android-accelerometer/。我尚未对其进行测试)
我的假设是,当您定义“手机/电话”时,您希望知道是否可以在设备上拨打电话,而这在定义为“平板电脑”的设备上无法完成。验证方法如下。如果您想基于传感器,屏幕尺寸等来了解某些信息,那么这确实是一个不同的问题。
此外,在使用屏幕分辨率或大型资源管理还是大型资源管理时,在过去可能是一种有效的方法,新的“移动”设备现在具有如此大的屏幕和高分辨率,以至于模糊了这条线,而如果您真的希望要了解电话与无电话功能,以下是“最好的”。
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
if(manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE){
return "Tablet";
}else{
return "Mobile";
}
基于罗伯特·戴尔·约翰逊三世(Robert Dale Johnson III)和海尔顿·伊萨克(Helton Isac),我想出了这段代码希望这对您有用
public static boolean isTablet(Context context) {
TelephonyManager manager =
(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
if (manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) {
//Tablet
return true;
} else {
//Mobile
return false;
}
}
public static boolean isTabletDevice(Context activityContext) {
// Verifies if the Generalized Size of the device is XLARGE to be
// considered a Tablet
boolean xlarge =
((activityContext.getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE);
// If XLarge, checks if the Generalized Density is at least MDPI (160dpi)
if (xlarge) {
DisplayMetrics metrics = new DisplayMetrics();
Activity activity = (Activity) activityContext;
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
// MDPI=160, DEFAULT=160, DENSITY_HIGH=240, DENSITY_MEDIUM=160,
// DENSITY_TV=213, DENSITY_XHIGH=320
if (metrics.densityDpi == DisplayMetrics.DENSITY_DEFAULT
|| metrics.densityDpi == DisplayMetrics.DENSITY_HIGH
|| metrics.densityDpi == DisplayMetrics.DENSITY_MEDIUM
|| metrics.densityDpi == DisplayMetrics.DENSITY_XHIGH) {
// Yes, this is a tablet!
return true;
}
}
// No, this is not a tablet!
return false;
}
所以在你的代码中做一个过滤器
if(isTabletDevice(Utilities.this) && isTablet(Utilities.this)){
//Tablet
} else {
//Phone
}
对于那些想要参考Google的代码来决定哪些设备将使用Tablet UI的人,可以参考以下内容:
// SystemUI (status bar) layout policy
int shortSizeDp = shortSize
* DisplayMetrics.DENSITY_DEFAULT
/ DisplayMetrics.DENSITY_DEVICE;
if (shortSizeDp < 600) {
// 0-599dp: "phone" UI with a separate status & navigation bar
mHasSystemNavBar = false;
mNavigationBarCanMove = true;
} else if (shortSizeDp < 720) {
// 600-719dp: "phone" UI with modifications for larger screens
mHasSystemNavBar = false;
mNavigationBarCanMove = false;
} else {
// 720dp: "tablet" UI with a single combined status & navigation bar
mHasSystemNavBar = true;
mNavigationBarCanMove = false;
}
}
shortSize
多少?
此方法是Google推荐的。我在Google Offical Android App中看到此代码iosched
public static boolean isTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
public static bool isTablet (Context context) { return (context.Resources.Configuration.ScreenLayout & Android.Content.Res.ScreenLayout.SizeMask) >= Android.Content.Res.ScreenLayout.SizeLarge; }
其他答案列出了许多以编程方式确定设备是手机还是平板电脑的方式。但是,如果您阅读该文档,则不建议采用这种方法来支持各种屏幕尺寸。
而是为平板电脑或手机声明不同的资源。你做这个我增加额外的资源文件夹layout
,values
等等。
对于Android 3.2(API级别13),添加一个sw600dp
文件夹。这意味着š mallest 瓦特 IDþ是至少为600dp,这大约是手机/平板鸿沟。但是,您也可以添加其他尺寸。请查看此答案,以获取有关如何添加其他布局资源文件的示例。
如果您还支持Android 3.2之前的设备,则需要添加large
或xlarge
文件夹以支持平板电脑。(电话通常是small
和normal
。)
这是在为不同的屏幕尺寸添加额外的xml文件之后您的资源可能想要的图像。
使用此方法时,系统将为您确定一切。您不必担心在运行时使用哪个设备。您只需提供适当的资源,然后让Android完成所有工作即可。
笔记
如果您仅定位API级别> = 13,请尝试
public static boolean isTablet(Context context) {
return context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
}
欢呼声:-)
考虑“可接受的”新目录(例如,values-sw600dp),我根据屏幕的宽度DP创建了此方法:
public static final int TABLET_MIN_DP_WEIGHT = 450;
protected static boolean isSmartphoneOrTablet(Activity act){
DisplayMetrics metrics = new DisplayMetrics();
act.getWindowManager().getDefaultDisplay().getMetrics(metrics);
int dpi = 0;
if (metrics.widthPixels < metrics.heightPixels){
dpi = (int) (metrics.widthPixels / metrics.density);
}
else{
dpi = (int) (metrics.heightPixels / metrics.density);
}
if (dpi < TABLET_MIN_DP_WEIGHT) return true;
else return false;
}
在此列表中,您可以找到一些流行设备和平板电脑尺寸的DP:
Wdp / Hdp
Nexus:
360/567 XOOM:1280/752
GALAXY NOTE:400/615
NEXUS 7:961/528
GABXY TAB(> 7 && <10):1280/752
GALAXY S3:360/615
Wdp =宽度dp
Hdp =高度dp
好吧,对我有用的最佳解决方案很简单:
private boolean isTabletDevice(Resources resources) {
int screenLayout = resources.getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
boolean isScreenLarge = (screenLayout == Configuration.SCREENLAYOUT_SIZE_LARGE);
boolean isScreenXlarge = (screenLayout == Configuration.SCREENLAYOUT_SIZE_XLARGE);
return (isScreenLarge || isScreenXlarge);
}
像这样使用:
public void onCreate(Bundle savedInstanceState) {
[...]
if (this.isTabletDevice(this.getResources()) == true) {
[...]
}
}
我真的不想看像素大小,而只依赖于屏幕大小。
在将Nexus 7(LARGE)检测为平板电脑时效果很好,但无法检测到Galaxy S3(NORMAL)。
使用此方法,该方法在设备为平板电脑时返回true
public boolean isTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
如果屏幕尺寸检测在较新的设备上未返回正确的值,请尝试:
/*
Returns '1' if device is a tablet
or '0' if device is not a tablet.
Returns '-1' if an error occured.
May require READ_EXTERNAL_STORAGE
permission.
*/
public static int isTablet()
{
try
{
InputStream ism = Runtime.getRuntime().exec("getprop ro.build.characteristics").getInputStream();
byte[] bts = new byte[1024];
ism.read(bts);
ism.close();
boolean isTablet = new String(bts).toLowerCase().contains("tablet");
return isTablet ? 1 : 0;
}
catch (Throwable t)
{t.printStackTrace(); return -1;}
}
在Android 4.2.2上测试(对不起我的英语。)
我知道这不是直接回答您的问题,但是这里的其他答案很好地说明了如何识别屏幕尺寸。您在问题中写道,您在倾斜时遇到了问题,这也发生在我身上。
如果您在智能手机上运行陀螺仪(或旋转传感器),则可以根据该设备的默认方向(例如,三星GS2为默认人像,三星GT-7310为默认风景,虽然它是平板电脑,但新的Google Nexus 7是默认人像!)。
现在,如果您要使用陀螺仪,则可能会得到适用于智能手机的可行解决方案,但某些平板电脑上的轴会混乱,反之亦然。
如果您使用上述解决方案之一,仅选择屏幕尺寸,然后应用
SensorManager.remapCoordinateSystem(inputRotationMatrix, SensorManager.AXIS_X,
SensorManager.AXIS_Y, outputRotationMatrix);
如果轴具有大屏幕或超大屏幕尺寸,则可以翻转轴,这在90%的情况下都可以使用,但是例如在Nexus 7上,会造成麻烦(因为它具有默认的纵向方向和大屏幕尺寸)。
API演示随附的RotationVectorSample提供了解决此问题的最简单方法,方法是nosensor
在清单中将sceenOrientation设置为:
<activity
...
android:screenOrientation="nosensor">
...
</activity>
下面的方法是计算设备屏幕的对角线长度,以确定设备是手机还是平板电脑。此方法唯一需要考虑的是确定设备是否为平板电脑的天气的阈值是多少。在下面的示例中,我将其设置为7英寸以上。
public static boolean isTablet(Activity act)
{
Display display = act.getWindow().getWindowManager().getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
display.getMetrics(displayMetrics);
float width = displayMetrics.widthPixels / displayMetrics.xdpi;
float height = displayMetrics.heightPixels / displayMetrics.ydpi;
double screenDiagonal = Math.sqrt( width * width + height * height );
int inch = (int) (screenDiagonal + 0.5);
Toast.makeText(act, "inch : "+ inch, Toast.LENGTH_LONG).show();
return (inch >= 7 );
}
public boolean isTablet() {
int screenLayout = getResources().getConfiguration().screenLayout;
return (Build.VERSION.SDK_INT >= 11 &&
(((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) ||
((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE)));
}
在手机和平板电脑之间划清界限越来越困难。例如(截至2015年8月)三星Mega 6.3设备从sw600dp文件夹中提取资源-就Android而言,它是一台平板电脑。
来自@Vyshnavi的答案适用于我们测试过的所有设备,但不适用于Mega 6.3。
上面的@Helton Isac答案将Mega 6.3作为手机返回-但由于该设备仍会从sw600dp中获取资源,因此可能导致其他问题-例如,如果将Viewpager用于手机而不是用于平板电脑,则会出现NPE错误。
最后,似乎需要检查的条件太多,我们可能只需要接受某些电话实际上是平板电脑即可:-P
这是我使用的方法:
public static boolean isTablet(Context ctx){
return = (ctx.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
使用:
这是推荐的方法!
为什么使用这个?
Use this method which returns true when the device is a tablet
public boolean isTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
我在上面看到了很多方法。Configuration类在下面得到了正确的答案:
/**
* Check if the Configuration's current {@link #screenLayout} is at
* least the given size.
*
* @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL},
* {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or
* {@link #SCREENLAYOUT_SIZE_XLARGE}.
* @return Returns true if the current screen layout size is at least
* the given size.
*/
public boolean isLayoutSizeAtLeast(int size) {
int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
return cur >= size;
}
只需致电:
getResources().getConfiguration().
isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);
没关系?
我只需要在布局文件中检测智能手机/平板电脑,因为我正在使用导航代码。
我首先要做的是创建一个layout-sw600dp目录,但是它无法正常工作,因为它将在横向模式下在我的Nokia 8上激活,但是屏幕高度太小了。
因此,我将目录重命名为layout-sw600dp-h400dp,然后得到了预期的效果。h-xxxdp参数应取决于要在布局上放置多少内容,因此应取决于应用程序。
请查看下面的代码。
private boolean isTabletDevice() {
if (android.os.Build.VERSION.SDK_INT >= 11) { // honeycomb
// test screen size, use reflection because isLayoutSizeAtLeast is
// only available since 11
Configuration con = getResources().getConfiguration();
try {
Method mIsLayoutSizeAtLeast = con.getClass().getMethod(
"isLayoutSizeAtLeast", int.class);
boolean r = (Boolean) mIsLayoutSizeAtLeast.invoke(con,
0x00000004); // Configuration.SCREENLAYOUT_SIZE_XLARGE
return r;
} catch (Exception x) {
x.printStackTrace();
return false;
}
}
return false;
}
我认为平板电脑的最小和最大宽度和高度为600像素,
因此需要知道屏幕密度和dp中的高度/宽度,
才能获取值:
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
Display display = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
float density = metrics.density;
if((width/density>=600 && height/density>=600))
isTablette = true;
else
isTablette = false;
例如,手机和平板电脑之间有一个重要区别(至少对于我的程序而言)。这是设备的默认方向。手机具有纵向方向,平板电脑-横向。并分别确定设备的方法:
private static boolean isLandscapeDefault(Display display) {
Log.d(TAG, "isTablet()");
final int width = display.getWidth();
final int height = display.getHeight();
switch (display.getOrientation()) {
case 0: case 2:
if(width > height) return true;
break;
case 1: case 3:
if(width < height) return true;
break;
}
return false;
}
编辑:在与Dan Hulme的讨论之后,更改了该方法的名称。
我推荐android库'caffeine',其中包含get Phone或tablet,以及10inch〜!
非常容易使用。
图书馆在这里。
https://github.com/ShakeJ/Android-Caffeine-library
和使用
DisplayUtil.isTablet(this);
DisplayUtil.isTenInch(this);
对我来说,手机和平板电脑之间的区别不是设备的大小和/或像素密度,它会随着技术和品味的变化而变化,而是屏幕比例。如果要显示文本屏幕,则需要知道是否需要15条长行(电话)和20条短行(平板电脑)。对于我的游戏,我使用以下代码估算软件将要处理的矩形:
Rect surfaceRect = getHolder().getSurfaceFrame();
screenWidth = surfaceRect.width();
screenHeight = surfaceRect.height();
screenWidthF = (float) screenWidth;
screenHeightF = (float) screenHeight;
widthheightratio = screenWidthF/screenHeightF;
if(widthheightratio>=1.5) {
isTablet=false;
}else {
isTablet=true;
}