之前寫過一篇文章叫"完美解決flutter 動(dòng)態(tài)TabBar TabView的坑" ,希望對(duì)各位客官有所有幫助.今天我們?cè)賮砩钔赥abView.
可能各位覺得 本人是不是與TabView扛上了,其實(shí)不是的,是項(xiàng)目需要嘍;
在看了之前那篇?jiǎng)討B(tài)Tab TabView的文章后,會(huì)解決動(dòng)態(tài)Tab,但緊接著就遇到,TabView里面的內(nèi)容,如何保持狀態(tài)呢.本人也在網(wǎng)上搜索一下解決方案,雖然有是有,但我發(fā)現(xiàn)要么是還不夠詳細(xì),要么就是對(duì)動(dòng)態(tài)Tab,TabView怎么保持狀態(tài)這塊沒有相應(yīng)的介紹,對(duì)于flutter 新手來說,可能還是難度的.這就是寫這篇文章的初衷了.
好了,說不多說,先來看一下最終的效果.
1.固定個(gè)數(shù)的Tab (留意圖片中滾動(dòng)到的行數(shù).比喻英語先是滾到了200行,等操作一段時(shí)間,再回來英語界面,還是在200行那個(gè)位置,也就是狀態(tài)被保持了; 下面2張效果圖同理)

2.動(dòng)態(tài)Tab

3.動(dòng)態(tài)Tab,每個(gè)TabView里面的數(shù)據(jù)不相同

