在 Flutter 中为选项卡添加底部边框

问题描述 投票:0回答:10

我想做的是添加 tabBar 的底部边框,因此它将位于选项卡标题下方、指示器颜色上方,对于活动选项卡和非活动选项卡,就像所附图像一样。

红线是我要添加的内容,绿线是指示器颜色。

注意,通常我使用“底部”为 appBar 执行此操作,但这里底部保留给 TabBar

这可能吗?

非常感谢

android flutter dart flutter-layout
10个回答
7
投票

您可以按照 abdulrahmanAbdullah 的说明设置 AppBar

shape
属性。但如果您严格需要指示器上方的边框,则可以将其放在每个选项卡栏项目内。这是对此的一种看法:

import 'package:flutter/material.dart';

void main() {
  runApp(TabBarDemo());
}



class TabBarDemo extends StatelessWidget {

  Widget _createTab(String text) {
    return Tab(
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(
            child: Container(
              child: Center(child: Text(text)),
              decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Colors.black)))
            )
          ),
        ]
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primaryColor: Colors.white,
      ),
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            elevation: 0,
            bottom: TabBar(
              labelPadding: EdgeInsets.all(0),
              tabs: [
                _createTab("Tab 1"),
                _createTab("Tab 2"),
                _createTab("Tab 3"),
              ],
            ),
            title: Text('Tabs Demo'),
          ),
          body: TabBarView(
            children: [
              Icon(Icons.directions_car),
              Icon(Icons.directions_transit),
              Icon(Icons.directions_bike),
            ],
          ),
        ),
      ),
    );
  }
}

7
投票

尝试设置appBar边框:

appBar: AppBar(
    shape: Border(bottom: BorderSide(color: Colors.red)),
     .... 

7
投票

只需将 TabBar 包装到 DecolatedBox 中,如下所示:

DecoratedBox(
    decoration: BoxDecoration(
    //This is for background color
    color: Colors.white.withOpacity(0.0),

    //This is for bottom border that is needed
    border: Border(
        bottom: BorderSide(color: AppColors.color4, width: 2.sp)),
    ),
    child: TabBar(
        ...
    ),
),

希望您能得到帮助。


3
投票

我设法使用'flexibleSpace'属性而不是'bottom'属性来做到这一点,因为flexibleSpace可以有任何小部件,而不仅仅是像bottom这样的'PreferredSizeWidget'。

所以我给了flexibleSpace一个列,然后我能够将TabBar和容器放入该列中,然后使用Matrix4.translationValues(0.0, -2.6, 0.0)我给了包含边框的容器,一个负数-填充(或类似),因此它移动到指标颜色的顶部。

return SafeArea(
  top: true,
  child: Scaffold(
    appBar: PreferredSize(
      preferredSize: Size.fromHeight(100.0),
      child: AppBar(
        backgroundColor: Theme.of(context).buttonColor,
        title: Text(
          'AppBar',
          textAlign: TextAlign.center,
          style: Theme.of(context).textTheme.title,
        ),
        centerTitle: true,
        elevation: 0.0,
        flexibleSpace: Padding(
          padding: const EdgeInsets.only(top: 50.0),
          child: Column(
            children: <Widget>[
              // Tab Bar
              new TabBar(
                indicatorColor: Theme.of(context).accentColor,
                tabs: <Tab>[
                  new Tab(
                    text: 'Tab1',
                  ),
                  new Tab(
                    text: 'Tab2',
                  ),
                ],
                controller: _tabController,
              ),
              // Border
              Container(
                // Negative padding
                transform: Matrix4.translationValues(0.0, -2.6, 0.0),
                // Add top border
                decoration: BoxDecoration(
                   border: Border(
                     top: BorderSide(
                        color: Color(0xFFc3c3c3),
                        width: 0.6,
                     ),
                   ),
                ),
              ),
            ],
          ),
        ),
      ),
    ),
    body: new TabBarView(
      children: <Widget>[
        new Tab1(),
        new Tab2(),
      ],
      controller: _tabController,
    ),
  ),
);

奇迹发生了^^


3
投票

另一种方法是使用堆栈并将该行放置在选项卡下方

               Stack(
                  alignment: Alignment.bottomCenter,
                  children: [
                    Container(
                      decoration: BoxDecoration(
                          border: Border(
                        bottom: BorderSide(color: Colors.white70, width: 1),
                      )),
                    ),
                    TabBar(
                      indicatorWeight: 3.0,
                      tabs: [
                        Tab(
                          icon: Icon(Icons.home),
                        ),
                        Tab(
                          icon: Icon(Icons.show_chart),
                        ),
                      ],
                    ),
                  ],
                ),

1
投票

这是我的 spenster 解决方案的版本

我创建了一个新的小部件“BorderedTab”,它实现了 Tab:而不是函数:

import 'package:flutter/material.dart';

class BorderedTab extends StatelessWidget implements Tab {
  const BorderedTab({
    Key key,
    this.text,
    this.borderColor=Colors.grey,
    this.width=0.5,
  }) : super(key: key);

  final String text;
  final Color borderColor;
  final double width;

  @override
  Widget build(BuildContext context) {
    return Tab(
      child: Row(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Expanded(
                child: Container(
                    child: Center(
                        child: Text(text)
                    ),
                    decoration: BoxDecoration(
                        border: Border(
                            bottom: BorderSide(
                                width: width,
                                color: borderColor,
                            ),
                        ),
                    ),
                ),
            ),
          ]
      ),
    );
  }

  @override
  // TODO: implement child
  Widget get child => null;

  @override
  // TODO: implement icon
  Widget get icon => null;
}

