GVKun编程网logo

dart – Flutter:AutomaticKeepAliveClientMixin不能与BottomNavigationBar一起使用(flutter与dart关系)

8

在本文中,我们将为您详细介绍dart–Flutter:AutomaticKeepAliveClientMixin不能与BottomNavigationBar一起使用的相关知识,并且为您解答关于flut

在本文中,我们将为您详细介绍dart – Flutter:AutomaticKeepAliveClientMixin不能与BottomNavigationBar一起使用的相关知识,并且为您解答关于flutter与dart关系的疑问,此外,我们还会提供一些关于(17)Flutter BottomNavigationBar、16-Flutter移动电商实战-切换后页面状态的保持AutomaticKeepAliveClientMixin、5、Flutter 实现 ViewPager、bottomNavigationBar 界面切换、BottomNavigationBar + BottomNavigationBarItem 导航的另外一种用法的有用信息。

本文目录一览:

dart – Flutter:AutomaticKeepAliveClientMixin不能与BottomNavigationBar一起使用(flutter与dart关系)

dart – Flutter:AutomaticKeepAliveClientMixin不能与BottomNavigationBar一起使用(flutter与dart关系)

我有一个名为AddPatientView的页面,其中BottomNavigationBar包含AddPatientInfo和AddPatient Images页面.所有这三个都是有状态的小部件.

默认情况下,AddPatientInfo打开,其中包含一堆TextFields(用于输入患者信息),在AddPatientimages页面中,用户可以添加Images.

问题是如果我在AddPatientInfo上填充TextFields然后转到AddPatientimages然后返回,所有TextFields都是空的.这是正确的,因为整个小部件树得到重建,我放弃了所有填充的数据.

所以我正在实现AutomaticKeepAliveClientMixin,因此即使更改选项卡也会保持状态.但它似乎不起作用:

Working Gif via GIPHY

这是我的代码:

AddPatientView(父)

class AddPatientView extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _AddPatientViewState();
  }
}

class _AddPatientViewState extends State<AddPatientView> {
  int _currentIndex = 0;
  List<Widget> _children;
  List<File> _imageFileList = new List<File>();

  @override
  void initState() {
    super.initState();
    _children = [
      AddPatientInfo(savePatient),AddPatientimages(_imageFileList)
    ];
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("New Patient Record"),),body: _children[_currentIndex],bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,items: [
          BottomNavigationBarItem(icon: new Icon(Icons.create),title: new Text('Info')),BottomNavigationBarItem(icon: new Icon(Icons.camera_alt),title: new Text('Images')),],onTap: (int index) {
          setState(() {
            _currentIndex = index;
          });
        },);
  }
}

AddPatientInfo

class AddPatientInfo extends StatefulWidget {
  final Function savePatient;

  AddPatientInfo(this.savePatient){
  }

  @override
  State<StatefulWidget> createState() {
    return _AddPatientInfoState();
  }
}

class _AddPatientInfoState extends State<AddPatientInfo> with AutomaticKeepAliveClientMixin<AddPatientInfo> {

  Function _savePatient;
  String _firstName,_lastName,_gender,_phone,_email,_diabetesMeds,_hypertensionMeds,_others;
  int _age,_diabetesYears,_hypertensionYears,_smokesPerDay,_smokerYears;
  bool _diabetes = false,_hypertension = false,_smoker = false,_chestPain = false,_cva = false,_ckd = false,_breathlessness = false,_syncope = false,_sweating = false,_sweatingFeet = false;

  List<String> _genderList = new List<String>();
  List<String> _yesNoList = new List<String>();
  List<File> _imageFileList = new List<File>();

