Flutter -如何制作自定义标签栏

iqjalb3h  于 2022-12-24  发布在  Flutter
关注(0)|答案(5)|浏览(220)

这是我想要的输出。我仍然是新的flutter,所以谁可以让我知道,如果已经有一个小部件,这种开关或我应该如何做一个??此外,我希望数据显示在这个按钮下面的变化,如果我选择其他按钮,但我猜这是显而易见的。
先谢了。

e5nszbig

e5nszbig1#

您可以使用TabBar小部件来实现这一点,我添加了一个完整的示例来演示如何使用TabBar小部件来创建它:

  • 代码 *
  1. class StackOver extends StatefulWidget {
  2. @override
  3. _StackOverState createState() => _StackOverState();
  4. }
  5. class _StackOverState extends State<StackOver>
  6. with SingleTickerProviderStateMixin {
  7. TabController _tabController;
  8. @override
  9. void initState() {
  10. _tabController = TabController(length: 2, vsync: this);
  11. super.initState();
  12. }
  13. @override
  14. void dispose() {
  15. super.dispose();
  16. _tabController.dispose();
  17. }
  18. @override
  19. Widget build(BuildContext context) {
  20. return Scaffold(
  21. appBar: AppBar(
  22. title: Text(
  23. 'Tab bar',
  24. ),
  25. ),
  26. body: Padding(
  27. padding: const EdgeInsets.all(8.0),
  28. child: Column(
  29. children: [
  30. // give the tab bar a height [can change hheight to preferred height]
  31. Container(
  32. height: 45,
  33. decoration: BoxDecoration(
  34. color: Colors.grey[300],
  35. borderRadius: BorderRadius.circular(
  36. 25.0,
  37. ),
  38. ),
  39. child: TabBar(
  40. controller: _tabController,
  41. // give the indicator a decoration (color and border radius)
  42. indicator: BoxDecoration(
  43. borderRadius: BorderRadius.circular(
  44. 25.0,
  45. ),
  46. color: Colors.green,
  47. ),
  48. labelColor: Colors.white,
  49. unselectedLabelColor: Colors.black,
  50. tabs: [
  51. // first tab [you can add an icon using the icon property]
  52. Tab(
  53. text: 'Place Bid',
  54. ),
  55. // second tab [you can add an icon using the icon property]
  56. Tab(
  57. text: 'Buy Now',
  58. ),
  59. ],
  60. ),
  61. ),
  62. // tab bar view here
  63. Expanded(
  64. child: TabBarView(
  65. controller: _tabController,
  66. children: [
  67. // first tab bar view widget
  68. Center(
  69. child: Text(
  70. 'Place Bid',
  71. style: TextStyle(
  72. fontSize: 25,
  73. fontWeight: FontWeight.w600,
  74. ),
  75. ),
  76. ),
  77. // second tab bar view widget
  78. Center(
  79. child: Text(
  80. 'Buy Now',
  81. style: TextStyle(
  82. fontSize: 25,
  83. fontWeight: FontWeight.w600,
  84. ),
  85. ),
  86. ),
  87. ],
  88. ),
  89. ),
  90. ],
  91. ),
  92. ),
  93. );
  94. }
  95. }
  • 输出 *
展开查看全部
atmip9wb

atmip9wb2#

