Flutter: làm thế nào để ngăn thay đổi hướng thiết bị và ép dọc?


122

Tôi muốn ngăn ứng dụng của mình thay đổi hướng và buộc bố cục dính vào "chân dung".

Trong main.dart, tôi đặt:

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

nhưng khi tôi sử dụng các nút xoay của Trình mô phỏng Android, bố cục "tuân theo" hướng thiết bị mới ...

Làm thế nào tôi có thể giải quyết điều này?

Cảm ơn


4
Giả sử bạn đã nhập 'package:flutter/services.dart', thì có thể đó là lỗi: github.com/flutter/flutter/issues/13238
Brian Kung

Không chắc tại sao điều này xảy ra với bạn. Tôi đã thử chạy mã của bạn trên một trình giả lập và cũng là thiết bị của riêng tôi và nó hoạt động tốt.
Hemanth Raj

SystemChrome.setPreferredOrientationstrả về không đồng bộ, vì vậy có vẻ như runAppnên được bao trong một then.
Ken

Câu trả lời:


189

Nhập package:flutter/services.dart, sau đó

Đặt phương pháp SystemChrome.setPreferredOrientationsbên trong Widget build().

Thí dụ:

  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      SystemChrome.setPreferredOrientations([
        DeviceOrientation.portraitUp,
        DeviceOrientation.portraitDown,
      ]);
      return new MaterialApp(...);
    }
  }

Cập nhật

Giải pháp này có thể không hoạt động đối với một số thiết bị IOS như đã đề cập trong tài liệu cập nhật về lỗi vào tháng 10 năm 2019.

Họ khuyên nên sửa hướng bằng cách đặt UISupportedInterfaceOrientations trong Info.plist như thế này

<array>
    <string>UIInterfaceOrientationPortrait</string>
</array>

Để biết thêm thông tin https://github.com/flutter/flutter/issues/27235#issuecomment-508995063


Đã làm việc. Cảm ơn bạn <3
Suthura Sudharaka

1
Nếu bạn đặt SystemChrome.setPreferredOrientations trong chính, bạn sẽ gặp lỗi: ServicesBinding.defaultBinaryMessenger đã được truy cập trước khi khởi tạo ràng buộc. Việc chèn mã vào bản dựng hoạt động vì các ràng buộc đã được khởi tạo tại thời điểm này.
Golden Lion

75

@boeledi, Nếu bạn muốn "khóa" hướng thiết bị và không cho phép nó thay đổi khi người dùng xoay điện thoại của họ, điều này có thể dễ dàng đặt như bên dưới,

// This did not work as requirement
void main() {
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  runApp(new MyApp());
}

Bạn phải đợi cho đến khi setPreferredOrientationshoàn tất và sau đó khởi động ứng dụng

// This will works always for lock screen Orientation.
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
    .then((_) {
      runApp(new MyApp());
    });
}

Đôi khi nó phát ra lỗi khi biên dịch, bạn nên sử dụng các giải pháp gốc. Thêm 'android: screenOrientation = "chân dung"' vào MainActivity trên AndroidManifest như Abeer Iqbal's đề xuất đã làm việc cho tôi trên Android.
Tincho825

44

iOS:

Kêu gọi SystemChrome.setPreferredOrientations()không làm việc cho tôi, và tôi đã phải thay đổi Device Orientationtrong dự án Xcode như sau:

nhập mô tả hình ảnh ở đây

Android:

Đặt screenOrientationthuộc tính portraitcho hoạt động chính trong tệp android/app/src/main/AndroidManifest.xmlnhư sau:

nhập mô tả hình ảnh ở đây


Tôi đã gặp vấn đề tương tự, bạn đã chạy nó trên iPad chưa? Tôi chỉ thử nghiệm trên iPad và điều này có vẻ là một vấn đề: github.com/flutter/flutter/issues/27235
Boy

android: Thuộc tính này đã được thêm vào API cấp 24.
BloodLoss

Tôi sử dụng screenOrientationtừ API cấp 8 cho Android. @BloodLoss, tôi nghĩ bạn đọc nó trên tài liệu, nhưng về resizeableActivitythuộc tính. Kiểm tra lại liên kết. ^^
Erick M. Sprengel

22

Phương thức 'setPreferredOrientations' trả về một đối tượng Tương lai. Mỗi tài liệu, một Tương lai đại diện cho một số giá trị sẽ có sẵn ở đâu đó trong tương lai. Đó là lý do tại sao bạn sẽ đợi cho đến khi nó có sẵn và sau đó chuyển sang ứng dụng. Do đó, sẽ có phương thức 'then' được sử dụng, theo định nghĩa, "đăng ký các lệnh gọi lại sẽ được gọi khi Tương lai hoàn thành". Do đó, bạn sẽ sử dụng mã này:

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

Ngoài ra, phải nhập tệp sau:

'package: Flagship / services.dart'


Tôi có thể xác nhận điều này hoạt động. Nhưng hãy sử dụng whenComplete () thay vì then (), khi hàm không có tham số.
Csaba Gergely

20

Mở android / app / src / main / AndroidManifest.xml và thêm dòng sau vào MainActivity:

