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

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

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

e5nszbig

e5nszbig1#

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

  • 代码 *
class StackOver extends StatefulWidget {
  @override
  _StackOverState createState() => _StackOverState();
}

class _StackOverState extends State<StackOver>
    with SingleTickerProviderStateMixin {
  TabController _tabController;

  @override
  void initState() {
    _tabController = TabController(length: 2, vsync: this);
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
    _tabController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'Tab bar',
        ),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          children: [
            // give the tab bar a height [can change hheight to preferred height]
            Container(
              height: 45,
              decoration: BoxDecoration(
                color: Colors.grey[300],
                borderRadius: BorderRadius.circular(
                  25.0,
                ),
              ),
              child: TabBar(
                controller: _tabController,
                // give the indicator a decoration (color and border radius)
                indicator: BoxDecoration(
                  borderRadius: BorderRadius.circular(
                    25.0,
                  ),
                  color: Colors.green,
                ),
                labelColor: Colors.white,
                unselectedLabelColor: Colors.black,
                tabs: [
                  // first tab [you can add an icon using the icon property]
                  Tab(
                    text: 'Place Bid',
                  ),

                  // second tab [you can add an icon using the icon property]
                  Tab(
                    text: 'Buy Now',
                  ),
                ],
              ),
            ),
            // tab bar view here
            Expanded(
              child: TabBarView(
                controller: _tabController,
                children: [
                  // first tab bar view widget 
                  Center(
                    child: Text(
                      'Place Bid',
                      style: TextStyle(
                        fontSize: 25,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ),

                  // second tab bar view widget
                  Center(
                    child: Text(
                      'Buy Now',
                      style: TextStyle(
                        fontSize: 25,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
  • 输出 *
atmip9wb

atmip9wb2#

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

import 'package:flutter/material.dart';

typedef SwitchOnChange = Function(int);

class CustomSwitch extends StatefulWidget {
  SwitchOnChange onChange;

  CustomSwitch({this.onChange});

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

class CustomSwitchState extends State<CustomSwitch>
    with TickerProviderStateMixin {
  AnimationController controller;
  Animation animation;

  GlobalKey key = GlobalKey();
  @override
  void initState() {
    Future.delayed(Duration(milliseconds: 100)).then((v) {
      controller = AnimationController(
          vsync: this, duration: Duration(milliseconds: 300));

      tabWidth = key.currentContext.size.width / 2;
      // var width = (media.size.width - (2 * media.padding.left)) / 2;
      animation = Tween<double>(begin: 0, end: tabWidth).animate(controller);

      setState(() {});

      controller.addListener(() {
        setState(() {});
      });
    });
    super.initState();
  }

  var selectedValue = 0;
  double tabWidth = 0;
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        selectedValue == 0 ? this.controller.forward() : controller.reverse();
        selectedValue = selectedValue == 0 ? 1 : 0;
      },
      child: Container(
        key: key,
        height: 44,
        decoration: BoxDecoration(
            color: Colors.grey, borderRadius: BorderRadius.circular(22)),
        child: Stack(
          children: <Widget>[
            Row(
              children: <Widget>[
                Transform.translate(
                  offset: Offset(animation?.value ?? 0, 0),
                  child: Container(
                    height: 44,
                    width: tabWidth,
                    decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(22),
                        boxShadow: [
                          BoxShadow(color: Colors.grey, blurRadius: 3),
                        ]),
                  ),
                ),
              ],
            ),
            Center(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Container(
                    width: tabWidth,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Icon(Icons.directions_walk),
                        SizedBox(width: 5),
                        Text("Place Bid")
                      ],
                    ),
                  ),
                  Container(
                    width: tabWidth,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Icon(Icons.directions_walk),
                        SizedBox(width: 5),
                        Text("Buy now")
                      ],
                    ),
                  )
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
wsewodh2

wsewodh23#

您也可以使用PageView小工具。

const double borderRadius = 25.0;

class CustomSwitchState extends StatefulWidget {
  @override
  _CustomSwitchStateState createState() => _CustomSwitchStateState();
}

class _CustomSwitchStateState extends State<CustomSwitchState> with SingleTickerProviderStateMixin {

  PageController _pageController;
  int activePageIndex = 0;

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    _pageController = PageController();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SingleChildScrollView(
          physics: const ClampingScrollPhysics(),
          child: GestureDetector(
            onTap: () {
              FocusScope.of(context).requestFocus(FocusNode());
            },
            child: Container(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height,
              child: Column(
                mainAxisSize: MainAxisSize.max,
                children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.only(top: 20.0),
                    child: _menuBar(context),
                  ),
                  Expanded(
                    flex: 2,
                    child: PageView(
                      controller: _pageController,
                      physics: const ClampingScrollPhysics(),
                      onPageChanged: (int i) {
                        FocusScope.of(context).requestFocus(FocusNode());
                        setState(() {
                          activePageIndex = i;
                        });
                      },
                      children: <Widget>[
                        ConstrainedBox(
                          constraints: const BoxConstraints.expand(),
                          child: Center(child: Text("Place Bid"),),
                        ),
                        ConstrainedBox(
                          constraints: const BoxConstraints.expand(),
                          child: Center(child: Text("Buy Now"),),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        ));
  }

  Widget _menuBar(BuildContext context) {
    return Container(
      width: 300.0,
      height: 50.0,
      decoration: const BoxDecoration(
        color: Color(0XFFE0E0E0),
        borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
      ),
      child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Expanded(
              child: InkWell(
                borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
                onTap: _onPlaceBidButtonPress,
                child: Container(
                  width: MediaQuery.of(context).size.width,
                  padding: EdgeInsets.symmetric(vertical: 15),
                  alignment: Alignment.center,
                  decoration: (activePageIndex == 0) ? const BoxDecoration(
                    color: Colors.green,
                    borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
                  ) : null,
                  child: Text(
                    "Place Bid",
                    style: (activePageIndex == 0) ? TextStyle(color: Colors.white) : TextStyle(color: Colors.black),
                  ),
                ),
              ),
            ),
            Expanded(
              child: InkWell(
                borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
                onTap: _onBuyNowButtonPress,
                child: Container(
                  width: MediaQuery.of(context).size.width,
                  padding: EdgeInsets.symmetric(vertical: 15),
                  alignment: Alignment.center,
                  decoration: (activePageIndex == 1) ? const BoxDecoration(
                    color: Colors.green,
                    borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
                  ) : null,
                  child: Text(
                    "Buy Now",
                    style: (activePageIndex == 1) ? TextStyle(color: Colors.white, fontWeight: FontWeight.bold) : TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
                  ),
                ),
              ),
            ),
          ],
        ),
    );
  }

  void _onPlaceBidButtonPress() {
    _pageController.animateToPage(0,
        duration: const Duration(milliseconds: 500), curve: Curves.decelerate);
  }

  void _onBuyNowButtonPress() {
    _pageController.animateToPage(1,
        duration: const Duration(milliseconds: 500), curve: Curves.decelerate);
  }

}

输出

pod7payv

pod7payv4#

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

输出:

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

class DetailScreen extends StatefulWidget {
  var body;
  String title = "";

  DetailScreen(this.body, this.title);

  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<DetailScreen> with TickerProviderStateMixin {
  late int _startingTabCount;

  List<Tab> _tabs = <Tab>[];
  List<Widget> _generalWidgets = <Widget>[];
  late TabController _tabController;

  @override
  void initState() {
    _startingTabCount = widget.body["related_modules"].length;
    _tabs = getTabs(_startingTabCount);
    _tabController = getTabController();
    super.initState();
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        bottom: TabBar(
          isScrollable: true,
          tabs: _tabs,
          controller: _tabController,
        ),
        flexibleSpace: Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
              colors: [
                Colors.grey,
                Colors.blue,
              ],
              stops: [0.3, 1.0],
            ),
          ),
        ),
        leading: IconButton(
          icon: Icon(Icons.arrow_back_ios),
          color: Colors.white,
          onPressed: () {
            Navigator.of(context, rootNavigator: true).pop(context);
          },
        ),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.skip_previous),
            color: Colors.white,
            onPressed: () {
              goToPreviousPage();
            },
          ),
          Container(
            margin: EdgeInsets.only(right: 15),
            child: IconButton(
              icon: Icon(Icons.skip_next),
              color: Colors.white,
              onPressed: () {
                goToNextPage();
              },
            ),
          )
        ],
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: TabBarView(
              physics: NeverScrollableScrollPhysics(),
              controller: _tabController,
              children: getWidgets(),
            ),
          ),
        ],
      ),
    );
  }

  TabController getTabController() {
    return TabController(length: _tabs.length, vsync: this)
      ..addListener(_updatePage);
  }

  Tab getTab(int widgetNumber) {
    return Tab(
      icon: Column(
        children: [
          if (widget.body["related_modules"][widgetNumber]["icon"].toString() ==
              "fa-comments-o") ...[
            Icon(
              Icons.comment_outlined,
            ),
          ] else if (widget.body["related_modules"][widgetNumber]["icon"]
                  .toString() ==
              "fa-map-marker") ...[
            Icon(
              Icons.location_on_rounded,
            ),
          ] else if (widget.body["related_modules"][widgetNumber]["icon"]
                  .toString() ==
              "fa-address-card") ...[
            Icon(
              Icons.contact_page_sharp,
            ),
          ] else ...[
            Icon(
              getIconUsingPrefix(
                name: widget.body["related_modules"][widgetNumber]["icon"]
                    .toString()
                    .substring(3),
              ),
            )
          ]
        ],
      ),
      text: widget.body["related_modules"][widgetNumber]["label"].toString(),
    );
  }

  Widget getWidget(int widgetNumber) {
    return Center(
      child: Text("Widget nr: $widgetNumber"),
    );
  }

  List<Tab> getTabs(int count) {
    _tabs.clear();
    for (int i = 0; i < count; i++) {
      _tabs.add(getTab(i));
    }
    return _tabs;
  }

  List<Widget> getWidgets() {
    _generalWidgets.clear();
    for (int i = 0; i < _tabs.length; i++) {
      _generalWidgets.add(getWidget(i));
    }
    return _generalWidgets;
  }

  void _updatePage() {
    setState(() {});
  }

  //Tab helpers

  bool isFirstPage() {
    return _tabController.index == 0;
  }

  bool isLastPage() {
    return _tabController.index == _tabController.length - 1;
  }

  void goToPreviousPage() {
    _tabController.animateTo(_tabController.index - 1);
  }

  void goToNextPage() {
    isLastPage()
        ? showDialog(
            context: context,
            builder: (context) => AlertDialog(
                title: Text("End reached"),
                content: Text("This is the last page.")))
        : _tabController.animateTo(_tabController.index + 1);
  }
}
9jyewag0

9jyewag05#

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

import 'package:flutter/material.dart';

class SettingsScreen extends StatelessWidget {

  const SettingsScreen({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Settings'),
          bottom: PreferredSize(
            preferredSize: Size.fromHeight(AppBar().preferredSize.height),
            child: Container(
              height: 50,
              padding: const EdgeInsets.symmetric(
                horizontal: 20,
                vertical: 5,
              ),
              child: Container(
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(
                    10,
                  ),
                  color: Colors.grey[200],
                ),
                child: TabBar(
                  labelColor: Colors.white,
                  unselectedLabelColor: Colors.black,
                  indicator: BoxDecoration(
                    borderRadius: BorderRadius.circular(
                      10,
                    ),
                    color: Colors.pink,
                  ),
                  tabs: const [
                    Tab(
                      text: 'Basic',
                    ),
                    Tab(
                      text: 'Advanced',
                    )
                  ],
                ),
              ),
            ),
          ),
        ),
        body: const TabBarView(
          children: [
            Center(
              child: Text(
                'Basic Settings',
                style: TextStyle(
                  fontSize: 30,
                ),
              ),
            ),
            Center(
              child: Text(
                'Advanced Settings',
                style: TextStyle(
                  fontSize: 30,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

相关问题