【发布时间】:2021-01-14 14:54:06
【问题描述】:
我找到了flutter PageView inside TabBarView: scrolling to next tab at the end of page 但是这个解决方案对我不起作用
是否可以在 PageView 上滚动父 TabBar 并滚动?
我也找到了How to “merge” scrolls on a TabBarView inside a PageView? 但是这种情况是倒置的
这是我在应用程序中使用的代码,但我是 Flutter 的新手 Actual result in this video
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
final List<PageController> _controllers = List.generate(
EPeriod.values.length,
(index) => PageController(),
);
TabController _tabBarController;
@override
void initState() {
super.initState();
_tabBarController = TabController(
vsync: this,
length: EPeriod.values.length,
);
}
@override
void dispose() {
_tabBarController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
StyleGuide().init(context);
return Scaffold(
backgroundColor: StyleGuide.colors.accent,
body: Padding(
padding: EdgeInsets.only(
top: StyleGuide.sizes.topPadding,
bottom: StyleGuide.sizes.bottomPadding,
),
child: _buildContent(),
),
);
}
Widget _buildContent() {
return Center(
child: Column(
children: <Widget>[
_buildAppBar(),
_buildTabBarView(),
],
),
);
}
Widget _buildTabBarView() {
return DefaultTabController(
length: EPeriod.values.length,
child: Column(
children: [
Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1,
color: StyleGuide.colors.white.withOpacity(0.1),
),
),
),
child: TabBar(
controller: _tabBarController,
indicatorColor: StyleGuide.colors.white,
labelStyle: StyleGuide.styles.titleTabBar,
tabs: EPeriod.values
.map((period) => Container(
alignment: Alignment.center,
height: 40,
child: Text(describeEnum(period).toUpperCase()),
))
.toList(),
),
),
Container(
height: 166,
child: TabBarView(
controller: _tabBarController,
children:
EPeriod.values.asMap().entries.map(_buildPeriodData).toList(),
),
)
],
),
);
}
Widget _buildPeriodDataSummaryPage(EPeriod period) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Balance'.toUpperCase(),
style: StyleGuide.styles.titleSmall.copyWith(
color: StyleGuide.colors.white.withOpacity(0.5),
),
),
Text(
'-\$171 559.80',
style: StyleGuide.styles.titleLarge,
),
Text(
'+5.21%',
style: StyleGuide.styles.titleSmall.copyWith(
fontSize: 16,
color: StyleGuide.colors.white.withOpacity(0.8),
),
),
],
);
}
Widget _buildPeriodDataPieChartPage(EPeriod period) {
return Row(
children: [
Container(
width: StyleGuide.sizes.screenWidth / 2,
// TODO: chart
),
Container(
width: StyleGuide.sizes.screenWidth / 2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Incomes'.toUpperCase(),
style: StyleGuide.styles.titleSmall.copyWith(
color: StyleGuide.colors.white.withOpacity(0.5),
),
),
Text(
'\$171 559.80',
style: StyleGuide.styles.titleMedium,
),
SizedBox(height: 16),
Text(
'Expenses'.toUpperCase(),
style: StyleGuide.styles.titleSmall.copyWith(
color: StyleGuide.colors.white.withOpacity(0.5),
),
),
Text(
'-\$171 559.80',
style: StyleGuide.styles.titleMedium,
),
],
),
),
],
);
}
Widget _buildPeriodDataPage(int index, EPeriod period) {
Function widget =
index == 0 ? _buildPeriodDataSummaryPage : _buildPeriodDataPieChartPage;
return widget(period);
}
Widget _buildPeriodData(MapEntry<int, EPeriod> entry) {
var period = entry.value;
var index = entry.key;
final _controller = _controllers[index];
return Container(
height: 170,
child: Stack(
children: [
PageView.builder(
allowImplicitScrolling: true,
controller: _controller,
itemCount: 2,
itemBuilder: (context, index) => _buildPeriodDataPage(
index,
period,
),
onPageChanged: (page) {
var nextIndex = _tabBarController.index + 1;
if (page == 2 && nextIndex < _tabBarController.length) {
_tabBarController.animateTo(_tabBarController.index + 1);
}
var prevIndex = _tabBarController.index - 1;
if (page == -1 && prevIndex > -1) {
_tabBarController.animateTo(prevIndex);
}
},
),
DotsIndicator(
controller: _controller,
itemCount: 2,
onPageSelected: (page) {
_controller.animateToPage(
page,
duration: Home._kDuration,
curve: Home._kCurve,
);
},
),
],
),
);
}
Widget _buildAppBar() {
return Container(
height: 44,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(
alignment: Alignment.centerLeft,
child: GestureDetector(
child: Image.asset(
settingsIcon,
color: StyleGuide.colors.white,
),
),
),
),
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('Accounts', style: StyleGuide.styles.titleAppBar),
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
child:
Image.asset(searchIcon, color: StyleGuide.colors.white),
),
SizedBox(width: 12),
GestureDetector(
child: Image.asset(addIcon, color: StyleGuide.colors.white),
),
],
),
)
],
),
),
);
}
}
【问题讨论】:
标签: flutter