问题描述
我在多页表单的底部有一个导航栏,带有可后退或前进的按钮,以及当前页面的指示器。
现在,我将指示器放置在另一个包含按钮的Row
上方的Row
中,例如:
这有效,即使在较小的显示器上也可以使用。但是,如果有足够的空间,我宁愿将指示器与按钮放在同一行(除了指示器不在中心):
问题是,对于某些设备而言,这可能太宽了,尤其是如果页面数不止几个。在那种情况下,我希望页面指示器或按钮可以像当前设计一样“换行”到新行。
将所有内容都放在Wrap
中很容易,但这将使NEXT
-按钮而不是页面指示符自动换行,因为那是最后一个元素。
是否有一种简单的方法可以使中间元素在需要时自动换行?还是必须借助手动计算尺寸并创建两种不同布局的黑魔法?
解决方法
最简单的解决方案是添加不可见的包装以计算高度。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',theme: ThemeData(
primarySwatch: Colors.blue,),home: Scaffold(
body: SafeArea(
child: MyHomePage(),);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int currentPageIndex = 1;
int pageCount = 8;
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,children: [
Text(
currentPageIndex.toString(),Row(
mainAxisSize: MainAxisSize.min,children: [
RaisedButton(
child: Text('+1 page'),onPressed: () => setState(() => ++pageCount),SizedBox(
width: 10,RaisedButton(
child: Text('-1 page'),onPressed: () => setState(() => --pageCount),],)
],Container(
child: _BottomNavigation(
onPrev: () => setState(() => --currentPageIndex),onNext: () => setState(() => ++currentPageIndex),currentCount: currentPageIndex,totalCount: pageCount,);
}
}
class _BottomNavigation extends StatelessWidget {
const _BottomNavigation({
Key key,@required this.totalCount,@required this.currentCount,@required this.onNext,@required this.onPrev,}) : assert(totalCount != null),assert(currentCount != null),assert(onNext != null),assert(onPrev != null),super(key: key);
final void Function() onPrev;
final void Function() onNext;
final int totalCount;
final int currentCount;
@override
Widget build(BuildContext context) {
return Stack(
children: [
buildHelper(),buildIndicatorBar(),Positioned(
bottom: 0,left: 0,right: 0,child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [
_button(
'<< PREIOUS',onPrev,isVisible: currentCount > 1,_button(
'NEXT >>',onNext,isVisible: currentCount < totalCount,);
}
Wrap buildHelper() {
return Wrap(
children: List.generate(
totalCount,(index) {
return Container(
width: index == 0 ? 250 : 15,height: 20,);
},);
}
Row buildIndicatorBar() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,children: List.generate(totalCount,(index) {
var isLast = totalCount != index + 1;
var isCurrent = currentCount == index + 1;
return Container(
height: isCurrent ? 20 : 10,width: isCurrent ? 20 : 10,margin: EdgeInsets.only(right: isLast ? 10 : 0),decoration: BoxDecoration(
shape: BoxShape.circle,color: isCurrent ? Colors.blueAccent : null,border: Border.all(
color: Colors.blueAccent,);
}),);
}
Widget _button(String text,void Function() onPress,{bool isVisible}) {
return Visibility(
visible: isVisible,child: GestureDetector(
onTap: onPress,child: Text(text),);
}
}