Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter Listview swipe to change TabBar index

Tags:

flutter

dart

I have implemented TabBar without TabBarView. I am using a single ListView as body since the layout after selecting a tab is same for all tabs.

What I want to achieve is, change the tab while swiping left / right in the listview. How can I do this?

TabBar

TabBar(
        indicatorWeight: 3,
        indicatorSize: TabBarIndicatorSize.label,
        onTap: (index) {
          categoryId = newsProvider.categories[index].id;
          page = 1;
          fetchPosts(newsProvider);
        },
        isScrollable: true,
        tabs: [
          for (Category category in newsProvider.categories)
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
              child: Text(
                category.name,
                style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
              ),
            ),
        ],
      ),

body

ListView.builder(
                    padding: EdgeInsets.only(bottom: 60),
                    physics: BouncingScrollPhysics(),
                    controller: _scrollController,
                    itemCount: newsProvider.posts.length,
                    itemBuilder: (context, index) {
                      return GestureDetector(
                        onTap: () {
                          Navigator.of(context).push(MaterialPageRoute(
                            builder: (BuildContext context) =>
                                HabaruDetails(newsProvider.posts[index]),
                          ));
                        },
                        child: Container(
                          height: 200,
                          margin: EdgeInsets.only(left: 10, right: 10, top: 10),
                          child: ClipRRect(
                            borderRadius: BorderRadius.circular(7),
                            child: Stack(
                              children: [
                                Positioned.fill(
                                  child: Hero(
                                    tag: newsProvider.posts[index].id,
                                    child: FadeInImage.memoryNetwork(
                                        placeholder: kTransparentImage,
                                        fit: BoxFit.cover,
                                        image: newsProvider
                                            .posts[index].betterFeaturedImage.mediumLarge),
                                  ),
                                ),
                                Container(
                                  height: 200,
                                  decoration: BoxDecoration(
                                      color: Colors.white,
                                      gradient: LinearGradient(
                                          begin: FractionalOffset.topCenter,
                                          end: FractionalOffset.bottomCenter,
                                          colors: [
                                            Colors.black.withOpacity(0.0),
                                            Colors.black.withOpacity(0.95),
                                          ],
                                          stops: [
                                            0.0,
                                            1.0
                                          ])),
                                ),
                                Positioned.fill(
                                  child: Align(
                                    alignment: Alignment.bottomCenter,
                                    child: Padding(
                                      padding: const EdgeInsets.symmetric(
                                          horizontal: 16, vertical: 30),
                                      child: Text(
                                        newsProvider.posts[index].title.rendered,
                                        textAlign: TextAlign.center,
                                        textDirection: TextDirection.rtl,
                                        style: TextStyle(
                                          fontSize: 24,
                                          fontWeight: FontWeight.bold,
                                          color: Colors.white,
                                          height: 1.7,
                                        ),
                                      ),
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                      );
                    },
                  )
like image 637
Xihuny Avatar asked Nov 07 '22 04:11

Xihuny


1 Answers

I think you still must use a TabBarView, but you can generate its children dynamically based on the categories list like below.

@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          bottom: TabBar(
            tabs: [...],
          ),
        ),
        body: TabBarView(
          children: newsProvider.categories.map(
                (e) => ListView.builder(...).toList(),
          ),
        ),
      ),
    ),
  );
}
like image 187
Jihad Naji Avatar answered Nov 15 '22 07:11

Jihad Naji