  @override
  void initState() {
    super.initState();
    _savePatient = widget.savePatient;
    _genderList.addAll(['Male','Female','Other']);
    _yesNoList.addAll(['Yes','No']);
    _gender = _genderList.elementAt(0);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizetoAvoidBottomPadding: false,body: Container(
        margin: EdgeInsets.all(10.0),child: Form(
          child: new ListView(
            children: <Widget>[
              TextField(
                decoration: Inputdecoration(
                    labelText: 'Patient First Name',labelStyle: TextStyle(
                        color: Colors.black
                    ),hintText: 'Enter patients first name'
                ),onChanged: (String value) {
                  setState(() {
                    _firstName = value;
                  });
                },TextField(
                decoration: Inputdecoration(
                    labelText: 'Patient Last Name',hintText: 'Enter patients last name'
                ),onChanged: (String value) {
                  setState(() {
                    _lastName = value;
                  });
                },//other textfield widgets below
            ],)
      ),);
  }

  @override
  bool get wantKeepAlive => true;
}

我在这里错过了什么?是否有更优雅的方式来维护表单中的数据?

解决方法

从 AutomaticKeepAliveClientMixin的文档:

/// A mixin with convenience methods for clients of [AutomaticKeepAlive]. Used
/// with [State] subclasses.
///
/// Subclasses must implement [wantKeepAlive],and their [build] methods must
/// call `super.build` (the return value will always return null,and should be
/// ignored).

所以在你的例子中,在你返回Scaffold之前只需要调用super.build:

Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(...);
  }

(17)Flutter BottomNavigationBar

(17)Flutter BottomNavigationBar

 效果展示

项目结构:

 

main.dart

内容很简单

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

import ''home/home.dart'';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: ''Flutter Demo'',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You''ll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn''t reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      initialRoute: "/",
      routes: {
        "/": (context) => Home(),
      },
    );
  }
}

Home里面也没有做什么处理 如果项目定型的话  ndexPage就可以改为home使用。

因为home 只做了一层转发

home.dart

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

import ''IndexPage.dart'';

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return IndexPage();
  }
}

核心代码来了IndexPage.dart

因为要点击修改页面状态 所以使用了 StatefulWidget 

不然没有setStatus方法

import ''package:flutter/material.dart'';
import ''package:flutter_xiaochao/home/page/advisory_page.dart'';
import ''package:flutter_xiaochao/home/page/expore_page.dart'';
import ''package:flutter_xiaochao/home/page/guide_page.dart'';
import ''package:flutter_xiaochao/home/page/mime_page.dart'';

class IndexPage extends StatefulWidget {
  @override
  _IndexPageState createState() => _IndexPageState();
}

class _IndexPageState extends State<IndexPage> {
  final List<BottomNavigationBarItem> bottomNavItems = [
    BottomNavigationBarItem(
      backgroundColor: Colors.blue,
      icon: Icon(Icons.home),
      label: "探索",
    ),
    BottomNavigationBarItem(
      backgroundColor: Colors.green,
      icon: Icon(Icons.message),
      label: "指南",
    ),
    BottomNavigationBarItem(
      backgroundColor: Colors.amber,
      icon: Icon(Icons.shopping_cart),
      label: "资讯",
    ),
    BottomNavigationBarItem(
      backgroundColor: Colors.red,
      icon: Icon(Icons.person),
      label: "我的",
    ),
  ];
  final pages = [ExplorePage(), GuidePage(), AdvisoryPage(), MinePage()];

  int currentIndex;

  @override
  void initState() {
    currentIndex = 0;
  }

  void _changeIndexPage(index) {
    /*如果点击的导航项不是当前项  切换 */
    if (index != currentIndex) {
      setState(() {
        currentIndex = index;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: BottomNavigationBar(
        items: bottomNavItems,
        currentIndex: currentIndex,
        type: BottomNavigationBarType.shifting,
        showSelectedLabels: true,
        showUnselectedLabels: true,
        onTap: _changeIndexPage,
      ),
      body: pages[currentIndex],
    );
  }
}

余下四个就很简单

advisory_page.dart

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

class AdvisoryPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      child: Text("发现"),
    );
  }
}

expore_page.dart


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

class ExplorePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      child: Text("探索"),
    );
  }
}

guide_page.dart


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

class GuidePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      child: Text("向导"),
    );
  }
}

mime_page.dart


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

class MinePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      child: Text("我的"),
    );
  }
}

 

16-Flutter移动电商实战-切换后页面状态的保持AutomaticKeepAliveClientMixin

16-Flutter移动电商实战-切换后页面状态的保持AutomaticKeepAliveClientMixin

