├── .github └── workflows │ └── dart.yml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── flutter_device_type.iml ├── lib └── flutter_device_type.dart ├── pubspec.lock ├── pubspec.yaml ├── res └── values │ └── strings_en.arb └── test └── flutter_device_type_test.dart /.github/workflows/dart.yml: -------------------------------------------------------------------------------- 1 | name: Publish package to pub.dev 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | container: 10 | image: google/dart:latest 11 | steps: 12 | - uses: actions/checkout@v1 13 | - name: Setup credentials 14 | run: | 15 | mkdir -p ~/.pub-cache 16 | cat < ~/.pub-cache/credentials.json 17 | { 18 | "accessToken":"${{ secrets.OAUTH_ACCESS_TOKEN }}", 19 | "refreshToken":"${{ secrets.OAUTH_REFRESH_TOKEN }}", 20 | "tokenEndpoint":"https://accounts.google.com/o/oauth2/token", 21 | "scopes": [ "openid", "https://www.googleapis.com/auth/userinfo.email" ], 22 | "expiration": 1615436537375 23 | } 24 | EOF 25 | - name: Publish package 26 | run: pub publish -f -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | ios/.generated/ 9 | ios/Flutter/Generated.xcconfig 10 | ios/Runner/GeneratedPluginRegistrant.* 11 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.4.0] - 03-09-2020 2 | * Switched to null safety 3 | 4 | ## [0.3.2] - 10-11-2020 5 | * Added some more checks for IPhoneX for those still using it. This allows detecting from iPhoneX onwards 6 | 7 | ## [0.3.1] - 10-11-2020 8 | * Fix more issues relating to low res Android devices. 9 | 10 | ## [0.3.0] - 04-11-2020 11 | * Fix issues relating to low res Android devices. 12 | * Added hasNotch property 13 | 14 | ## [0.1.0] - 24-12-2018 15 | 16 | * Determine if device is a Table or Phone, if device is iOS or Android and if device if iPhoneX as well as get device's physical and screen dimensions 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Matthew Whitaker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flutter_device_type 2 | 3 | Determine the type of handheld device on Flutter. Like if the device is a Tablet or is iPhoneX or later or has notch. 4 | 5 | ## Usage 6 | 7 | ```dart 8 | //Get the physical device size 9 | print( Device.size ); 10 | //Quick methods to access the physical device width and height 11 | print("Device Width: ${Device.width}, Device Height: ${Device.height}"); 12 | 13 | //To get the actual screen size (Which is same as what MediaQuery gives) 14 | print( Device.screenSize ); 15 | //Quick methods to access the screen width and height 16 | print("Device Width: ${Device.screenWidth}, Device Height: ${Device.screenHeight}"); 17 | 18 | //Check if device is tablet 19 | if( Device.get().isTablet ){ 20 | //do something large 21 | } 22 | 23 | //Check if device is at least an iphone x 24 | // NOTE: This detects up to Iphone 12 pro max 25 | if( Device.get().isIphoneX ){ 26 | //Do some notch business 27 | } 28 | 29 | // For a generic notch test use 30 | if( Device.get().hasNotch ){ 31 | //Do some notch business 32 | } 33 | 34 | //Other utility methods 35 | print( Device.get().isPhone ); 36 | print( Device.get().isAndroid ); 37 | print( Device.get().isIos ); 38 | 39 | //So to check for iPad for instance 40 | if( Device.get().isIos && Device.get().isTablet ){ 41 | //make the font larger :) 42 | } 43 | ``` 44 | 45 | `Device.get()` will return only one instance so not need to save it except for brevity 46 | 47 | You should try not to store a reference for `Device.get()` because it now responds to changes and orientations 48 | -------------------------------------------------------------------------------- /flutter_device_type.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lib/flutter_device_type.dart: -------------------------------------------------------------------------------- 1 | library flutter_device_type; 2 | 3 | import 'dart:io'; 4 | import 'dart:ui' as ui; 5 | import 'dart:math' as Math; 6 | 7 | class Device { 8 | static double devicePixelRatio = ui.window.devicePixelRatio; 9 | static ui.Size size = ui.window.physicalSize; 10 | static double width = size.width; 11 | static double height = size.height; 12 | static double screenWidth = width / devicePixelRatio; 13 | static double screenHeight = height / devicePixelRatio; 14 | static ui.Size screenSize = new ui.Size(screenWidth, screenHeight); 15 | final bool isTablet, isPhone, isIos, isAndroid, isIphoneX, hasNotch; 16 | static Device? _device; 17 | static Function? onMetricsChange; 18 | 19 | Device( 20 | {required this.isTablet, 21 | required this.isPhone, 22 | required this.isIos, 23 | required this.isAndroid, 24 | required this.isIphoneX, 25 | required this.hasNotch}); 26 | 27 | factory Device.get() { 28 | if (_device != null) return _device!; 29 | 30 | if (onMetricsChange == null) { 31 | onMetricsChange = ui.window.onMetricsChanged; 32 | ui.window.onMetricsChanged = () { 33 | _device = null; 34 | 35 | size = ui.window.physicalSize; 36 | width = size.width; 37 | height = size.height; 38 | screenWidth = width / devicePixelRatio; 39 | screenHeight = height / devicePixelRatio; 40 | screenSize = new ui.Size(screenWidth, screenHeight); 41 | 42 | onMetricsChange!(); 43 | }; 44 | } 45 | 46 | bool isTablet; 47 | bool isPhone; 48 | bool isIos = Platform.isIOS; 49 | bool isAndroid = Platform.isAndroid; 50 | bool isIphoneX = false; 51 | bool hasNotch = false; 52 | 53 | if (devicePixelRatio < 2 && (width >= 1000 || height >= 1000)) { 54 | isTablet = true; 55 | isPhone = false; 56 | } else if (devicePixelRatio == 2 && (width >= 1920 || height >= 1920)) { 57 | isTablet = true; 58 | isPhone = false; 59 | } else { 60 | isTablet = false; 61 | isPhone = true; 62 | } 63 | 64 | // Recalculate for Android Tablet using device inches 65 | if (isAndroid) { 66 | final adjustedWidth = _calWidth() / devicePixelRatio; 67 | final adjustedHeight = _calHeight() / devicePixelRatio; 68 | final diagonalSizeInches = (Math.sqrt( 69 | Math.pow(adjustedWidth, 2) + Math.pow(adjustedHeight, 2))) / 70 | _ppi; 71 | //print("Dialog size inches is $diagonalSizeInches"); 72 | if (diagonalSizeInches >= 7) { 73 | isTablet = true; 74 | isPhone = false; 75 | } else { 76 | isTablet = false; 77 | isPhone = true; 78 | } 79 | } 80 | 81 | if (isIos && 82 | isPhone && 83 | (screenHeight == 812 || 84 | screenWidth == 812 || 85 | screenHeight == 896 || 86 | screenWidth == 896 || 87 | // iPhone 12 pro 88 | screenHeight == 844 || 89 | screenWidth == 844 || 90 | // Iphone 12 pro max 91 | screenHeight == 926 || 92 | screenWidth == 926)) { 93 | isIphoneX = true; 94 | hasNotch = true; 95 | } 96 | 97 | if (_hasTopOrBottomPadding()) hasNotch = true; 98 | 99 | return _device = new Device( 100 | isTablet: isTablet, 101 | isPhone: isPhone, 102 | isAndroid: isAndroid, 103 | isIos: isIos, 104 | isIphoneX: isIphoneX, 105 | hasNotch: hasNotch); 106 | } 107 | 108 | static double _calWidth() { 109 | if (width > height) 110 | return (width + 111 | (ui.window.viewPadding.left + ui.window.viewPadding.right) * 112 | width / 113 | height); 114 | return (width + ui.window.viewPadding.left + ui.window.viewPadding.right); 115 | } 116 | 117 | static double _calHeight() { 118 | return (height + 119 | (ui.window.viewPadding.top + ui.window.viewPadding.bottom)); 120 | } 121 | 122 | static int get _ppi => Platform.isAndroid 123 | ? 160 124 | : Platform.isIOS 125 | ? 150 126 | : 96; 127 | 128 | static bool _hasTopOrBottomPadding() { 129 | final padding = ui.window.viewPadding; 130 | //print(padding); 131 | return padding.top > 0 || padding.bottom > 0; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.5.0" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.2.0" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | fake_async: 47 | dependency: transitive 48 | description: 49 | name: fake_async 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.2.0" 53 | flutter: 54 | dependency: "direct main" 55 | description: flutter 56 | source: sdk 57 | version: "0.0.0" 58 | flutter_test: 59 | dependency: "direct dev" 60 | description: flutter 61 | source: sdk 62 | version: "0.0.0" 63 | matcher: 64 | dependency: transitive 65 | description: 66 | name: matcher 67 | url: "https://pub.dartlang.org" 68 | source: hosted 69 | version: "0.12.10" 70 | meta: 71 | dependency: transitive 72 | description: 73 | name: meta 74 | url: "https://pub.dartlang.org" 75 | source: hosted 76 | version: "1.3.0" 77 | path: 78 | dependency: transitive 79 | description: 80 | name: path 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "1.8.0" 84 | sky_engine: 85 | dependency: transitive 86 | description: flutter 87 | source: sdk 88 | version: "0.0.99" 89 | source_span: 90 | dependency: transitive 91 | description: 92 | name: source_span 93 | url: "https://pub.dartlang.org" 94 | source: hosted 95 | version: "1.8.0" 96 | stack_trace: 97 | dependency: transitive 98 | description: 99 | name: stack_trace 100 | url: "https://pub.dartlang.org" 101 | source: hosted 102 | version: "1.10.0" 103 | stream_channel: 104 | dependency: transitive 105 | description: 106 | name: stream_channel 107 | url: "https://pub.dartlang.org" 108 | source: hosted 109 | version: "2.1.0" 110 | string_scanner: 111 | dependency: transitive 112 | description: 113 | name: string_scanner 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "1.1.0" 117 | term_glyph: 118 | dependency: transitive 119 | description: 120 | name: term_glyph 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "1.2.0" 124 | test_api: 125 | dependency: transitive 126 | description: 127 | name: test_api 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "0.2.19" 131 | typed_data: 132 | dependency: transitive 133 | description: 134 | name: typed_data 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.3.0" 138 | vector_math: 139 | dependency: transitive 140 | description: 141 | name: vector_math 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "2.1.0" 145 | sdks: 146 | dart: ">=2.12.0 <3.0.0" 147 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_device_type 2 | description: Determine the type of handheld device on Flutter. Like if the device is a Tablet or is iPhoneX. 3 | version: 0.4.0 4 | homepage: https://github.com/ominibyte/flutter_device_type.git 5 | 6 | environment: 7 | sdk: '>=2.12.0 <3.0.0' 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | dev_dependencies: 14 | flutter_test: 15 | sdk: flutter 16 | 17 | # For information on the generic Dart part of this file, see the 18 | # following page: https://www.dartlang.org/tools/pub/pubspec 19 | 20 | # The following section is specific to Flutter. 21 | flutter: 22 | 23 | # To add assets to your package, add an assets section, like this: 24 | # assets: 25 | # - images/a_dot_burr.jpeg 26 | # - images/a_dot_ham.jpeg 27 | # 28 | # For details regarding assets in packages, see 29 | # https://flutter.io/assets-and-images/#from-packages 30 | # 31 | # An image asset can refer to one or more resolution-specific "variants", see 32 | # https://flutter.io/assets-and-images/#resolution-aware. 33 | 34 | # To add custom fonts to your package, add a fonts section here, 35 | # in this "flutter" section. Each entry in this list should have a 36 | # "family" key with the font family name, and a "fonts" key with a 37 | # list giving the asset and other descriptors for the font. For 38 | # example: 39 | # fonts: 40 | # - family: Schyler 41 | # fonts: 42 | # - asset: fonts/Schyler-Regular.ttf 43 | # - asset: fonts/Schyler-Italic.ttf 44 | # style: italic 45 | # - family: Trajan Pro 46 | # fonts: 47 | # - asset: fonts/TrajanPro.ttf 48 | # - asset: fonts/TrajanPro_Bold.ttf 49 | # weight: 700 50 | # 51 | # For details regarding fonts in packages, see 52 | # https://flutter.io/custom-fonts/#from-packages 53 | -------------------------------------------------------------------------------- /res/values/strings_en.arb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ominibyte/flutter_device_type/e82d78f5db9cfc27ff41c2ce580b5e43e007223c/res/values/strings_en.arb -------------------------------------------------------------------------------- /test/flutter_device_type_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_device_type/flutter_device_type.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | 4 | void main() { 5 | test('Test that size is not null', () { 6 | expect(Device.size, isNotNull); 7 | expect(Device.get().isIphoneX, isNotNull); 8 | expect(Device.get().hasNotch, isNotNull); 9 | }); 10 | } 11 | --------------------------------------------------------------------------------