Flattern: So stellen Sie die Bildschirmausrichtung bei Bedarf ein und sperren sie

76

Auf einer meiner Flatter-Seiten muss der Bildschirm in den Querformatmodus versetzt und gesperrt werden, damit er nicht in den Hochformatmodus gedreht werden kann, sondern nur auf einer Seite. Benötigen Sie also eine Möglichkeit, diese Funktion im laufenden Betrieb zu aktivieren. Weiß jemand, wie man das macht?

Ich möchte, dass es sich nach links oder rechts dreht, nur nicht in den Hochformatmodus.

Jus10
quelle

Antworten:

161

Importieren Sie zuerst das Servicepaket:

import 'package:flutter/services.dart';

Dadurch erhalten Sie Zugriff auf die SystemChromeKlasse, die"Controls specific aspects of the operating system's graphical interface and how it interacts with the application."

Gehen Sie beim Laden des Widgets folgendermaßen vor:

@override
void initState(){
  super.initState();
  SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
  ]);
}

Wenn ich dann die Seite verlasse, normalisiere ich sie wie folgt:

@override
dispose(){
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeRight,
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
  super.dispose();
}
Jus10
quelle
2
aber scheint nur auf Android zu arbeiten github.com/flutter/flutter/issues/20124
Luigino De Togni
Oh, ich habe es nicht bemerkt. Das ist sehr gut möglich, ich habe das nur auf Android getestet.
Jus10
Trotzdem kann es durch Platform Channel github.com/flutter/flutter/issues/13238#issuecomment-435958221 gelöst werden und ich denke, es wird bald behoben
Luigino De Togni
19
Nur um zu ernennen, dass dieser Fehler vor Monaten behoben wurde, und diese Lösung funktioniert jetzt auch unter iOS
Pablo Insua
1
Soweit ich sehe, ist es keine gute Idee, die bevorzugte Ausrichtung in der Entsorgungsmethode festzulegen. Die Entsorgungsmethode wird nicht aufgerufen, wenn Sie zu einer anderen Route navigieren und beabsichtigen, zurückzukehren.
Rowan Gontier
25

Ich würde ein einfaches Mixin verwenden , um das Telefon im Hochformat zu sperren . Die folgende Lösung sperrt die gesamte App im Hochformat oder setzt bestimmte Bildschirme auf Hochformat, während die Drehung an anderer Stelle beibehalten wird.

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

/// Forces portrait-only mode application-wide
/// Use this Mixin on the main app widget i.e. app.dart
/// Flutter's 'App' has to extend Stateless widget.
///
/// Call `super.build(context)` in the main build() method
/// to enable portrait only mode
mixin PortraitModeMixin on StatelessWidget {
  @override
  Widget build(BuildContext context) {
    _portraitModeOnly();
    return null;
  }
}

/// Forces portrait-only mode on a specific screen
/// Use this Mixin in the specific screen you want to
/// block to portrait only mode.
///
/// Call `super.build(context)` in the State's build() method
/// and `super.dispose();` in the State's dispose() method
mixin PortraitStatefulModeMixin<T extends StatefulWidget> on State<T> {
  @override
  Widget build(BuildContext context) {
    _portraitModeOnly();
    return null;
  }

  @override
  void dispose() {
    _enableRotation();
  }
}

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

void _enableRotation() {
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.landscapeRight,
  ]);
}

Um die Rotation in der gesamten App zu blockieren, implementieren Sie sie PortraitModeMixinim Haupt- AppWidget. Denken Sie daran, rufen Sie super.build(context)in Widget build(BuildContext context)Methode.

/// Main App widget
class App extends StatelessWidget with PortraitModeMixin {
  const App();

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return CupertinoApp(
      title: 'Flutter Demo',
      theme: CupertinoThemeData(),
      home: Text("Block screen rotation example"),
    );
  }
}

Um die Drehung in einem bestimmten Bildschirm zu blockieren, implementieren Sie sie PortraitStatefulModeMixin<SampleScreen>im Status des jeweiligen Bildschirms. Denken Sie daran, rufen super.build(context)in die staatlichen build()Verfahren und super.dispose()in dispose()Verfahren. Wenn es sich bei Ihrem Bildschirm um ein StatelessWidget handelt, wiederholen Sie einfach die Lösung der App (vorheriges Beispiel), dh verwenden Sie sie PortraitModeMixin.

/// Specific screen
class SampleScreen extends StatefulWidget {
  SampleScreen() : super();

  @override
  State<StatefulWidget> createState() => _SampleScreenState();
}

class _SampleScreenState extends State<SampleScreen>
    with PortraitStatefulModeMixin<SampleScreen> {
  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Text("Flutter - Block screen rotation example");
  }

  @override
  void dispose() {
     super.dispose();
  }
}

Mixins mit einer solchen Syntax funktionieren ab Dart 2.1

kosiara - Bartosz Kosarzycki
quelle
1
Ich habe Ihre Mixin-Klasse ausprobiert - die zustandslose Version funktioniert einwandfrei, jedoch löst statefull eine Ausnahme aus, sobald meine statefull-Klasse ihre disposed-Methode aufruft. Beachten Sie, dass ich super.dispose()in meiner Klasse anrufe. Unten ist der Fehler: I / flutter (29686): Die folgende Zusicherung wurde beim Finalisieren des Widget-Baums ausgelöst: I / flutter (29686): _MultiPlayerAcceptPageState.dispose konnte super.dispose nicht aufrufen. I / flutter (29686): dispose () -Implementierungen müssen immer ihre discl () -Methode der Superklasse aufrufen, um sicherzustellen, dass alle vom Widget verwendeten I / flutter (29686): -Ressourcen vollständig freigegeben werden.
Angel Todorov
Gleiche Ausnahme für die Stateful-Version. Haben Sie dieses Problem gelöst?
Whisperer
4
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown])
    .then((_) {
      runApp(new MyApp());
    });
}
Prusakov
quelle
3
Obwohl dieser Code eine Lösung für die Frage bietet, ist es besser, einen Kontext hinzuzufügen, warum / wie er funktioniert. Dies kann zukünftigen Benutzern helfen, zu lernen und dieses Wissen auf ihren eigenen Code anzuwenden. Es ist auch wahrscheinlich, dass Sie positive Rückmeldungen von Benutzern in Form von Upvotes erhalten, wenn der Code erklärt wird.
Borchvm
4

Manchmal konnte es aufgrund von Nullinformationen zur Orientierung nicht funktionieren. Sie können es einfach so verwenden:

import services.dart


void main() {
    SystemChrome.setPreferredOrientations(
    [DeviceOrientation.portraitUp]
     )
        .then((_) {
          runApp(new MyApp());
        });
    }

// Warten Sie nach dem Starten der App auf die Ausrichtung des Einstellungsbildschirms und -> sperren Sie dann die Ausrichtung

dev.zom
quelle
1

Import services.dartund Ihre void mainFunktion sollte wie folgt sein:

void main(){

    WidgetsFlutterBinding.ensureInitialized();
    SystemChrome.setPreferredOrientations(
       [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown])
       .then((_){
           runApp(MyApp());
       }
    );
}
Samir Rahimy
quelle