在页面之间切换时,抖动的相机框架掉落了

时间:2018-07-04 10:11:52

标签: dart flutter

我尝试将Flutter camera plugin(0.2.1)与PageView和BottomNavigationBar结合使用,但是每次切换页面时,都会跳过几帧,并且UI冻结一秒钟。

对于这个示例,我简化了代码库:

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

void main() => runApp(new Pages());

class Pages extends StatefulWidget {
  @override
  _PagesState createState() => _PagesState();
}

class _PagesState extends State<Pages> {
  PageController _pageController;
  int _page = 0;

  @override
  void initState() {
    _pageController = new PageController();
    super.initState();
  }

  void navTapped(int page) {
    _pageController.animateToPage(page,
        duration: const Duration(milliseconds: 300), curve: Curves.ease);
  }

  void onPageChanged(int page) {
    setState(() {
      this._page = page;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: new Text("CameraTest"),
        ),
        body: PageView(
          children: <Widget>[Feed(), Camera(), Profile()],
          controller: _pageController,
          onPageChanged: onPageChanged,
        ),
        bottomNavigationBar: new BottomNavigationBar(
          items: [
            new BottomNavigationBarItem(
                icon: new Icon(Icons.home), title: new Text("Feed")),
            new BottomNavigationBarItem(
                icon: new Icon(Icons.camera), title: new Text("Capture")),
            new BottomNavigationBarItem(
                icon: new Icon(Icons.person), title: new Text("Profile"))
          ],
          onTap: navTapped,
          currentIndex: _page,
        ),
      ),
    );
  }
}

class Camera extends StatefulWidget {
  @override
  _CameraState createState() => _CameraState();
}

class _CameraState extends State<Camera> {
  List<CameraDescription> _cameras;
  CameraController _controller;

  initCameras() async{
    _cameras = await availableCameras();
    _controller = new CameraController(_cameras[0], ResolutionPreset.medium);
    await _controller.initialize();
    setState(() {});
  }

  @override
  void initState() {
    initCameras();
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    if (_controller == null || !_controller.value.isInitialized) {
      return new Center(
        child: new Text("Waiting for camera...", style: TextStyle(color: Colors.grey),),
      );
    }
    return new AspectRatio(
        aspectRatio: _controller.value.aspectRatio,
        child: new CameraPreview(_controller));
  }
}

//just placeholder widgets

class Feed extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: new Text("Feed"));
  }
}

class Profile extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: new Text("Profile"));
  }
}

基本上有三页,中间一页显示摄像机预览 (how it's supposed to look),但切换到相机并从相机切换回this时会发生。这确实很烦人,因为它破坏了用户体验,并且一点也不流畅。当调用initCameras()或放置摄像机控制器时,会出现延迟。我尝试将initCameras()与FutureBuilder结合使用,后者根本没有帮助,并在单独的隔离中运行该方法,但是似乎仅允许在主要隔离上进行平台调用。对我来说有点奇怪,因为打开相机并不需要太多的cpu功能,因此异步方法应该没问题。我知道有一个image-picker plugin,但我想直接在应用程序中预览。我还考虑过在应用程序启动时运行initCameras(),但是当用户仅使用应用程序的另一个页面时,我并不想一直运行相机。

是否有任何方法可以改善initCameras()或使用其他实现来解决口吃?我什至都不在乎是否需要一秒钟来加载,但我不希望任何帧跳越。

我遵循了相机页面底部的example

在不同的Android版本的物理设备和仿真器上进行了测试。

2 个答案:

答案 0 :(得分:0)

如果要在与将图像路径存储为全局变量不同的页面中使用图像路径,请在所需位置使用它。

答案 1 :(得分:0)

我通过在初始化相机之前添加延迟来解决了类似的问题:

Future.delayed(Duration(seconds: 1), () {
  initCameras();
});

这样,在页面导航动画完成后调用initCameras()。您可以显示CircularProgressIndicator()以使此延迟更加人性化。 我敢肯定有更整洁的方法来解决此问题,但这似乎是最简单的解决方案。