Home > Net >  How to implement a Sliver App Bar with Tabs & other widgets above Tabs?
How to implement a Sliver App Bar with Tabs & other widgets above Tabs?

Time:08-29

How to implement a SliverAppBar with Tabs & Widgets above Tabs?

How to create a SliverAppBar like Talabat App:

Please, check the below - video.

  • How to solve it?

  • What can I do?

  • I am doing...

https://youtube.com/shorts/HeuOTpdRZYY

I tried the below code:

=========================================================

    class HomeScreen extends StatelessWidget {
      const HomeScreen({Key? key}) : super(key: key);

      @override
      Widget build(BuildContext context) {
        var textTheme = Theme.of(context).textTheme;
        // return Scaffold(
        //   body: NestedScrollView(
        //     headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        //       return <Widget>[
        //         const SliverAppBar(
        //           backgroundColor: Colors.red,
        //           flexibleSpace: FlexibleSpaceBar(),
        //         )
        //       ];
        //     },
        //     body: Container(
        //       child: Builder(builder: (context) {
        //         return Column(
        //             mainAxisAlignment: MainAxisAlignment.start, children: const []);
        //       }),
        //     ),
        //   ),
        // );

        return Scaffold(
          body: CustomScrollView(
            slivers: [
              SliverAppBar(
                pinned: true,
                expandedHeight: 500,
                toolbarHeight: AppSize.s60,
                collapsedHeight: 200,
                leading: GestureDetector(
                  onTap: () {},
                  child: Center(
                    child: Container(
                      width: AppSize.s50,
                      height: AppSize.s44,
                      decoration: const BoxDecoration(
                        color: Palette.kPrimaryColor,
                        borderRadius: BorderRadius.all(
                          Radius.circular(AppSize.s10),
                        ),
                      ),
                      child: Center(
                        child: SvgPicture.asset(
                          AppAssets.menu,
                          height: AppSize.s14,
                        ),
                      ),
                    ),
                  ),
                ),
                title: const Text(
                  "FASDFASD F",
                  style: TextStyle(
                    color: Colors.black,
                  ),
                ),
                actions: [
                  const SizedBox(width: AppSize.s10),
                  IconButton(
                    onPressed: () {},
                    splashRadius: AppSize.s28,
                    icon: SvgPicture.asset(
                      AppAssets.shoppingCart,
                      height: AppSize.s32,
                    ),
                  ),
                ],
                flexibleSpace: Container(
                  color: Colors.deepOrange,
                  // height: 250,
                  child: Column(
                    children: [
                      Container(
                        height: 100,
                        color: Colors.green,
                        margin: const EdgeInsets.all(10),
                      ),
                      Container(
                        height: 100,
                        color: Colors.black,
                        margin: const EdgeInsets.all(10),
                      ),
                      Container(
                        height: 100,
                        color: Colors.black26,
                        margin: const EdgeInsets.all(10),
                      ),
                      Container(
                        height: 100,
                        color: Colors.black45,
                        margin: const EdgeInsets.all(10),
                      ),
                      Container(
                        height: 120,
                        color: Colors.blueGrey,
                      ),
                    ],
                  ),
                ),
                bottom: const CustomAppBarBottom(),
                backgroundColor: Palette.kWhiteColor,
              ),
              SliverToBoxAdapter(
                child: Column(
                  children: [
                    Container(
                      height: 100,
                      color: Colors.green,
                      margin: const EdgeInsets.all(10),
                    ),
                    Container(
                      height: 100,
                      color: Colors.purple,
                      margin: const EdgeInsets.all(10),
                    ),
                    Container(
                      height: 100,
                      color: Colors.purple,
                      margin: const EdgeInsets.all(10),
                    ),
                    Container(
                      height: 100,
                      color: Colors.green,
                      margin: const EdgeInsets.all(10),
                    ),
                    Container(
                      height: 100,
                      color: Colors.purple,
                      margin: const EdgeInsets.all(10),
                    ),
                    Container(
                      height: 100,
                      color: Colors.purple,
                      margin: const EdgeInsets.all(10),
                    ),
                    Container(
                      height: 100,
                      color: Colors.green,
                      margin: const EdgeInsets.all(10),
                    ),
                    Container(
                      height: 100,
                      color: Colors.purple,
                      margin: const EdgeInsets.all(10),
                    ),
                    Container(
                      height: 100,
                      color: Colors.green,
                      margin: const EdgeInsets.all(10),
                    ),
                    Container(
                      height: 100,
                      color: Colors.black87,
                      margin: const EdgeInsets.all(10),
                    ),
                  ],
                ),
              ),
            ],
          ),
        );
      }
    }

    class CustomAppBarBottom extends StatelessWidget
        implements PreferredSizeWidget {
      const CustomAppBarBottom({Key? key}) : super(key: key);

      @override
      Widget build(BuildContext context) {
        var outlineInputBorder = OutlineInputBorder(
          borderRadius: AppRadius.bottomRadius,
          borderSide: BorderSide.none,
        );
        return Container(
          margin: EdgeInsets.symmetric(
            horizontal: getUIPadding(context),
            vertical: 10,
          ),
          decoration: BoxDecoration(
            color: Palette.kWhiteColor,
            borderRadius: AppRadius.bottomRadius,
            boxShadow: const [
              BoxShadow(
                color: Color.fromARGB(20, 0, 0, 0),
                blurRadius: 7,
              )
            ],
          ),
          child: TextFormField(
            style: const TextStyle(
              height: 1.2,
            ),
            decoration: InputDecoration(
              hintText: "عن ماذا تبحث؟",
              hintStyle: const TextStyle(
                color: Palette.onboardingDescriptionColor,
              ),
              prefixIcon: Align(
                // alignment: Alignment.centerRight,
                widthFactor: 1.0,
                child: SvgPicture.asset(
                  AppAssets.search,
                  width: AppSize.s25,
                ),
              ),
              isDense: true,
              border: outlineInputBorder,
              errorBorder: outlineInputBorder,
              enabledBorder: outlineInputBorder,
              focusedBorder: outlineInputBorder,
              disabledBorder: outlineInputBorder,
              focusedErrorBorder: outlineInputBorder,
            ),
          ),
        );
      }

      @override
      Size get preferredSize => const Size.fromHeight(AppSize.s60);
    }