试试这个,你必须change一些colourfont:-

  1. import 'package:flutter/material.dart';
  2. typedef SwitchOnChange = Function(int);
  3. class CustomSwitch extends StatefulWidget {
  4. SwitchOnChange onChange;
  5. CustomSwitch({this.onChange});
  6. @override
  7. State<StatefulWidget> createState() {
  8. return CustomSwitchState();
  9. }
  10. }
  11. class CustomSwitchState extends State<CustomSwitch>
  12. with TickerProviderStateMixin {
  13. AnimationController controller;
  14. Animation animation;
  15. GlobalKey key = GlobalKey();
  16. @override
  17. void initState() {
  18. Future.delayed(Duration(milliseconds: 100)).then((v) {
  19. controller = AnimationController(
  20. vsync: this, duration: Duration(milliseconds: 300));
  21. tabWidth = key.currentContext.size.width / 2;
  22. // var width = (media.size.width - (2 * media.padding.left)) / 2;
  23. animation = Tween<double>(begin: 0, end: tabWidth).animate(controller);
  24. setState(() {});
  25. controller.addListener(() {
  26. setState(() {});
  27. });
  28. });
  29. super.initState();
  30. }
  31. var selectedValue = 0;
  32. double tabWidth = 0;
  33. @override
  34. Widget build(BuildContext context) {
  35. return GestureDetector(
  36. onTap: () {
  37. selectedValue == 0 ? this.controller.forward() : controller.reverse();
  38. selectedValue = selectedValue == 0 ? 1 : 0;
  39. },
  40. child: Container(
  41. key: key,
  42. height: 44,
  43. decoration: BoxDecoration(
  44. color: Colors.grey, borderRadius: BorderRadius.circular(22)),
  45. child: Stack(
  46. children: <Widget>[
  47. Row(
  48. children: <Widget>[
  49. Transform.translate(
  50. offset: Offset(animation?.value ?? 0, 0),
  51. child: Container(
  52. height: 44,
  53. width: tabWidth,
  54. decoration: BoxDecoration(
  55. color: Colors.white,
  56. borderRadius: BorderRadius.circular(22),
  57. boxShadow: [
  58. BoxShadow(color: Colors.grey, blurRadius: 3),
  59. ]),
  60. ),
  61. ),
  62. ],
  63. ),
  64. Center(
  65. child: Row(
  66. mainAxisAlignment: MainAxisAlignment.center,
  67. crossAxisAlignment: CrossAxisAlignment.center,
  68. children: <Widget>[
  69. Container(
  70. width: tabWidth,
  71. child: Row(
  72. mainAxisAlignment: MainAxisAlignment.center,
  73. children: <Widget>[
  74. Icon(Icons.directions_walk),
  75. SizedBox(width: 5),
  76. Text("Place Bid")
  77. ],
  78. ),
  79. ),
  80. Container(
  81. width: tabWidth,
  82. child: Row(
  83. mainAxisAlignment: MainAxisAlignment.center,
  84. children: <Widget>[
  85. Icon(Icons.directions_walk),
  86. SizedBox(width: 5),
  87. Text("Buy now")
  88. ],
  89. ),
  90. )
  91. ],
  92. ),
  93. ),
  94. ],
  95. ),
  96. ),
  97. );
  98. }
  99. }
展开查看全部
wsewodh2

wsewodh23#

您也可以使用PageView小工具。

  1. const double borderRadius = 25.0;
  2. class CustomSwitchState extends StatefulWidget {
  3. @override
  4. _CustomSwitchStateState createState() => _CustomSwitchStateState();
  5. }
  6. class _CustomSwitchStateState extends State<CustomSwitchState> with SingleTickerProviderStateMixin {
  7. PageController _pageController;
  8. int activePageIndex = 0;
  9. @override
  10. void dispose() {
  11. _pageController.dispose();
  12. super.dispose();
  13. }
  14. @override
  15. void initState() {
  16. super.initState();
  17. _pageController = PageController();
  18. }
  19. @override
  20. Widget build(BuildContext context) {
  21. return Scaffold(
  22. body: SingleChildScrollView(
  23. physics: const ClampingScrollPhysics(),
  24. child: GestureDetector(
  25. onTap: () {
  26. FocusScope.of(context).requestFocus(FocusNode());
  27. },
  28. child: Container(
  29. width: MediaQuery.of(context).size.width,
  30. height: MediaQuery.of(context).size.height,
  31. child: Column(
  32. mainAxisSize: MainAxisSize.max,
  33. children: <Widget>[
  34. Padding(
  35. padding: const EdgeInsets.only(top: 20.0),
  36. child: _menuBar(context),
  37. ),
  38. Expanded(
  39. flex: 2,
  40. child: PageView(
  41. controller: _pageController,
  42. physics: const ClampingScrollPhysics(),
  43. onPageChanged: (int i) {
  44. FocusScope.of(context).requestFocus(FocusNode());
  45. setState(() {
  46. activePageIndex = i;
  47. });
  48. },
  49. children: <Widget>[
  50. ConstrainedBox(
  51. constraints: const BoxConstraints.expand(),
  52. child: Center(child: Text("Place Bid"),),
  53. ),
  54. ConstrainedBox(
  55. constraints: const BoxConstraints.expand(),
  56. child: Center(child: Text("Buy Now"),),
  57. ),
  58. ],
  59. ),
  60. ),
  61. ],
  62. ),
  63. ),
  64. ),
  65. ));
  66. }
  67. Widget _menuBar(BuildContext context) {
  68. return Container(
  69. width: 300.0,
  70. height: 50.0,
  71. decoration: const BoxDecoration(
  72. color: Color(0XFFE0E0E0),
  73. borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
  74. ),
  75. child: Row(
  76. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  77. children: <Widget>[
  78. Expanded(
  79. child: InkWell(
  80. borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
  81. onTap: _onPlaceBidButtonPress,
  82. child: Container(
  83. width: MediaQuery.of(context).size.width,
  84. padding: EdgeInsets.symmetric(vertical: 15),
  85. alignment: Alignment.center,
  86. decoration: (activePageIndex == 0) ? const BoxDecoration(
  87. color: Colors.green,
  88. borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
  89. ) : null,
  90. child: Text(
  91. "Place Bid",
  92. style: (activePageIndex == 0) ? TextStyle(color: Colors.white) : TextStyle(color: Colors.black),
  93. ),
  94. ),
  95. ),
  96. ),
  97. Expanded(
  98. child: InkWell(
  99. borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
  100. onTap: _onBuyNowButtonPress,
  101. child: Container(
  102. width: MediaQuery.of(context).size.width,
  103. padding: EdgeInsets.symmetric(vertical: 15),
  104. alignment: Alignment.center,
  105. decoration: (activePageIndex == 1) ? const BoxDecoration(
  106. color: Colors.green,
  107. borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
  108. ) : null,
  109. child: Text(
  110. "Buy Now",
  111. style: (activePageIndex == 1) ? TextStyle(color: Colors.white, fontWeight: FontWeight.bold) : TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
  112. ),
  113. ),
  114. ),
  115. ),
  116. ],
  117. ),
  118. );
  119. }
  120. void _onPlaceBidButtonPress() {
  121. _pageController.animateToPage(0,
  122. duration: const Duration(milliseconds: 500), curve: Curves.decelerate);
  123. }
  124. void _onBuyNowButtonPress() {
  125. _pageController.animateToPage(1,
  126. duration: const Duration(milliseconds: 500), curve: Curves.decelerate);
  127. }
  128. }