固定個(gè)數(shù)的Tab
- 先新建一個(gè)tab_page
- 再分別建立 chinese_page, english_page, math_page
tab_page 代碼如下:
import 'package:flutter/material.dart';
import 'package:flutter_test_demos/chinese_page.dart';
import 'english_page.dart';
import 'package:flutter_test_demos/math_page.dart';
class TabPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _TabBar();
}
class _TabBar extends State<TabPage> {
final List<String> _tabValues = ['語文', '英語', '數(shù)學(xué)'];
final List<String> _contentList = [
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)',
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)',
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)',
];
TabController _controller;
@override
void initState() {
super.initState();
_controller = TabController(
length: _tabValues.length,
vsync: ScrollableState(),
);
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('TabBar'),
bottom: TabBar(
tabs: _tabValues.map((f) {
return Text(f);
}).toList(),
controller: _controller,
indicatorColor: Colors.red,
indicatorSize: TabBarIndicatorSize.tab,
isScrollable: true,
labelColor: Colors.red,
unselectedLabelColor: Colors.black,
indicatorWeight: 5.0,
labelStyle: TextStyle(height: 2),
),
),
body: TabBarView(controller: _controller, children: [
ChinesePage(_contentList),
EnglisthPage(),
MathPage()
] //固定Tab
),
);
}
}
chinese_page 代碼如下:
import 'package:flutter/material.dart';
class ChinesePage extends StatefulWidget {
List list;
ChinesePage(this.list);
@override
_ChinesePageState createState() => _ChinesePageState();
}
class _ChinesePageState extends State<ChinesePage>
with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: widget.list.length,
itemBuilder: (build, index) {
return Container(
padding: EdgeInsets.only(top: 150),
child: Text("${widget.list[index]} ----- $index"));
}));
}
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
english_page 代碼如下:
import 'package:flutter/material.dart';
class EnglisthPage extends StatefulWidget {
@override
_EnglisthPageState createState() => _EnglisthPageState();
}
class _EnglisthPageState extends State<EnglisthPage>
with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
return Scaffold(body: ListView.builder(itemBuilder: (build, index) {
return Text("en --- $index");
}));
}
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
math_page 代碼如下:
import 'package:flutter/material.dart';
class MathPage extends StatefulWidget {
// String title;
// MathPage(this.title);
@override
_MathPageState createState() => _MathPageState();
}
class _MathPageState extends State<MathPage>
with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
return Scaffold(body: ListView.builder(itemBuilder: (build, index) {
return Text("math --- $index");
}));
}
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
重點(diǎn)來嘍
chinese_page, english_page, math_page 三個(gè)界面的代碼都比較簡(jiǎn)單,關(guān)鍵的每個(gè)界面都是 with AutomaticKeepAliveClientMixin 以及 重寫了 bool get wantKeepAlive => true;這個(gè)方法. 這就是狀態(tài)保持的關(guān)鍵地方
寫到這里是不是感覺此文章就應(yīng)該結(jié)束了呢,其實(shí)不是的, 在項(xiàng)目中很有可能tab的個(gè)數(shù)是不確定,比喻說,tab個(gè)數(shù)是網(wǎng)絡(luò)請(qǐng)求下來的數(shù)據(jù),這就有了動(dòng)態(tài)tab,接下來,我們介紹動(dòng)態(tài)tab怎么保持狀態(tài)
動(dòng)態(tài)Tab
- 先新建一個(gè)tab_page (這個(gè)tab_page與前面有點(diǎn)區(qū)別)
- 再新建一個(gè)math_page (這個(gè)math_page與前面有點(diǎn)區(qū)別)
tab_page 代碼如下:
import 'package:flutter/material.dart';
import 'package:flutter_test_demos/chinese_page.dart';
import 'english_page.dart';
import 'package:flutter_test_demos/math_page.dart';
class TabPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _TabBar();
}
class _TabBar extends State<TabPage> {
final List<String> _tabValues = [
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)'
];
final List<String> _contentList = [
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)',
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)',
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)',
];
TabController _controller;
@override
void initState() {
super.initState();
_controller = TabController(
length: _tabValues.length,
vsync: ScrollableState(),
);
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('TabBar'),
bottom: TabBar(
tabs: _tabValues.map((f) {
return Text(f);
}).toList(),
controller: _controller,
indicatorColor: Colors.red,
indicatorSize: TabBarIndicatorSize.tab,
isScrollable: true,
labelColor: Colors.red,
unselectedLabelColor: Colors.black,
indicatorWeight: 5.0,
labelStyle: TextStyle(height: 2),
),
),
body: TabBarView(
controller: _controller,
children: //動(dòng)態(tài)Tab
createSameContentPages(_tabValues)),
);
}
//創(chuàng)建與tabs個(gè)數(shù)相同的 Pages
List<Widget> createSameContentPages(List tabList) {
List<Widget> desList = [];
for (int i = 0; i < tabList.length; i++) {
desList.add(MathPage(tabList[i]));
}
return desList;
}
}
math_page 代碼如下:
import 'package:flutter/material.dart';
class MathPage extends StatefulWidget {
String title;
MathPage(this.title);
@override
_MathPageState createState() => _MathPageState();
}
class _MathPageState extends State<MathPage>
with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
return Scaffold(body: ListView.builder(itemBuilder: (build, index) {
return Text("${widget.title} --- $index");
}));
}
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
跑起來試試吧,與前面的效果圖第二張圖運(yùn)行是一樣的結(jié)果.
動(dòng)態(tài)Tab 每個(gè)TabView里面的數(shù)據(jù)不相同
- 先新建一個(gè)tab_page (這個(gè)tab_page與前面有點(diǎn)區(qū)別)
tab_page 代碼如下:
import 'package:flutter/material.dart';
import 'package:flutter_test_demos/chinese_page.dart';
import 'english_page.dart';
import 'package:flutter_test_demos/math_page.dart';
class TabPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _TabBar();
}
class _TabBar extends State<TabPage> {
final List<String> _tabValues = [
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)'
];
final List<String> _contentList = [
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)',
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)',
'語文',
'英語',
'化學(xué)',
'物理',
'數(shù)學(xué)',
'生物',
'體育',
'經(jīng)濟(jì)',
];
TabController _controller;
@override
void initState() {
super.initState();
_controller = TabController(
length: _tabValues.length,
vsync: ScrollableState(),
);
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('TabBar'),
bottom: TabBar(
tabs: _tabValues.map((f) {
return Text(f);
}).toList(),
controller: _controller,
indicatorColor: Colors.red,
indicatorSize: TabBarIndicatorSize.tab,
isScrollable: true,
labelColor: Colors.red,
unselectedLabelColor: Colors.black,
indicatorWeight: 5.0,
labelStyle: TextStyle(height: 2),
),
),
body: TabBarView(
controller: _controller,
children: //動(dòng)態(tài)Tab
createPages(_contentList, _tabValues)),
);
}
List<Widget> createPages(List contentList, List tabList) {
List<Widget> desList = [];
for (int i = 0; i < tabList.length; i++) {
if (i == 0) {
desList.add(ChinesePage(contentList.sublist(0, 10))); //傳入不同的數(shù)據(jù)
} else if (i == 1) {
desList.add(ChinesePage(contentList.sublist(0, 5))); //傳入不同的數(shù)據(jù)
} else {
desList.add(ChinesePage(contentList)); //傳入不同的數(shù)據(jù)
}
}
return desList;
}
}
_tabValues 這個(gè)list可以是網(wǎng)絡(luò)請(qǐng)求下來的數(shù)據(jù).我這里是直接寫死的,總體意思是根據(jù)_tabValues的個(gè)數(shù)來生成對(duì)應(yīng)個(gè)數(shù)的pages,而且能保持各個(gè)page的狀態(tài);
跑起來試試吧,與前面的效果圖第三張圖運(yùn)行是一樣的結(jié)果.
結(jié)尾
希望這篇干貨,對(duì)大家有所幫助吧,后續(xù)會(huì)分享更多干貨,也希望大家多支持--不妨點(diǎn)個(gè)贊吧~~