Reputation: 6292
I am actually trying to figure out if the app is running on a smartphone or tablet in my Flutter app, but the package device_info
can only tell about the device, but not whether the device is a smartphone or tablet.
Is there a way we can do this by checking the size of the device?
Upvotes: 75
Views: 68806
Reputation: 2759
2023, a Dart 3 solution inspired from bakua's answer, and also this answer:
bool get isTablet {
final firstView = WidgetsBinding.instance.platformDispatcher.views.first;
final logicalShortestSide = firstView.physicalSize.shortestSide / firstView.devicePixelRatio;
return logicalShortestSide > 600;
}
Upvotes: 11
Reputation: 16619
I wrote this context extension depending on the other answers. It works for me:
extension ContextExt on BuildContext {
bool get isPhone => MediaQuery.of(this).size.width < 600.0;
bool get isTablet => MediaQuery.of(this).size.width >= 600.0;
}
Usage:
final iconSize = context.isTablet ? 50.0 : 30.0;
Upvotes: 0
Reputation: 255
Create a Dart file, size_config.dart
import 'dart:io';
import 'package:flutter/widgets.dart';
import 'dart:async';
import 'package:device_info_plus/device_info_plus.dart';
class SizeConfig {
static late MediaQueryData _mediaQueryData;
static late double screenWidth;
static late double screenHeight;
static late double blockSizeHorizontal;
static late double blockSizeVertical;
static late double safeBlockHorizontal;
static late double safeBlockVertical;
static bool isIpad = false;
void init(BuildContext context) async {
_mediaQueryData = MediaQuery.of(context);
screenWidth = _mediaQueryData.size.width;
screenHeight = _mediaQueryData.size.height;
blockSizeHorizontal = screenWidth / 100;
blockSizeVertical = screenHeight / 100;
isIpad = await isTablet(context);
}
static Future<bool> isTablet(BuildContext context) async {
bool isTab = false;
if (Platform.isIOS) {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
if (iosInfo.model.toLowerCase() == "ipad") {
isTab = true;
} else {
isTab = false;
}
return isTab;
} else {
var shortestSide = MediaQuery.of(context).size.shortestSide;
if (shortestSide > 600) {
isTab = true;
} else {
isTab = false;
}
return isTab;
}
}
}
Calling
@override
Widget build(BuildContext context) {
SizeConfig().init(context);
var height = SizeConfig.screenHeight;
var width = SizeConfig.screenWidth;
bool isIpad = SizeConfig.isIpad;
Upvotes: -1
Reputation: 271
You can use the device_info_plus package from Flutter:
static Future<bool> isTablet(BuildContext context) async {
bool isTab = false;
if (Platform.isIOS) {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
if(iosInfo.model?.toLowerCase() == "ipad") {
isTab = true;
} else {
isTab = false;
}
return isTab;
} else {
var shortestSide = MediaQuery.of(context).size.shortestSide;
if(shortestSide > 600) {
isTab = true;
} else {
isTab = false;
}
return isTab;
}
}
Calling..
Future checkDeviceType() async {
bool iPad = await isTablet(context);
if(iPad) {
// Write your logic here..
}
}
Upvotes: 0
Reputation: 1065
Usually, the aspect ratio (width : height) of an Android tablet and iPad is in the range of from 0.75 to 1.4, and following is the fastest way to check. We can adjust the UI according to the aspect ratio.
bool isTablet;
double ratio = MediaQuery.of(context).size.width / MediaQuery.of(context).size.height;
if((ratio >= 0.74) && (ratio < 1.5))
{
isTablet = true;
} else {
isTablet = false;
}
Upvotes: 1
Reputation: 12151
Here's the same as in other answers, but returning an enum
instead of a bool
or a String
. As it's more closed, it's easier to use it.
import 'package:flutter/widgets.dart';
enum DeviceType { Phone, Tablet }
DeviceType getDeviceType() {
final data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
return data.size.shortestSide < 550 ? DeviceType.Phone : DeviceType.Tablet;
}
Thanks to Chandler and bakua for the inspiration :·)
Upvotes: 16
Reputation: 6736
For Android, as Chandler said, you should check the smallest size of the screen, but for iOS, you can identify if it's an iPad with 100% accuracy using the device_info package:
Add in pubspec.yaml
:
device_info: ^0.4.2+4
static Future<bool> isTablet(BuildContext context) async {
if (Platform.isIOS) {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
return iosInfo.model.toLowerCase() == "ipad";
} else {
// The equivalent of the "smallestWidth" qualifier on Android.
var shortestSide = MediaQuery.of(context).size.shortestSide;
// Determine if we should use mobile layout or not, 600 here is
// a common breakpoint for a typical 7-inch tablet.
return shortestSide > 600;
}
}
Upvotes: 9
Reputation: 3297
Use:
// The equivalent of the "smallestWidth" qualifier on Android.
var shortestSide = MediaQuery.of(context).size.shortestSide;
// Determine if we should use mobile layout or not, 600 here is
// a common breakpoint for a typical 7-inch tablet.
final bool useMobileLayout = shortestSide < 600;
Copied from Implementing master-detail layouts in Flutter
Thanks to Sergi.
Upvotes: 59
Reputation: 829
Despite iOS having a clear separation between a phone and a tablet, this doesn't happen in Android. You need to base the choice based on screen width.
Check this article to see an example on how to discriminate: Implementing master-detail layouts in Flutter
Upvotes: 15
Reputation: 7207
You can use DeviceType.tablet
from the sizer package. You would do:
SizerUtil.deviceType == DeviceType.tablet
The field is set using this logic, which is the same as the most accepted answer here. I already use sizer to make my app responsive, so using it to determine whether the device is a tablet is convenient.
Upvotes: 1
Reputation: 14454
You can use this if you don't have an access to BuildContext. I took it out from sdk/flutter/packages/flutter/lib/src/widgets/app.dart:1252
.
String getDeviceType() {
final data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
return data.size.shortestSide < 600 ? 'phone' :'tablet';
}
Upvotes: 56
Reputation: 251
One of the ways is calculated diagonal for screen resolution.
import 'package:flutter/widgets.dart';
import 'dart:math';
class TabletDetector {
// iPhone 6S
// |_ [portrait]
// |_ size: 375.0x667.0, pixelRatio: 2.0, pixels: 750.0x1334.0
// |_ diagonal: 765.1888655750291
// |_ [horizontal]
// |_ size: 667.0x375.0, pixelRatio: 2.0, pixels: 1334.0x750.0
// |_ diagonal: 765.1888655750291
// iPhone X
// |_ [portrait]
// |_ size: 375.0x812.0, pixelRatio: 3.0, pixels: 1125.0x2436.0
// |_ diagonal: 894.4098613052072
// |_ [horizontal]
// |_ size: 812.0x375.0, pixelRatio: 3.0, pixels: 2436.0x1125.0
// |_ diagonal: 894.4098613052072
// iPhone XS Max
// |_ [portrait]
// |_ size: 414.0x896.0, pixelRatio: 3.0, pixels: 1242.0x2688.0
// |_ diagonal: 987.0217829409845
// |_ [horizontal]
// |_ size: 896.0x414.0, pixelRatio: 3.0, pixels: 2688.0x1242.0
// |_ diagonal: 987.0217829409845
// iPad Pro (9.7-inch)
// |_ [portrait]
// |_ size: 768.0x1024.0, pixelRatio: 2.0, pixels: 1536.0x2048.0
// |_ diagonal: 1280.0
// |_ [horizontal]
// |_ size: 1024.0x768.0, pixelRatio: 2.0, pixels: 2048.0x1536.0
// |_ diagonal: 1280.0
// iPad Pro (10.5-inch)
// |_ [portrait]
// |_ size: 834.0x1112.0, pixelRatio: 2.0, pixels: 1668.0x2224.0
// |_ diagonal: 1390.0
// |_ [horizontal]
// |_ size: 1112.0x834.0, pixelRatio: 2.0, pixels: 2224.0x1668.0
// |_ diagonal: 1390.0
// iPad Pro (12.9-inch)
// |_ [portrait]
// |_ size: 1024.0x1366.0, pixelRatio: 2.0, pixels: 2048.0x2732.0
// |_ diagonal: 1707.2000468603555
// |_ [horizontal]
// |_ size: 1366.0x1024.0, pixelRatio: 2.0, pixels: 2732.0x2048.0
// |_ diagonal: 1707.2000468603555
static bool isTablet(MediaQueryData query) {
var size = query.size;
var diagonal = sqrt(
(size.width * size.width) +
(size.height * size.height)
);
/*
print(
'size: ${size.width}x${size.height}\n'
'pixelRatio: ${query.devicePixelRatio}\n'
'pixels: ${size.width * query.devicePixelRatio}x${size.height * query.devicePixelRatio}\n'
'diagonal: $diagonal'
);
*/
var isTablet = diagonal > 1100.0;
return isTablet;
}
}
Upvotes: 20