输出

展开查看全部
pod7payv

pod7payv4#

    • 如果您想要这样的选项卡布局,可以使用此**

输出:

  1. import 'package:flutter/material.dart';
  2. import 'package:icons_helper/icons_helper.dart';
  3. class DetailScreen extends StatefulWidget {
  4. var body;
  5. String title = "";
  6. DetailScreen(this.body, this.title);
  7. @override
  8. _MainPageState createState() => _MainPageState();
  9. }
  10. class _MainPageState extends State<DetailScreen> with TickerProviderStateMixin {
  11. late int _startingTabCount;
  12. List<Tab> _tabs = <Tab>[];
  13. List<Widget> _generalWidgets = <Widget>[];
  14. late TabController _tabController;
  15. @override
  16. void initState() {
  17. _startingTabCount = widget.body["related_modules"].length;
  18. _tabs = getTabs(_startingTabCount);
  19. _tabController = getTabController();
  20. super.initState();
  21. }
  22. @override
  23. void dispose() {
  24. _tabController.dispose();
  25. super.dispose();
  26. }
  27. @override
  28. Widget build(BuildContext context) {
  29. return Scaffold(
  30. appBar: AppBar(
  31. title: Text(widget.title),
  32. bottom: TabBar(
  33. isScrollable: true,
  34. tabs: _tabs,
  35. controller: _tabController,
  36. ),
  37. flexibleSpace: Container(
  38. decoration: BoxDecoration(
  39. gradient: LinearGradient(
  40. colors: [
  41. Colors.grey,
  42. Colors.blue,
  43. ],
  44. stops: [0.3, 1.0],
  45. ),
  46. ),
  47. ),
  48. leading: IconButton(
  49. icon: Icon(Icons.arrow_back_ios),
  50. color: Colors.white,
  51. onPressed: () {
  52. Navigator.of(context, rootNavigator: true).pop(context);
  53. },
  54. ),
  55. actions: <Widget>[
  56. IconButton(
  57. icon: Icon(Icons.skip_previous),
  58. color: Colors.white,
  59. onPressed: () {
  60. goToPreviousPage();
  61. },
  62. ),
  63. Container(
  64. margin: EdgeInsets.only(right: 15),
  65. child: IconButton(
  66. icon: Icon(Icons.skip_next),
  67. color: Colors.white,
  68. onPressed: () {
  69. goToNextPage();
  70. },
  71. ),
  72. )
  73. ],
  74. ),
  75. body: Column(
  76. children: <Widget>[
  77. Expanded(
  78. child: TabBarView(
  79. physics: NeverScrollableScrollPhysics(),
  80. controller: _tabController,
  81. children: getWidgets(),
  82. ),
  83. ),
  84. ],
  85. ),
  86. );
  87. }
  88. TabController getTabController() {
  89. return TabController(length: _tabs.length, vsync: this)
  90. ..addListener(_updatePage);
  91. }
  92. Tab getTab(int widgetNumber) {
  93. return Tab(
  94. icon: Column(
  95. children: [
  96. if (widget.body["related_modules"][widgetNumber]["icon"].toString() ==
  97. "fa-comments-o") ...[
  98. Icon(
  99. Icons.comment_outlined,
  100. ),
  101. ] else if (widget.body["related_modules"][widgetNumber]["icon"]
  102. .toString() ==
  103. "fa-map-marker") ...[
  104. Icon(
  105. Icons.location_on_rounded,
  106. ),
  107. ] else if (widget.body["related_modules"][widgetNumber]["icon"]
  108. .toString() ==
  109. "fa-address-card") ...[
  110. Icon(
  111. Icons.contact_page_sharp,
  112. ),
  113. ] else ...[
  114. Icon(
  115. getIconUsingPrefix(
  116. name: widget.body["related_modules"][widgetNumber]["icon"]
  117. .toString()
  118. .substring(3),
  119. ),
  120. )
  121. ]
  122. ],
  123. ),
  124. text: widget.body["related_modules"][widgetNumber]["label"].toString(),
  125. );
  126. }
  127. Widget getWidget(int widgetNumber) {
  128. return Center(
  129. child: Text("Widget nr: $widgetNumber"),
  130. );
  131. }
  132. List<Tab> getTabs(int count) {
  133. _tabs.clear();
  134. for (int i = 0; i < count; i++) {
  135. _tabs.add(getTab(i));
  136. }
  137. return _tabs;
  138. }
  139. List<Widget> getWidgets() {
  140. _generalWidgets.clear();
  141. for (int i = 0; i < _tabs.length; i++) {
  142. _generalWidgets.add(getWidget(i));
  143. }
  144. return _generalWidgets;
  145. }
  146. void _updatePage() {
  147. setState(() {});
  148. }
  149. //Tab helpers
  150. bool isFirstPage() {
  151. return _tabController.index == 0;
  152. }
  153. bool isLastPage() {
  154. return _tabController.index == _tabController.length - 1;
  155. }
  156. void goToPreviousPage() {
  157. _tabController.animateTo(_tabController.index - 1);
  158. }
  159. void goToNextPage() {
  160. isLastPage()
  161. ? showDialog(
  162. context: context,
  163. builder: (context) => AlertDialog(
  164. title: Text("End reached"),
  165. content: Text("This is the last page.")))
  166. : _tabController.animateTo(_tabController.index + 1);
  167. }
  168. }