CodePudding user response:

This widget give you some sample idea, Also check SliverPersistentHeader for custom header. You can check sliver_tools package for pinned header. Also TabBar can be replace with scroll_to_index.

class TestWidget extends StatefulWidget {
  const TestWidget({Key? key}) : super(key: key);

  @override
  State<TestWidget> createState() => _TestWidgetState();
}

class _TestWidgetState extends State<TestWidget>
    with SingleTickerProviderStateMixin {
  late final TabController tabController =
      TabController(length: 10, vsync: this);

  double itemHeight = 120;

  double? appBarHeight;
 late final ScrollController controller = ScrollController()
    ..addListener(() {
      if (controller.hasClients) {
        final moveTo =
            ((controller.offset - appBarHeight!) / itemHeight).toInt();

        tabController.animateTo(moveTo < 0 ? 0 : moveTo);
        setState(() {});
      }
    });
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: LayoutBuilder(builder: (context, constraints) {
        appBarHeight ??= constraints.maxHeight;

        return CustomScrollView(
          controller: controller,
          slivers: [
            SliverAppBar(
              pinned: true,
              expandedHeight: constraints.maxHeight * .7,
              bottom: PreferredSize(
                child: TabBar(
                  controller: tabController,
                  tabs: List.generate(
                      10,
                      (index) => Container(
                            width: 100,
                            height: 40,
                            alignment: Alignment.center,
                            color: index == tabController.index
                                ? Colors.deepOrange
                                : Colors.cyanAccent,
                            child: Text("$index"),
                          )),
                ),
                preferredSize: Size.fromHeight(kToolbarHeight),
              ),
            ),
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, index) {
                  return Container(
                    height: itemHeight,
                    color: index.isEven ? Colors.green : Colors.pink,
                    width: constraints.maxWidth,
                  );
                },
              ),
            )
          ],
        );
      }),
    );
  }
}

CodePudding user response:

I want to add some widgets above TabBar and show TabBar only on top (On scrolling).

Error after adding some widgets above TabBar

  • Related