然后我像常规 Tab 一样使用 BorderedTab,但使用:

labelPadding: EdgeInsets.all(0.0), // Important to remove default padding

最终应用栏:

import 'package:../widgets/bordered_tab.dart';

...

appBar: AppBar(
  backgroundColor: Theme.of(context).buttonColor,
  title: Text(
    'TabBar',
    textAlign: TextAlign.center,
    style: Theme.of(context).textTheme.title,
  ),
  centerTitle: true,
  elevation: 0.0,
  bottom: new TabBar(
    labelColor: Theme.of(context).primaryColor,
    indicatorColor:Theme.of(context).accentColor,
    labelPadding: EdgeInsets.all(0.0), // Important to remove default padding
    tabs: <Tab>[
      BorderedTab(
        text: 'Tab1',
        borderColor: Color(0xFFc3c3c3),
      ),
      BorderedTab(
        text: 'Tab2',
        borderColor: Color(0xFFc3c3),
      ),
    ],
    controller: _tabController,
  ),
),

1
投票

我想添加一个答案

所有答案都有一个问题,就是底线要么高于指标,要么低于指标,而且高度也很难控制。

嗯。这是 flutter 3 中的工作版本

                  PreferredSize(
                    preferredSize: Size.fromHeight(kToolbarHeight),
                    child: DecoratedBox(
                      decoration: BoxDecoration(
                        border: Border(
                          bottom: BorderSide(
                            color: AppColors.border,
                            width: 3,
                          ),
                        ),
                      ),
                      child: TabBar(
                        labelColor: AppColors.secondText,
                        unselectedLabelColor: AppColors.grayText,
                        indicator: UnderlineTabIndicator(
                          borderSide: BorderSide(
                              width: 3.0, color: AppColors.secondText),
                          insets: EdgeInsets.symmetric(horizontal: 30.0),
                        ),
                        tabs: [
                          Tab(
                            text: "Tab 1",
                          ),
                          Tab(
                            text: "Tab 2",
                          ),
                        ],
                      ),
                    ),
                  ),
    

0
投票

使用 DecoratedBox 和 PreferredSize

首先将 TabBar 放入 PreferredSize :

child: AppBar(
      bottom: PreferredSize(
        preferredSize: Size.fromHeight(50),
        child: TabBar(
          tabs: [
            Tab(
              text: 'tab-1',
            ),
            Tab(
              text: 'tab-2',
            ),
            Tab(
              text: 'tab-3',
            ),
          ],
        ),
      ),
    ),

然后用 DecoratedBox 包裹 TabBar

child: AppBar(
      bottom: PreferredSize(
        preferredSize: Size.fromHeight(50),
        child: DecoratedBox(
          decoration: BoxDecoration(
            border: Border(bottom: BorderSide(width: 2,color: Color.fromARGB(255, 255, 0, 0)))
          ),
          child: TabBar(
            tabs: [
              Tab(
                text: 'tab-1',
              ),
              Tab(
                text: 'tab-2',
              ),
              Tab(
                text: 'tab-3',
              ),
            ],
          ),
        ),
      ),
    ),

0
投票

不使用其他元素的最简单方法是将 BoxShadow 与 TabBar 一起使用,如下所示:

TabBar(
                        controller: _tabController,
                        indicator: BoxDecoration(
                                                 boxShadow: [
                            BoxShadow(
                              color: Colors.red,                         
                              offset: Offset(0, 2.0),
                            )
                          ],
                        
                          color: Colors.white,
                        ),
                        labelColor: Colors.red,
                        unselectedLabelColor: Colors.grey.shade900,
                        labelPadding: EdgeInsets.symmetric(horizontal: 10.0),
                        isScrollable: false,
                        tabs: [
                          Tab(
                            text: 'T1',
                          ),
                          Tab(
                            text: 'T2',
                          ),
                          Tab(
                            text: 'T3',
                          ),
                          Tab(
                            text: 'T4',
                          ),
                        ],
                      ),

或者使用UnderlineTabIndicator作为TabBar的指示参数:

indicator: UnderlineTabIndicator(
                  borderSide: BorderSide(width: 3.0),
                  insets: EdgeInsets.symmetric(horizontal: 30.0),
                ),

0
投票

您可以使用

TabBar
dividerColor
属性。

© www.soinside.com 2019 - 2024. All rights reserved.