How to detect orientation change in layout in Flutter?
Asked Answered
T

9

78

How to find out Orientation is portrait or landscape in Flutter

if(portrait){
  return ListView.builder()
}else{
  return GridView.count()
}
Trimmer answered 12/6, 2018 at 10:31 Comment(0)
R
119

In order to determine the Orientation of the screen, we can use the OrientationBuilder Widget. The OrientationBuilder will determine the current Orientation and rebuild when the Orientation changes.

new OrientationBuilder(
  builder: (context, orientation) {
    return new GridView.count(
      // Create a grid with 2 columns in portrait mode, or 3 columns in
      // landscape mode.
      crossAxisCount: orientation == Orientation.portrait ? 2 : 3,
    );
  },
);

you can find the complete example here: https://flutter.io/cookbook/design/orientation/

Radiometeorograph answered 12/6, 2018 at 10:48 Comment(4)
I've used this on Android and it works fine when device's auto-rotate is enabled, but most people uses their phone with auto-rotate disabled (forced to portrait) and OrientationBuilder doesn't trigger the landscape. Is there anyway we can detect the orientation regarding of the auto-rotate state?Euxenite
What do you think about github.com/flutter/flutter/issues/19259 ?Parton
Downside to this option is you can differentiate orientations such as landscapeLeft and landscapeRight.Durwood
This was not working for me. When I changed my iOS Simulator to landscape this did not update the orientation. Using MediaQuery.of(context).orientation did work.Molybdous
A
117

You can use MediaQuery to check orientation:

var isPortrait = MediaQuery.of(context).orientation == Orientation.portrait
Auditor answered 12/6, 2018 at 10:32 Comment(2)
@AdarshVijayanP you can't use that at random code locations. It should be used in build or didChangeDependenciesParton
@GünterZöchbauer wrote code in build and then passed to my widget, Thank you, now it works great.Trimmer
L
23

it's quite easy

if (MediaQuery.of(context).orientation == Orientation.portrait){
    // is portrait
}else{
// is landscape
}
Loireatlantique answered 12/6, 2018 at 10:58 Comment(0)
P
6
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: OrientationBuilder(builder: (_, orientation) {
      if (orientation == Orientation.portrait)
        return _buildPortraitLayout(); // if orientation is portrait, show your portrait layout
      else
        return _buildLandscapeLayout(); // else show the landscape one
    }),
  );
}
Pentateuch answered 28/2, 2020 at 16:20 Comment(2)
OrientationBuilder only seems to work at the scaffold-level build. It doesn't seem to work further down the tree when I'm building a stateful widget. I wonder if this is a known thing.Harlem
OrientationBuilder only tells if the space for children is wider or narrower than its height, but is unrelated to the device orientationParton
B
3

For completeness sake, I would like to add another way to detect orientation in Flutter. Two ways to detect have been mentioned in the answers already. They are

  1. Media Query
  2. Orientation Builder

There is a third way which I came across when learning Flutter from Responsive Design video (skip to minute 2:34) by Google Engineers. It's called Layout Builder. Here is short snippet:

return Padding(
    padding: _padding,
    child: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
            if(constraints.maxHeight > constraints.maxWidth) {
                return _getPortraitLayout();
            }
            else {
                return _getLandscapeLayout();
            }
        },
    ),
);
Biddie answered 12/4, 2020 at 8:3 Comment(1)
this only works if you're using Layout Builder in an unconstrained layout (eg in the top of the screen widget tree). If you put LayoutBuilder inside a Container with height=50 and width=100, your method will always tell the user that he's in the landscape modeOrthotropous
M
2
OrientationBuilder(


 builder: (context, orientation) {
      return orientation == Orientation.portrait
          ? SafeArea(
          child: Scaffold(
              body: PortraitMode(context)
          )
      )
          : LandscapeMode(context);

    }
);
Moyers answered 4/3, 2020 at 12:35 Comment(0)
F
2

My variant.

1) In global scope set global ValueNotifier:

final ValueNotifier<bool> IS_PORTRAIT = ValueNotifier<bool>(true);

2) In a scaffold scope change value of our global ValueNotifier

return Scaffold(
        key: scaffoldKey,
        body: OrientationBuilder(
          builder: (BuildContext context, Orientation orientation) {
            IS_PORTRAIT.value = orientation == Orientation.portrait;
            return MyBody();
          },
        ),
);

3) Any where listen current orientation

return ValueListenableBuilder(
                  valueListenable: IS_PORTRAIT,
                  builder: (BuildContext context, value, Widget child) {
                     return Container(
                      color: Colors.green[100],
                      child: Container(),
                      height: (IS_PORTRAIT.value)? 150: 80,
                    );
                  },
                );
Finnougrian answered 28/1, 2021 at 11:47 Comment(0)
B
1

Mediaquery cannot be used in initState() and OrientationBuilder needs a widget, So I have created the following class which can be used anywhere in the project.

if(IsPortrait.isPortrait){
}else{
}

IsPortrait.class

class IsPortrait{
  static bool isPortrait = true;

  void init(BoxConstraints constraints, Orientation orientation) {
    if (orientation == Orientation.portrait) {
      isPortrait = true;
    }
   else{
     isPortrait = false;
   }
  }
}

following functions can be used to change the orientation

Portrait Mode Only

/// blocks rotation; sets orientation to: portrait
void _portraitModeOnly() {
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
}

Landscape mode only

/// blocks rotation; sets orientation to: landscape
    void _landscapeModeOnly() {
      SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.landscapeRight,
      ]);
    }

Enable Portrait and LandScape

void _enableRotation() {
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.landscapeRight,
  ]);
}
Bevash answered 23/12, 2020 at 8:17 Comment(0)
I
1

Just save and compare the value of current orientation. Something on the lines of :-

class CheckOrientationSampleState extends State<CheckOrientationSample> {
  
  bool? isCurrentPortrait;
  //Non-Mandatory in case of single use
  bool orientationChange = true;

  bool checkOrientationChange(BuildContext context) {
    bool ret = false;
    bool isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;;

    if (isCurrentPortrait == null) {
      isCurrentPortrait = MediaQuery.of(context).orientation == Orientation.portrait;;
      ret = true;
    } else if (isCurrentPortrait != isPortrait) {
      isCurrentPortrait = isPortrait;
      //Non-Mandatory in case of single use
      orientationChange = true
      ret = true;
    }
    else {
    //Non-Mandatory in case of single use
    orientationChange = false;
    }

    return ret;
  }

 
  @override
  Widget build(BuildContext context) {
    if (checkOrientationChange(context)) {
      //Do Stuff if only once check is required. Else use the stub Variable. In this case, it is **orientationChange**.
    }



    //Using stub variable 
    Widget retWidget = orientationChange?Container():PlaceHolder();
    orientationChange = false;
    return retWidget;
    
  }
}
Ithyphallic answered 15/11, 2023 at 10:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.