Youtube like fullscreen button on flutter

Viewed 1146

I’m becoming crazy trying to implement a Youtube-like fullscreen button, I have my widget tree inside an OrientationBuilder and the logic should follow this scheme:

If the orientation is locked by user: Fullscreen button should change the orientation from portrait to landscape, if in full screen the button should change to portrait this part is not a problem, I just call the correct SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]); or SystemChrome.setPreferredOrientations([DeviceOrientation.portrait]); and everything works ad expected

If the orientation is NOT locked by user: This is where everything becomes tricky… If in portrait and the fullscreen button is pressed SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]); should be called, but, if the user rotate the phone to landscape, and then back to portrait the orientation should be restored to the original portrait (check on youtube) the same should happen in fullscreen, the button swap to portrait, then if I move the phone back to portrait and then back to landscape, the app should rotate again. The only things that I have accomplished is to get the correct functionality on iOS, on the layout builder, I reset the preferred Orientation to “portrait, landscapeLeft, landscapeRight” just before the return of the OrientationBuilder builder method, but in Android this cause the Application to be rebuilt with the current orientation, but in iOS it stays until a back and forth rotation, any idea?

1 Answers

I encountered a similar issue on disabling fullscreen mode on my app. To enable fullscreen, I force the app to be on landscape by using SystemChrome.setPreferredOrientations(). I then disable fullscreen by setting the preferred orientation to portrait.

void _enableFullscreen(bool fullscreen) {
  isFullscreen = fullscreen;
  if (fullscreen) {
    // Force landscape orientation for fullscreen
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.landscapeRight,
    ]);
  } else {
    // Force portrait
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);
  }
}

The app detects the device's orientation using OrientationBuilder.

OrientationBuilder(builder: (context, orientation) {
  debugPrint('Device orientation: $orientation');
  isFullscreen = orientation == Orientation.landscape;
  return isFullscreen

      /// Landscape Layout
      ? Container()
       
      /// Portrait Layout
      : Column();
})

The issue that I encountered here was the widget doesn't rebuild base on the device's orientation (i.e. auto-rotate) after setting a preferred orientation. To solve this issue I set an empty list on setPreferredOrientations() to instruct the Flutter app to defer to the operating system default (orientation) again as mentioned in the docs.

Here's a complete sample. I'm using Flutter 2.5

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool isFullscreen = false;

  void _enableFullscreen(bool fullscreen) {
    isFullscreen = fullscreen;
    if (fullscreen) {
      // Force landscape orientation for fullscreen
      SystemChrome.setPreferredOrientations([
        DeviceOrientation.landscapeLeft,
        DeviceOrientation.landscapeRight,
      ]);
    } else {
      // Force portrait
      SystemChrome.setPreferredOrientations([
        DeviceOrientation.portraitUp,
        DeviceOrientation.portraitDown,
      ]);
      // Set preferred orientation to device default
      // Empty list causes the application to defer to the operating system default.
      // See: https://api.flutter.dev/flutter/services/SystemChrome/setPreferredOrientations.html
      SystemChrome.setPreferredOrientations([]);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: OrientationBuilder(builder: (context, orientation) {
        debugPrint('Device orientation: $orientation');
        isFullscreen = orientation == Orientation.landscape;
        return isFullscreen

            /// Landscape Layout
            ? Container(color: Colors.green)

            /// Portrait Layout
            : Column(
                children: [
                  Expanded(
                    flex: 1,
                    child: Container(color: Colors.green),
                  ),
                  Expanded(
                    flex: 3,
                    child: Container(color: Colors.lightBlueAccent),
                  )
                ],
              );
      }),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _enableFullscreen(!isFullscreen);
        },
        tooltip: 'Fullscreen',
        child: const Icon(Icons.fullscreen),
      ),
    );
  }
}

Demo

Related