Mahi
Mahi

Reputation: 6292

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

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

Answers (12)

Praxder
Praxder

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

MBH
MBH

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

Deepak Yadav
Deepak Yadav

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

Ankur Yadav
Ankur Yadav

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

persec10000
persec10000

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

Roc Boronat
Roc Boronat

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

Kirill Karmazin
Kirill Karmazin

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

Chandler
Chandler

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

Sergi and Replace
Sergi and Replace

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

user2233706
user2233706

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

bakua
bakua

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

b4rtaz
b4rtaz

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

Related Questions