convex_bottom_bar icon indicating copy to clipboard operation
convex_bottom_bar copied to clipboard

How to make tabBar item responsive?

Open NTMS2017 opened this issue 4 years ago • 6 comments

Hi,

With a custom appear sample I try to make tabBar item responsive but seems margin and StyleHook is not allow me to make a more responsive.

For my app I use flutter_screenutil and auto_size_text plugin for responsive ui design. But can't make to work with tabor item.

Without modification (still not work as expected) the appear item looks too small on iPad mini4. With current modification image is below.

Also I couldn't find any "tabContent" example and usage in your example apps. It looks If I can modify tabContent I might be able to make tabor items more responsive.

Any idea?

Note: In main.dart I use ScreenUtilInit(designSize: Size(360, 690),... for my design draft. I can change a different UI draft but output still same.

import 'package:auto_size_text/auto_size_text.dart';
import 'package:convex_bottom_bar/convex_bottom_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:ntms_test_app/PageC.dart';
import 'package:ntms_test_app/pageA.dart';
import 'package:ntms_test_app/pageB.dart';

double myWidth;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await SystemChrome.setEnabledSystemUIOverlays([]);
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
        designSize: Size(360, 690),
        allowFontScaling: true,
        builder: () => MaterialApp(
            debugShowCheckedModeBanner: false,
            title: 'Flutter Demo',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: HomePage()));
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  int _currentIndex = 0;
  List<Color> _myColors = [Colors.green, Colors.red, Colors.blue];

  List<TabItem> items = <TabItem>[
    TabItem(icon: Icons.home, title: 'Home'),
    TabItem(icon: Icons.map, title: 'Discovery'),
    TabItem(icon: Icons.plus_one, title: 'Add'),
  ];

  Color pageColor;

  List<Widget> listWidgets = [PageA(myColor: Colors.green), PageB(myColor: Colors.red), PageC(myColor: Colors.blue)];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    myWidth = MediaQuery.of(context).size.width;
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: AutoSizeText(
          'Custom ConvexAppBar',
          style: TextStyle(color: Colors.black, fontSize: 18.0.ssp),
        ),
        backgroundColor: _myColors[_currentIndex],
      ),
      body: listWidgets[_currentIndex],
      bottomNavigationBar: StyleProvider(
        style: Style(),
        child: ConvexAppBar(
          disableDefaultTabController: false,
          height: MediaQuery.of(context).size.width > 360 ? 70 : 50,
          top: MediaQuery.of(context).size.width > 360 ? -60 : -30,
          curveSize: MediaQuery.of(context).size.width > 360 ? 100 : 75,
          style: TabStyle.react,
          items: [
            TabItem(
              title: '2019',
              icon: Icon(
                Icons.link,
                color: _myColors[0],
                size: MediaQuery.of(context).size.width > 360 ? 40 : 20,
              ),
            ),
            TabItem(
                title: '2020',
                icon: Icon(
                  Icons.contact_page,
                  color: _myColors[1],
                  size: MediaQuery.of(context).size.width > 360 ? 40 : 20,
                )),
            TabItem(
                title: "2021",
                icon: Icon(
                  Icons.work,
                  color: _myColors[2],
                  size: MediaQuery.of(context).size.width > 360 ? 40 : 20,
                )),
          ],
          backgroundColor: Colors.yellow,
          activeColor: Colors.red,
          color: Colors.black,
          onTap: (i) {
            debugPrint('click $i');
            setState(() {
              _currentIndex = i;
              pageColor = _myColors[i];
            });
          },
        ),
      ),
    );
  }
}

/// CLASS STYLE
class Style extends StyleHook {
  @override
  double get activeIconSize => 40;

  @override
  double get activeIconMargin => 10;

  @override
  double get iconSize => 20;

  @override
  TextStyle textStyle(Color color) {
    return TextStyle(fontSize: 20.0.ssp);
  }
}
Screenshot 2021-03-27 at 13 48 20

NTMS2017 avatar Mar 27 '21 11:03 NTMS2017

This is best I can make it to responsive. But for iPad the icon size is not changing.

SDK:

environment:
  sdk: ">=2.7.0 <3.0.0"

Plugin:

  cupertino_icons: ^1.0.2
  flutter_screenutil: ^5.0.0-nullsafety.11
  auto_size_text: ^3.0.0-nullsafety.0
  convex_bottom_bar: ^3.0.0

CODE:

import 'package:auto_size_text/auto_size_text.dart';
import 'package:convex_bottom_bar/convex_bottom_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:ntms_test_app/PageC.dart';
import 'package:ntms_test_app/pageA.dart';
import 'package:ntms_test_app/pageB.dart';