android:screenOrientation="portrait"

Nếu bạn có cái này:

<activity
        android:name=".MainActivity"
        android:launchMode="singleTop"
        android:theme="@style/LaunchTheme"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize">

Bạn sẽ kết thúc với một cái gì đó như thế này:

<activity
        android:name=".MainActivity"
        android:launchMode="singleTop"
        android:theme="@style/LaunchTheme"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize">

Điều này hoạt động cho Android. Trên iOS, bạn sẽ phải thay đổi điều này từ trang Xcode: https://i.stack.imgur.com/hswoe.png (như Hejazi đã nói)


cảm ơn, NHỚ thứ tự của "chân dung" sau khi "định hướng" configChanges không thành vấn đề.
MR_AMDEV

13

Trước hết, hãy nhập tệp này vào tệp main.dart

import 'package:flutter/services.dart';

Sau đó, không sao chép dán thay vì xem (ghi nhớ) và viết mã bên dưới trong tệp main.dart

Để buộc trong bức chân dung chế độ:

void main() {
  SystemChrome.setPreferredOrientations(
      [DeviceOrientation.portraitUp,DeviceOrientation.portraitDown])
      .then((_) => runApp(MyApp()),
  );

Để buộc trong bối cảnh chế độ:

   void main() {
      SystemChrome.setPreferredOrientations(
          [DeviceOrientation.landscapeLeft,DeviceOrientation.landscapeRight])
          .then((_) => runApp(MyApp()),
      );

1
Cảm ơn bạn đã nhắc mọi người không sao chép-dán một cách mù quáng
Ryan

1
Tôi hiểu tại sao bạn yêu cầu KHÔNG sao chép dán ... đoạn kết} bị thiếu ... Tôi sao chép dán ... :)
rohan koshti

không hoạt động cho chrome nổi
Golden Lion

13

Đặt WidgetsFlutterBinding.ensureInitialized () nếu không, bạn sẽ gặp lỗi khi xây dựng.

import 'package:flutter/services.dart';

    void main() async => {
          WidgetsFlutterBinding.ensureInitialized(),

          await SystemChrome.setPreferredOrientations(
              [DeviceOrientation.portraitUp]), // To turn off landscape mode

          runApp(MainApp())
        };

5

setPreferredOrientationtrả về a Future<void>, vì vậy nó là không đồng bộ. Cách tiếp cận dễ đọc nhất là xác định mainlà không đồng bộ:

Future<void> main() async {
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  return runApp(new MyApp());
}

3
Tôi rất không đồng ý. awaitlà một mẫu lập trình phổ biến có mặt bằng nhiều ngôn ngữ và nó rất rõ ràng là gì. thentạo ra các mức độ làm tổ. Nếu bạn có ba hoặc bốn đoạn liên tục, bạn thensẽ thực sự trở nên rất khó đọc.
Rob Lyndon

.thencó thể được xâu chuỗi thay vì lồng vào nhau, như nó mong đợi a FutureOr. Điều này cho phép tôi sử dụng một cách tiếp cận chức năng hơn, dễ đọc và trang nhã hơn. Ví dụ: tôi có thể sử dụng phần nội dung biểu thức thay vì phần nội dung trong dấu ngoặc vuông bằng cách xâu chuỗi "thens".
Mateus Felipe

Đôi khi nó phát ra lỗi khi biên dịch, bạn nên sử dụng các giải pháp gốc. Thêm 'android: screenOrientation = "chân dung"' vào MainActivity trên AndroidManifest như Abeer Iqbal's đề xuất đã làm việc cho tôi trên Android.
Tincho825

Nếu bạn gặp phải lỗi: "Ngoại lệ không được xử lý: ServicesBinding.defaultBinaryMessenger đã được truy cập trước khi khởi tạo ràng buộc." hãy thử sử dụng bản sửa lỗi này: stackoverflow.com/questions/57689492/…
Fillipe Silva

1

Đối với các phiên bản rung mới cùng với việc thiết lập, preferred Orientationchúng tôi cần thêm một dòng bổ sung tức là

 WidgetsFlutterBinding.ensureInitialized();

Vì vậy, mã làm việc cho điều này là -

import 'package:flutter/services.dart';
    void main() {
          WidgetsFlutterBinding.ensureInitialized();
          SystemChrome.setPreferredOrientations([
            DeviceOrientation.portraitUp,
            DeviceOrientation.portraitDown
          ]);
          runApp(MyApp());
        }


0

Thử

 void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await SystemChrome.setPreferredOrientations(
          [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); 
    
      runApp(MyApp());
 }

Bạn cũng có thể thay đổi cài đặt hướng màn hình trong tệp kê khai android và tệp info.plist của ios.


0

Nhập nhập khẩu 'gói: Flagship / services.dart';

Sau đó, bạn đưa dòng mã bên dưới vào tệp main.dart và trong phương thức chính của bạn như sau:

WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitDown,
    DeviceOrientation.portraitUp,
  ]);

runApp(myApp());

-4

Giải pháp tốt nhất sẽ là sử dụng nó trong phương thức xây dựng của MyApp ().

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.