You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter如何实现仅单个页面保持横屏模式且不影响其他页面?

问题原因
  • 路由跳转逻辑问题:Flutter 中使用 Navigator.push 打开新页面时,原首页会被保存在路由栈中,不会触发 dispose 生命周期,你写在 dispose 里的恢复屏幕方向、释放播放器的逻辑完全没有执行。
  • 播放器实例错误:你初始化时创建了两个独立的播放器实例,给 _assetsAudioPlayer 赋值了一个空实例,又调用 AssetsAudioPlayer.newPlayer() 创建了另一个实例实际播放音乐,后续对 _assetsAudioPlayer 的所有操作都不会影响正在播放的实例,导致音乐无法停止。
解决方案

这里提供两种实现方案,根据你的业务复杂度选择即可。

方案1:跳转时手动处理(适合跳转入口少的场景)

直接在首页的跳转逻辑中,添加离开和返回时的处理逻辑:

第一步:修正播放器初始化逻辑

@override
void initState() {
  super.initState();
  // 设置首页仅横屏
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeRight,
    DeviceOrientation.landscapeLeft,
  ]);
  // 仅创建一个播放器实例
  _assetsAudioPlayer = AssetsAudioPlayer();
  _assetsAudioPlayer!.open(
    Audio("assets/audio/bgm.mp3"),
    autoStart: true,
    showNotification: true,
  );
}

第二步:修改跳转逻辑

// 首页内的跳转触发方法
void jumpToOtherPage() async {
  // 离开首页前暂停音乐,恢复全局默认方向
  await _assetsAudioPlayer?.pause();
  await SystemChrome.setPreferredOrientations([
    // 此处修改为你应用其他页面的默认方向,默认竖屏可仅保留portraitUp、portraitDown
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
    DeviceOrientation.landscapeRight,
    DeviceOrientation.landscapeLeft,
  ]);
  // 执行跳转
  await Navigator.push(context, MaterialPageRoute(builder: (context) => OtherPage()));
  // 回到首页后恢复横屏和音乐播放
  await SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeRight,
    DeviceOrientation.landscapeLeft,
  ]);
  _assetsAudioPlayer?.play();
}

第三步:修正dispose释放逻辑

@override
void dispose() {
  // 先释放播放器资源
  _assetsAudioPlayer?.stop();
  _assetsAudioPlayer?.dispose();
  _assetsAudioPlayer = null;
  // 恢复全局方向
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
    DeviceOrientation.landscapeRight,
    DeviceOrientation.landscapeLeft,
  ]);
  super.dispose();
}

方案2:路由监听自动处理(适合跳转入口多的场景)

通过 RouteObserver 监听首页的路由状态,自动处理进出首页的逻辑,无需每个跳转入口单独修改。

第一步:全局注册路由观察者

// 全局位置定义
final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>();

//  MaterialApp中添加配置
MaterialApp(
  navigatorObservers: [routeObserver],
  // 其他配置不变
)

第二步:首页混入RouteAware监听路由状态

class _HomePageState extends State<HomePage> with RouteAware {
  AssetsAudioPlayer? _assetsAudioPlayer;

  @override
  void initState() {
    super.initState();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
    ]);
    _assetsAudioPlayer = AssetsAudioPlayer();
    _assetsAudioPlayer!.open(
      Audio("assets/audio/bgm.mp3"),
      autoStart: true,
      showNotification: true,
    );
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 订阅路由监听
    routeObserver.subscribe(this, ModalRoute.of(context)!);
  }

  // 跳转到其他页面时触发
  @override
  void didPushNext() {
    _assetsAudioPlayer?.pause();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
    ]);
    super.didPushNext();
  }

  // 从其他页面回到首页时触发
  @override
  void didPopNext() {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
    ]);
    _assetsAudioPlayer?.play();
    super.didPopNext();
  }

  @override
  void dispose() {
    // 取消订阅,释放资源
    routeObserver.unsubscribe(this);
    _assetsAudioPlayer?.stop();
    _assetsAudioPlayer?.dispose();
    _assetsAudioPlayer = null;
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
    ]);
    super.dispose();
  }
}

内容的提问来源于stack exchange,提问作者Febin Johnson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 12:45:01