底栏切换每次都重新请求是一件非常恶心的事,flutter 中提供了AutomaticKeepAliveClientMixin 帮我们完成页面状态保存效果。

1、AutomaticKeepAliveClientMixin

AutomaticKeepAliveClientMixin 这个 Mixin 是 Flutter 为了保持页面设置的。哪个页面需要保持页面状态,就在这个页面进行混入。

不过使用使用这个 Mixin 是有几个先决条件的:

  • 使用的页面必须是 StatefulWidget,如果是 StatelessWidget 是没办法办法使用的。
  • 其实只有两个前置组件才能保持页面状态:PageView 和 IndexedStack。
  • 重写 wantKeepAlive 方法,如果不重写也是实现不了的。

2、修改index_page.dart

明白基本知识之后,就可以修改 index_page.dart,思路就是增加一个 IndexedStack 包裹在 tabBodies 外边。

整体代码如下:

import ''package:flutter/cupertino.dart'';
import ''package:flutter/material.dart'';
import ''home_page.dart'';
import ''category_page.dart'';
import ''cart_page.dart'';
import ''member_page.dart'';


class IndexPage extends StatefulWidget {
  _IndexPageState createState() => _IndexPageState();
}

class _IndexPageState extends State<IndexPage>{

  PageController _pageController;

  final List<BottomNavigationBarItem> bottomTabs = [
    BottomNavigationBarItem(
      icon:Icon(CupertinoIcons.home),
      title:Text(''首页'')
    ),
    BottomNavigationBarItem(
      icon:Icon(CupertinoIcons.search),
      title:Text(''分类'')
    ),
    BottomNavigationBarItem(
      icon:Icon(CupertinoIcons.shopping_cart),
      title:Text(''购物车'')
    ),
     BottomNavigationBarItem(
      icon:Icon(CupertinoIcons.profile_circled),
      title:Text(''会员中心'')
    ),
  ];

  final List<Widget> tabBodies = [
    HomePage(),
    CategoryPage(),
    CartPage(),
    MemberPage()
  ];

  int currentIndex= 0;
  var currentPage ;

  @override
  void initState() {
   currentPage=tabBodies[currentIndex];
   _pageController=new PageController()
      ..addListener(() {
        if (currentPage != _pageController.page.round()) {
          setState(() {
            currentPage = _pageController.page.round();
          });
        }
  });
  super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color.fromRGBO(2442452451.0),
      bottomNavigationBar: BottomNavigationBar(
        type:BottomNavigationBarType.fixed,
        currentIndex: currentIndex,
        items:bottomTabs,
        onTap: (index){
          setState(() {
           currentIndex=index;
            currentPage =tabBodies[currentIndex]; 
          });

        },
      ),
      body: IndexedStack(
        index: currentIndex,
        children: tabBodies
      )
    );
  }
}

3、加入Mixin保持页面状态

在 home_page.dart 里加入 AutomaticKeepAliveClientMixin 混入,加入后需要重写 wantKeepAlive 方法。

主要代码如下:

class _HomePageState extends State<HomePagewith AutomaticKeepAliveClientMixin {

  @override
  bool get wantKeepAlive =>true;
}

为了检验结果,我们在 HomePageState 里增加一个 initState,在里边 print 一些内容,如果内容输出了,证明我们的页面重新加载了,如果没输出,证明我们的页面保持了状态。

@override
void initState() {
    super.initState();
    print(''我打印了哈哈哈哈哈'');
}

5、Flutter 实现 ViewPager、bottomNavigationBar 界面切换

5、Flutter 实现 ViewPager、bottomNavigationBar 界面切换

1、前言

首先我们想一下,如果在 Android 中实现 布局切换,通常的思路是:

  1. 做一个 viewpager
  2. 一组 Fragment
  3. 每个 Fragment 绑定一个 xml
  4. 最后填充至 viewpager

2、Flutter 实现

上边提到的用安卓原生做,思路是很明确,但是代码量还是有的,那么来看一下, Flutter 如何使用 Viewpager 实现的。

2.1、创建有状态 Widget

