Can we check the device to be smartphone or tablet in Flutter?

58.4k Views Asked by At

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?

Many thanks Mahi

12

There are 12 best solutions below

1
Sergi and Replace On BEST ANSWER

Despite iOS has a clear separation between phone and 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: https://flutter.rocks/2018/01/28/implementing-adaptive-master-detail-layouts/

2
b4rtaz On

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;
  }
}
3
Chandler On
// 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 https://flutter.rocks/2018/01/28/implementing-adaptive-master-detail-layouts/

Thanks @Sergi

2
bakua On

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';
  }
1
Kirill Karmazin On

For Android as @Chandler said you should check the smallest size of the screen, but for iOS, you can identify if it's iPad with 100% accuracy using 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;
    }
  }
3
Roc Boronat On

Here's the same than in other aswers, 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 :·)

0
persec10000 On

Usually the Aspect ratio ( width : height) of Android Tablet and iPad is in the range of from 0.75 ~ 1.4, 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;
}
2
user2233706 On

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.

0
Ankur Yadav On

You can use device_info_plus package from flutter https://pub.dev/packages/device_info_plus

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..
     }
}
0
Deepak Yadav On

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;
0
MBH On

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;
0
Praxder On

2023, 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;
}