Чи є спосіб перевірити, чи користувач користується планшетом чи телефоном? У мене проблеми з функцією нахилу та новим планшетом (трансформер)
Чи є спосіб перевірити, чи користувач користується планшетом чи телефоном? У мене проблеми з функцією нахилу та новим планшетом (трансформер)
Відповіді:
Як уже згадувалося раніше, ви не хочете перевіряти, чи пристрій є планшетом чи телефоном, але хочете дізнатися про функції пристрою,
Здебільшого різниця між планшетом і телефоном - це розмір екрана, тому ви хочете використовувати різні файли компонування. Ці файли зберігаються в res/layout-<qualifiers>
каталогах. Ви можете створити XML-файл у дирекціїres/values-<same qualifiers>
для кожної з своїх макетів і помістити в нього ресурс 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);
}
Великі та розміри екрана XLARGE визначаються виробником залежно від відстані від очей, на якому вони повинні використовуватись (таким чином, ідея планшета).
Детальніше: http://groups.google.com/group/android-developers/browse_thread/thread/d6323d81f226f93f
Configuration.SCREENLAYOUT_SIZE_XLARGE
, тож вам не потрібно використовувати константу, а можете використовувати >= LARGE
.
Ця публікація мені дуже допомогла,
На жаль, у мене немає репутації, необхідної для оцінки всіх відповідей, які мені допомогли.
Мені потрібно було визначити, чи мій пристрій планшетний ПК чи телефон, завдяки чому я зможу реалізувати логіку екрана. І в моєму аналізі планшет повинен бути більше 7 дюймів (Xlarge), починаючи з MDPI.
Ось код нижче, який був створений на основі цієї публікації.
/**
* 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/ . Я її не перевіряв)
Моє припущення, що коли ви визначаєте "Мобільний телефон / телефон", ви хочете знати, чи можна телефонувати на пристрої, що не можна зробити на тому, що було б визначено як "Планшет". Нижче наведено спосіб підтвердити це. Якщо ви хочете знати щось на основі датчиків, розміру екрана тощо, це справді інше питання.
Крім того, під час використання роздільної здатності екрана або управління ресурсами великим по відношенню до xlarge, можливо, у минулому нові пристрої "Мобільні" використовували такі великі екрани та високу роздільну здатність, що вони розмивають цю лінію, хоча якщо ви дійсно бажаєте знати телефонний дзвінок проти відсутності можливості телефонного дзвінка, наведене нижче - "найкраще".
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
if(manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE){
return "Tablet";
}else{
return "Mobile";
}
На основі Роберта Дейла Джонсона III та Гелтона Ісака я придумав цей код. Сподіваюся, що це корисно
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 IOSched 2017 використовується наступний метод:
public static boolean isTablet(Context context) {
return context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
}
Тим, хто хоче посилатися на код Google щодо вирішення, які пристрої використовуватимуть інтерфейс планшетного ПК, можна посилатися нижче:
// 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 Appiosched
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
папку. Це означає, що найменший ш ідт становить щонайменше 600dp, що приблизно поділяє телефон / планшет. Однак ви також можете додати інші розміри. Перегляньте цю відповідь на прикладі того, як додати додатковий файл ресурсу макета.
Якщо ви також підтримуєте пристрої попередньої версії Android 3.2, вам потрібно буде додати large
або xlarge
папки для підтримки планшетів. (Телефони взагалі small
і normal
.)
Ось зображення того, що можуть сподобатися вашим ресурсам після додавання додаткових файлів xml для різних розмірів екрана.
Використовуючи цей метод, система визначає все для вас. Вам не потрібно турбуватися про те, який пристрій використовується під час виконання. Ви просто надаєте відповідні ресурси та дозволяєте Android виконувати всю роботу.
Примітки
Якщо ви орієнтуєтесь лише на рівень API-інтерфейсу> = 13, спробуйте
public static boolean isTablet(Context context) {
return context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
}
ура :-)
Розмірковуючи про "нові" прийняті каталоги (наприклад, значення-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;
}
І в цьому списку ви можете знайти деякі з популярних пристроїв та розмірів планшетів:
Wdp / Hdp
GALAXY Nexus: 360/567
XOOM:
1280/752 ПРИМІТКА GALAXY: 400/615
NEXUS 7: 961/528
GABAXY 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 (ВЕЛИКІ) виявлено як планшет, але не Galaxy S3 (NORMAL).
Використовуйте цей метод, який повертає істину, коли пристрій є планшетом
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 (вибачте за мою англійську.)
Я знаю, що це не безпосередньо відповідь на ваше запитання, але інші відповіді дають хороше уявлення про те, як визначити розмір екрана. Ви в своєму запитанні написали, що у вас проблеми з нахилом, і це так само трапилося і зі мною.
Якщо ви запускаєте гіроскоп (або датчик обертання) на смартфоні, вісь x- і y можна визначити інакше, ніж на планшеті, відповідно до орієнтації цього пристрою за замовчуванням (наприклад, Samsung GS2 - портрет за замовчуванням, Samsung GT-7310 - це стандартний пейзаж, новий Google Nexus 7 - портрет за замовчуванням, хоча це планшет!).
Тепер, якщо ви хочете скористатися Gyroscope, ви можете створити робоче рішення для смартфонів, але змішання осей на деяких планшетах або навпаки.
Якщо ви використовуєте одне з рішень зверху, переходьте лише до розміру екрана, а потім застосуйте
SensorManager.remapCoordinateSystem(inputRotationMatrix, SensorManager.AXIS_X,
SensorManager.AXIS_Y, outputRotationMatrix);
щоб перевернути вісь, якщо вона має великий або великий розмір екрана, це може працювати в 90% випадків, але, наприклад, на Nexus 7 це спричинить неполадки (тому що має портретну орієнтацію за замовчуванням та великий розмір екрана).
Найпростіший спосіб виправити це передбачено у RotationVectorSample, який постачається з демонстраційними програмами API, встановивши sceniOrientation nosensor
у своєму маніфесті:
<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 року) Samsung Mega 6.3 витягує ресурси з папок sw600dp - настільки, що стосується Android, це планшет.
Відповідь від @Vyshnavi працює на всіх пристроях, які ми перевірили, але не для Mega 6.3.
@Helton Isac відповідь вище повертає Mega 6.3 як телефон, але оскільки пристрій все ще захоплює ресурси з sw600dp, це може спричинити й інші проблеми - наприклад, якщо ви використовуєте оглядач для телефонів, а не для планшетів, ви отримаєте помилки NPE .
Врешті-решт просто здається, що існує занадто багато умов, на які потрібно перевірити, і ми, можливо, просто мусимо прийняти, що деякі телефони насправді є планшетами :-P
Це метод, який я використовую:
public static boolean isTablet(Context ctx){
return = (ctx.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
Використання:
Конфігурація. SCREENLAYOUT_SIZE_MASK
Конфігурація. 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;
}
Я бачу багато способів вище. Клас конфігурації отримав правильну відповідь трохи нижче:
/**
* 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);
нічого страшного?
Мені потрібно було виявити смартфон / планшет лише у файлі макета, оскільки я використовую код навігації.
Спочатку я створив каталог-макет-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;
}
РЕДАКТИРОВАНО: Після обговорень з Даном Халме змінив назву методу.
Я рекомендую андроїд-бібліотеку "кофеїну", який містить телефон або планшет, і 10 дюймів ~!
дуже просте використання.
бібліотека тут.
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;
}