首先创建有状态 StatefulWidget,然后构建 state:_ApplicationPageState

class ApplicationPage extends StatefulWidget {
  //@override
  //_ApplicationPageState createState() => new _ApplicationPageState();
   等同于上边注释掉的 createState();
    @override
    State<StatefulWidget> createState() {
      // TODO: implement createState
      return _ApplicationPageState();
    }

}

2.2、state

Scaffold 实现了基本的纸墨设计布局结构。所以我们 new Scaffold 然后 return 即可。

class _ApplicationPageState extends State<ApplicationPage> {

  int _currentPageIndex = 0;
  var _pageController = new PageController(initialPage: 0);

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar:
       new AppBar(
         title: new Text("我是AppBar"),
         centerTitle: true,
       ),
      body: new PageView.builder(
          onPageChanged:_pageChange,
          controller: _pageController,
          itemBuilder: (BuildContext context,int index){
            return index==1?new Text("我是第一页"):new Text("我是第二页");
          },
          itemCount: 2,
      ),
      bottomNavigationBar: new BottomNavigationBar(items: [
              BottomNavigationBarItem(
                  icon: new Icon(Icons.category), title: new Text("首页")),
              BottomNavigationBarItem(
                  icon: new Icon(Icons.message), title: new Text("我的")),
          ],
          currentIndex: _currentPageIndex,
          onTap: onTap,
      ),
    );
  }

  // bottomnaviagtionbar 和 pageview 的联动
  void onTap(int index) {
    // 过pageview的pagecontroller的animateToPage方法可以跳转
    _pageController.animateToPage(index,
        duration: const Duration(milliseconds: 300), curve: Curves.ease);
  }

  void _pageChange(int index) {
    setState(() {
      if (_currentPageIndex != index) {
        _currentPageIndex = index;
      }
    });
  }

}

关于上边有几个方法:

Scaffold 有下面几个主要属性:
  • appBar:显示在界面顶部的一个 AppBar,也就是 Android 中的 ActionBar 、Toolbar
  • body:当前界面所显示的主要内容 Widget
  • bottomNavigationBar: 显示在页面底部的导航栏

2.3、navBar和pageview如何联动?

通过上边的代码也可以发现,pageView有个 onPageChanged 属性,并且类中定义了一个 _pageChange 方法,

通过 pageview 的 pagecontroller 的 animateToPage 方法实现的界面跳转;

 

BottomNavigationBar + BottomNavigationBarItem 导航的另外一种用法

BottomNavigationBar + BottomNavigationBarItem 导航的另外一种用法

import ''package:flutter/material.dart'';
import ''News.dart'';
import ''Video.dart'';
import ''Chat.dart'';
import ''MyId.dart'';

class AppTwo extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(home: Home());
}

class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  int _currentIndex = 0;
  final List<Widget> _children = [
    NewsPage(),
    VideoPage(),
    ChatPage(),
    MyIdPage()
  ];

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
//      appBar: AppBar(
//        title: Text("第二种方式"),
//        centerTitle: true,
//      ),
      body: _children[_currentIndex],
//      CupertinoTabBar 是IOS分格
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        onTap: onTabTapped,
        items: [
          BottomNavigationBarItem(
              title: new Text("Home"), icon: new Icon(Icons.home)),
          BottomNavigationBarItem(
              title: new Text("List"), icon: new Icon(Icons.list)),
          BottomNavigationBarItem(
              title: new Text("Message"), icon: new Icon(Icons.message)),
        ],
      ),
    );

  }

  void onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
}
import ''package:flutter/material.dart'';
import ''Guide.dart'';

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

 

今天关于dart – Flutter:AutomaticKeepAliveClientMixin不能与BottomNavigationBar一起使用flutter与dart关系的分享就到这里,希望大家有所收获,若想了解更多关于(17)Flutter BottomNavigationBar、16-Flutter移动电商实战-切换后页面状态的保持AutomaticKeepAliveClientMixin、5、Flutter 实现 ViewPager、bottomNavigationBar 界面切换、BottomNavigationBar + BottomNavigationBarItem 导航的另外一种用法等相关知识,可以在本站进行查询。

本文标签: