DOGGA Nidhal
DOGGA Nidhal

Reputation: 53

how to set CupertinoSegmentedControl height?

I am trying to use CupertinoSegmentedControl from the flutter Cupertino library in the AppBar using the bottom attribute to achieve the following design (height = 32)

cupertino segmented control

so I tried the following :

@override
    Widget build(BuildContext context) {
        return Scaffold(
                appBar: AppBar(
                    elevation: 2,
                    backgroundColor: Colors.white,
                    centerTitle: true,
                    title: Text(this.widget.title, style: TextStyle(color: Colors.black)),
                    bottom: PreferredSize(
        child: Padding(
          padding: const  EdgeInsets.only(top: 8, bottom: 12),
          child: Row(
            children: <Widget>[
              SizedBox(width: 24),
              Expanded(
                child: CupertinoSegmentedControl(
                  children: this.widget.tabs,
                  groupValue: this._selectedTab,
                  onValueChanged: (value) {
                    this.setState(() => this._selectedTab = value);
                    this._tabController.animateTo(value);
                  }
                ),
              ),
              SizedBox(width: 24)
            ],
          ),
        ),
        preferredSize: Size(double.infinity, 48)
      )
                ),
                body: new TabBarView(
                    controller: this._tabController,
                    children: this.widget.views,
                ));
    } 

Upvotes: 5

Views: 10918

Answers (3)

Johnny
Johnny

Reputation: 1964

Here is full example based on @shadowsheep 's answer but improve version.

my_cupertino_segmented_control.dart

class MyCupertinoSegmentedControl extends StatelessWidget {
  final Map<int, Widget> children;
  final int? groupValue;
  final Function(int)? onValueChanged;

  const MyCupertinoSegmentedControl(
      {required this.children,
      this.groupValue,
      this.onValueChanged,
      super.key});

  @override
  Widget build(BuildContext context) {
    return PreferredSize(
        preferredSize: const Size(double.infinity, 48),
        child: Padding(
          padding: const EdgeInsets.only(top: 8, bottom: 12),
          child: Row(
            children: <Widget>[
              const SizedBox(width: 24),
              Expanded(
                child: CupertinoSegmentedControl<int>(
                    children: children,
                    groupValue: groupValue,
                    onValueChanged: (value) {
                      onValueChanged?.call(value);
                    }),
              ),
              const SizedBox(width: 24)
            ],
          ),
        ));
  }
}

It wrapped the annoying details to a simple widgets.

example.dart

import 'package:flutter/cupertino.dart';
import 'package:my_project/views/my_cupertino_segmented_control.dart';

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

  @override
  Widget build(BuildContext context) {
    return const CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('Segmented Control Example'),
      ),
      child: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

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

class HomePageState extends State<HomePage> {
  Map<int, Widget> segmentedWidgets = {};
  List<Widget> tabWidgets = [];
  int selectedIndex = 0;

  @override
  void initState() {
    super.initState();
    _loadSegmentedWidgets();
    _loadTabWidgets(); //Method to add the Children as user selected.
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
        children: <Widget>[
          MyCupertinoSegmentedControl(
              children: segmentedWidgets,
              groupValue: selectedIndex,
              onValueChanged: (value) {
                setState(() {
                  selectedIndex = value;
                });
              }),
          tabWidgets[selectedIndex],
        ],
      ),
    );
  }

  void _loadSegmentedWidgets() {
    for (int i = 0; i < 4; i++) {
      segmentedWidgets[i] = Padding(
        padding: const EdgeInsets.all(8.0),
        child: Text("Tab ${i + 1}"),
      );
    }
  }

  void _loadTabWidgets() {
    for (int i = 0; i < 4; i++) {
      tabWidgets.add(
        Center(
          child: Text("Detail ${i + 1}"),
        ),
      );
    }
  }
}

It's initialize the CupertinoPageScaffold and 4 tabs with tab details.

Here's preview

preview

Upvotes: 0

kazimad
kazimad

Reputation: 954

just add Padding widget, or margin property to Container and wrap your Widgets in your "tabs" collection (in you case it is this.widget.tabs) with it

in my case

CupertinoSegmentedControl<int>(
            children: segmentTextWidgets,
            ...
          ),


final Map<int, Widget> segmentTextWidgets = <int, Widget>{
    0: Container(
      margin: const EdgeInsets.symmetric(vertical: 16),
      child: Text("Tab 1 title"),
    ),
    1: Container(
      margin: const EdgeInsets.symmetric(vertical: 16),
      child: Text("Tab 2 title"),
    ),
  };

Upvotes: 5

shadowsheep
shadowsheep

Reputation: 15002

Is something like that similar to the layout that you want? (Removing the green color of course ^_^)

Play around with the Container and PreferredSize heights to adjust the height to fit your needs.

enter image description here

Scaffold(
    appBar: AppBar(
        elevation: 2,
        backgroundColor: Colors.white,
        centerTitle: true,
        title:
            Text(this.widget.title, style: TextStyle(color: Colors.black)),
        bottom: PreferredSize(
            child: Row(
              children: [
                Expanded(
                  child: Container(
                    height: 48,
                    color: Colors.lightGreenAccent,
                    child: CupertinoSegmentedControl(
                        children: children,
                        groupValue: this._selectedTab,
                        onValueChanged: (value) {
                          this.setState(() => this._selectedTab = value);
                        }),
                  ),
                )
              ],
            ),
            preferredSize: Size(double.infinity, 48))),
    body: Center(
        child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text('hello')
        ]
        )
    )
);

UPDATE:

enter image description here

As kazimad pointed out, if you want to increase the segmented control height and not only add padding to it insiede the app bar, you can add a Padding widget to your tabs, like that:

@override
Widget build(BuildContext context) {
  return Scaffold(
      appBar: AppBar(
          elevation: 2,
          backgroundColor: Colors.white,
          centerTitle: true,
          title:
              Text(this.widget.title, style: TextStyle(color: Colors.black)),
          bottom: PreferredSize(
              child: Padding(
                padding: const EdgeInsets.only(top: 8, bottom: 12),
                child: Row(
                  children: <Widget>[
                    SizedBox(width: 24),
                    Expanded(
                      child: CupertinoSegmentedControl(
                          children: const <int, Widget>{
                            0: Padding(
                                padding: EdgeInsets.all(8.0),
                                child: Text('Midnight')),
                            1: Padding(
                                padding: EdgeInsets.all(8.0),
                                child: Text('Viridian')),
                            2: Padding(
                                padding: EdgeInsets.all(8.0),
                                child: Text('Cerulean'))
                          },
                          groupValue: this._selectedTab,
                          onValueChanged: (value) {
                            // TODO: - fix it
                          }),
                    ),
                    SizedBox(width: 24)
                  ],
                ),
              ),
              preferredSize: Size(double.infinity, 48))),
      body: Center(
          child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [Text('hello')])));
}

Upvotes: 6

Related Questions