展开查看全部
9jyewag0

9jyewag05#

以下是我的变通方法,我认为这是最好的方法。

  1. import 'package:flutter/material.dart';
  2. class SettingsScreen extends StatelessWidget {
  3. const SettingsScreen({
  4. super.key,
  5. });
  6. @override
  7. Widget build(BuildContext context) {
  8. return DefaultTabController(
  9. length: 2,
  10. child: Scaffold(
  11. appBar: AppBar(
  12. title: const Text('Settings'),
  13. bottom: PreferredSize(
  14. preferredSize: Size.fromHeight(AppBar().preferredSize.height),
  15. child: Container(
  16. height: 50,
  17. padding: const EdgeInsets.symmetric(
  18. horizontal: 20,
  19. vertical: 5,
  20. ),
  21. child: Container(
  22. decoration: BoxDecoration(
  23. borderRadius: BorderRadius.circular(
  24. 10,
  25. ),
  26. color: Colors.grey[200],
  27. ),
  28. child: TabBar(
  29. labelColor: Colors.white,
  30. unselectedLabelColor: Colors.black,
  31. indicator: BoxDecoration(
  32. borderRadius: BorderRadius.circular(
  33. 10,
  34. ),
  35. color: Colors.pink,
  36. ),
  37. tabs: const [
  38. Tab(
  39. text: 'Basic',
  40. ),
  41. Tab(
  42. text: 'Advanced',
  43. )
  44. ],
  45. ),
  46. ),
  47. ),
  48. ),
  49. ),
  50. body: const TabBarView(
  51. children: [
  52. Center(
  53. child: Text(
  54. 'Basic Settings',
  55. style: TextStyle(
  56. fontSize: 30,
  57. ),
  58. ),
  59. ),
  60. Center(
  61. child: Text(
  62. 'Advanced Settings',
  63. style: TextStyle(
  64. fontSize: 30,
  65. ),
  66. ),
  67. ),
  68. ],
  69. ),
  70. ),
  71. );
  72. }
  73. }

展开查看全部

相关问题