double myWidth;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await SystemChrome.setEnabledSystemUIOverlays([]);
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
        designSize: Size(360, 690),
        allowFontScaling: true,
        builder: () => MaterialApp(
            debugShowCheckedModeBanner: false,
            title: 'Flutter Demo',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: HomePage()));
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  int _currentIndex = 0;
  List<Color> _myColors = [Colors.green, Colors.red, Colors.blue];

  List<TabItem> items = <TabItem>[
    TabItem(icon: Icons.home, title: 'Home'),
    TabItem(icon: Icons.map, title: 'Discovery'),
    TabItem(icon: Icons.plus_one, title: 'Add'),
  ];

  Color pageColor;

  List<Widget> listWidgets = [PageA(myColor: Colors.green), PageB(myColor: Colors.red), PageC(myColor: Colors.blue)];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    myWidth = 1.sw;
    print("WIDTH: $myWidth");
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: AutoSizeText(
          'Custom ConvexAppBar',
          style: TextStyle(color: Colors.black, fontSize: 18.0.ssp),
        ),
        backgroundColor: _myColors[_currentIndex],
      ),
      body: listWidgets[_currentIndex],
      bottomNavigationBar: StyleProvider(
        style: Style(),
        child: ConvexAppBar(
          disableDefaultTabController: true,
          height: myWidth > 320 ? 70 : 50,
          top: myWidth > 320 ? -50 : -30,
          curveSize: myWidth > 320 ? 150 : 100,
          style: TabStyle.react,
          items: [
            TabItem(
              title: '2019',
              icon: Icon(
                Icons.link,
                color: _myColors[0],
              ),
            ),
            TabItem(
                title: '2020',
                icon: Icon(
                  Icons.contact_page,
                  color: _myColors[1],
                )),
            TabItem(
                title: "2021",
                icon: Icon(
                  Icons.work,
                  color: _myColors[2],
                )),
          ],
          backgroundColor: Colors.yellow,
          activeColor: Colors.red,
          color: Colors.black,
          onTap: (i) {
            debugPrint('click $i');
            setState(() {
              _currentIndex = i;
              pageColor = _myColors[i];
            });
          },
        ),
      ),
    );
  }
}

/// CLASS STYLE
class Style extends StyleHook {
  @override
  double get activeIconSize => myWidth > 320 ? 70 : 40;

  @override
  double get activeIconMargin => myWidth > 320 ? 15 : 10;

  @override
  double get iconSize => myWidth > 320 ? 35.ssp : 25.ssp;

  @override
  TextStyle textStyle(Color color) {
    return TextStyle(fontSize: myWidth > 320 ? 18.0.ssp : 16.0.ssp, fontWeight: FontWeight.bold);
  }
}

listWidgets A

import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

/// PAGE A
class PageA extends StatefulWidget {
  final Color myColor;

  const PageA({Key key, this.myColor}) : super(key: key);

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

class _PageAState extends State<PageA> {
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          Center(
              child: AutoSizeText(
            'Entry A',
            style: TextStyle(fontSize: 20.0.ssp, fontWeight: FontWeight.bold, color: widget.myColor),
          )),
        ],
      ),
    );
  }
}

IMAGE: Screenshot 2021-03-28 at 09 58 34

NTMS2017 avatar Mar 28 '21 06:03 NTMS2017

@NTMS2017 The default example look fine on iPad mini4, so are you trying to make icon bigger on iPad? One more thing, I would suggest you ti provide two different style class, such as StyleIPad, StlyePhone to simplify the hook.

/// CLASS STYLE
class Style2 extends StyleHook {
  @override
  double get activeIconSize => 40 ;

  @override
  double get activeIconMargin => 5;

  @override
  double get iconSize => 50;

  @override
  TextStyle textStyle(Color color) {
    return TextStyle(fontSize: 12.0, fontWeight: FontWeight.bold);
  }
}
Screen Shot 2021-04-06 at 11 27 14

The style feature is limited. So if you can not make the tab to satisfy your case, you can make a custom one with other constructor, which allow you to define the tab by yourself.

  /// Define a custom tab style by implement a [DelegateBuilder].
  ///
  /// ```dart
  /// ConvexAppBar(
  ///   count: 5,
  ///   itemBuilder: Builder(),
  /// )
  ///
  /// class Builder extends DelegateBuilder {
  ///   @override
  ///   Widget build(BuildContext context, int index, bool active) {
  ///     return Text('TAB $index');
  ///   }
  /// }
  /// ```
  const ConvexAppBar.builder({
    Key? key,
    required this.itemBuilder,
    required this.count,
    this.initialActiveIndex,
    this.disableDefaultTabController = false,
    this.onTap,
    this.onTapNotify,
    this.controller,
    this.backgroundColor,
    this.gradient,
    this.height,
    this.curveSize,
    this.top,
    this.elevation,
    this.cornerRadius,
    this.curve = Curves.easeInOut,
    this.chipBuilder,
  }) 

avenwu avatar Apr 06 '21 02:04 avenwu

Yes I am trying to make icon bigger on iPad. I will try your suggestion to make 2 different style. And write here the result

NTMS2017 avatar Apr 06 '21 04:04 NTMS2017

Sorry :( couldn't make it. Do you have any custom (Define a custom tab style by implement a [DelegateBuilder].) example? If you can provide I will appreciated. Thanks

NTMS2017 avatar Apr 06 '21 06:04 NTMS2017

Checkout https://github.com/hacktons/convex_bottom_bar#custom-example

avenwu avatar Apr 06 '21 06:04 avenwu

@avenwu you are saying there you can customize everything, yes you are right.. but alsmot from scratch because you are not exposing things like TransitionContainer. and similar.

vytautas-pranskunas- avatar Sep 22 '23 06:09 vytautas-pranskunas-