Skip to main content

FluiKit Tabs

import 'package:flutter/material.dart';

class FluiKitTabview extends StatefulWidget {
  final List<FluiKitTabItem> tabs;
  final ValueChanged<int> onTabChanged;
  final TabViewDesign design;
  final int initialIndex;
  final int minTabs;

  FluiKitTabview({
    super.key,
    required this.tabs,
    required this.onTabChanged,
    required this.design,
    required this.minTabs,
    this.initialIndex = 0,
  }) {
    assert(
    tabs.length >= minTabs,
    'At least $minTabs tab(s) are required, but got ${tabs.length}.',
    );
  }

  @override
  State<FluiKitTabview> createState() => _FluiKitTabviewState();
}

class FluiKitTabItem {
  final String label;
  final Widget child;
  const FluiKitTabItem({required this.label, required this.child});
}

class TabViewDesign {
  final Color backgroundColor;
  final Color indicatorColor;
  final double indicatorHeight;
  final EdgeInsets tabPadding;
  final EdgeInsets margin;
  final TextStyle labelStyle;
  final TextStyle selectedLabelStyle;

  const TabViewDesign({
    this.backgroundColor = Colors.transparent,
    this.indicatorColor = Colors.blue,
    this.indicatorHeight = 2.0,
    this.tabPadding = const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
    this.margin = EdgeInsets.zero,
    this.labelStyle = const TextStyle(fontSize: 16, color: Colors.black),
    this.selectedLabelStyle = const TextStyle(
      fontSize: 16,
      fontWeight: FontWeight.bold,
      color: Colors.blue,
    ),
  });
}

class _FluiKitTabviewState extends State<FluiKitTabview> {
  late int _selectedIndex;

  @override
  void initState() {
    super.initState();
    _selectedIndex = widget.initialIndex;
  }

  @override
  Widget build(BuildContext context) {
    final design = widget.design;

    return Container(
      margin: design.margin,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(8),
        color: design.backgroundColor,
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withAlpha(10),
            blurRadius: 10,
            offset: Offset(2, 4),
          ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children:
                widget.tabs.asMap().entries.map((entry) {
                  final index = entry.key;
                  final tab = entry.value;
                  final isSelected = _selectedIndex == index;
                  return GestureDetector(
                    onTap: () {
                      setState(() {
                        _selectedIndex = index;
                        widget.onTabChanged(index);
                      });
                    },
                    child: Container(
                      padding: design.tabPadding,
                      decoration: BoxDecoration(
                        border: Border(
                          bottom:
                              isSelected
                                  ? BorderSide(
                                    color: design.indicatorColor,
                                    width: design.indicatorHeight,
                                  )
                                  : BorderSide.none,
                        ),
                      ),
                      child: AnimatedDefaultTextStyle(
                        duration: const Duration(milliseconds: 200),
                        style:
                            isSelected
                                ? design.selectedLabelStyle
                                : design.labelStyle,
                        child: Text(tab.label),
                      ),
                    ),
                  );
                }).toList(),
          ),
          // Content Area
          Expanded(
            child: IndexedStack(
              index: _selectedIndex,
              children:
                  widget.tabs
                      .map(
                        (tab) => Container(
                          margin: EdgeInsets.all(8),
                          child: tab.child,
                        ),
                      )
                      .toList(),
            ),
          ),
        ],
      ),
    );
  }
}

Content Widgets

Column(
              children: [
                SizedBox(
                  width: MediaQuery.of(context).size.width,
                  height: 300,
                  child: FluiKitTabview(
                    minTabs: 3, // Amount of Tabs
                    tabs: [
                      const FluiKitTabItem(
                        label: 'Tab 1',
                        child: TabItem1Content(),
                      ),
                      const FluiKitTabItem(
                        label: 'Tab 2',
                        child: TabItem2Content(),
                      ),
                      const FluiKitTabItem(
                        label: 'Tab 3',
                        child: TabItem3Content(),
                      ),
                    ],
                    onTabChanged: (index) {
                      //
                    },
                    design: TabViewDesign(
                      backgroundColor:
                          Theme.of(context).brightness == Brightness.light
                              ? Colors.grey.withAlpha(30)
                              : Colors.black26,
                      indicatorColor: AppSettings.appPrimaryColor,
                      indicatorHeight: 3,
                      tabPadding: EdgeInsets.symmetric(
                        horizontal: 24,
                        vertical: 12,
                      ),
                      margin: EdgeInsets.all(Insets.medium),
                      labelStyle: TextStyle(fontSize: 18, color: Colors.grey),
                      selectedLabelStyle: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                        color: AppSettings.appPrimaryColor,
                      ),
                    ),
                  ),
                ),
              ],
            )
import 'package:flutter/material.dart';

class TabItem1Content extends StatelessWidget {
  const TabItem1Content({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      Text(
        'Content for Tab 1',
        style: TextStyle(fontSize: 20),
      ),
      Text(
        'Lorem ipsum dolor sit amet. Vel eaque dolores non praesentium consectetur aut exercitationem sint et quia odit. Quo sequi reiciendis qui porro quibusdam sed corporis alias aut odit blanditiis et perspiciatis delectus in ullam inventore a natus voluptates.'
      )
    ]);
  }
}
import 'package:flutter/material.dart';

class TabItem2Content extends StatelessWidget {
  const TabItem2Content({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      Text(
        'Content for Tab 2',
        style: TextStyle(fontSize: 20),
      ),
      Text(
          'Sed sint perspiciatis ut quibusdam dolorem rem consequuntur ipsum et assumenda fugit. Sed corporis expedita ut error harum et neque quidem et voluptates voluptatem vel voluptatem quia qui suscipit perspiciatis.'
      )
    ]);
  }
}
class TabItem3Content extends StatelessWidget {
  const TabItem3Content({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      Text(
        'Content for Tab 3',
        style: TextStyle(fontSize: 20),
      ),
      Text(
          'Est dolorem explicabo et deserunt facere est assumenda quia qui esse quidem. Non odit fugiat ad perspiciatis delectus id eveniet ducimus et accusantium molestiae?'
      )
    ]);
  }
}
Looking for a Joomla Webdeveloper or a Flutter App Developer?
Whether you need a new business website, an e-commerce store, or a mobile application, we are here to help. Let’s bring your idea to life!
Ghekko | Webdeveloper and Application Developer
Ghekko The Netherlands
Willem Buytewechstraat 187 C
3024 XH, Rotterdam, Zuid Holland
Ghekko | Webdeveloper and Application Developer
Ghekko Spain
Plaza Alquibla 12 A
03390, Benejúzar, Alicante
Copyrights © Ghekko. All rights reserved.