简体   繁体   中英

How to create a dynamic tab bar in Flutter?

I have two tabs that are built from the repository class. I need to filter the items that are shown on them according to nationalities, but the items are rendered only on the first tab. The second tab doesn't show anything, I believe it has to do with Stateful and Stateless.

How can I run repository class each time I change tab?

The code below is about Tab and TabView

import 'package:flutter/material.dart';
import 'package:flutterbol/models/teams_model.dart';
import 'package:flutterbol/repository/teams_repository.dart';

class TeamsScreen extends StatefulWidget {
  @override
  _TeamsScreenState createState() => _TeamsScreenState();
}

class _TeamsScreenState extends State<TeamsScreen> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: choices.length,
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Tabbed AppBar'),
            bottom: TabBar(
              isScrollable: true,
              tabs: choices.map((Choice choice) {
                return Tab(
                  text: choice.title,
                  icon: Icon(choice.icon),
                );
              }).toList(),
            ),
          ),
          body: TabBarView(
            children: choices.map((Choice choice) {
              return Padding(
                padding: const EdgeInsets.all(16.0),
                child: ChoiceCard(choice: choice),
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

class Choice {
  const Choice({this.title, this.icon});

  final String title;
  final IconData icon;
}

const List<Choice> choices = const <Choice>[
  const Choice(title: 'NATIONALS', icon: Icons.flag),
  const Choice(title: 'INTERNATIONALS', icon: Icons.outlined_flag),
];

class ChoiceCard extends StatelessWidget {
  const ChoiceCard({Key key, this.choice}) : super(key: key);

  final Choice choice;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: FutureBuilder<List<TeamsModel>>(
          future: TeamsRepository().findAllAsync(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              return buildListView(snapshot.data);
            } else {
              return Center(
                child: CircularProgressIndicator(),
              );
            }
          },
        ));
  }

  ListView buildListView(List<TeamsModel> teams) {
    return ListView.builder(
      itemCount: teams == null ? 0 : teams.length,
      //itemCount: teams.length,
      itemBuilder: (BuildContext ctx, int index) {
        return teamCard(teams[index]);
      },
    );
  }

  Card teamCard(TeamsModel team) {
    if (team.nacionalidade == choice.title) {
      return Card(
        child: Text(team.name),
      );
    }
  }
}

Tabs and Cards

You can copy paste run full code below
You need to return Container() in else condition and return type is Widget not Card
code snippet

  Widget teamCard(TeamsModel team) {
    if (team.nacionalidade == choice.title) {
      return Card(
        child: Text(team.name),
      );
    } else {
      return Container();
    }
  }

working demo

在此处输入图像描述

full code

import 'package:flutter/material.dart';

class TeamsModel {
  String nacionalidade;
  String name;

  TeamsModel(this.name, this.nacionalidade);
}

class TeamsRepository {
  Future<List<TeamsModel>> findAllAsync() {
    return Future.value([
      TeamsModel("a", "NATIONALS"),
      TeamsModel("b", "NATIONALS"),
      TeamsModel("c", "INTERNATIONALS"),
      TeamsModel("d", "INTERNATIONALS")
    ]);
  }
}

class TeamsScreen extends StatefulWidget {
  @override
  _TeamsScreenState createState() => _TeamsScreenState();
}

class _TeamsScreenState extends State<TeamsScreen> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: choices.length,
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Tabbed AppBar'),
            bottom: TabBar(
              isScrollable: true,
              tabs: choices.map((Choice choice) {
                return Tab(
                  text: choice.title,
                  icon: Icon(choice.icon),
                );
              }).toList(),
            ),
          ),
          body: TabBarView(
            children: choices.map((Choice choice) {
              print(choice.title);
              return Padding(
                padding: const EdgeInsets.all(16.0),
                child: ChoiceCard(choice: choice),
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

class Choice {
  const Choice({this.title, this.icon});

  final String title;
  final IconData icon;
}

const List<Choice> choices = const <Choice>[
  const Choice(title: 'NATIONALS', icon: Icons.flag),
  const Choice(title: 'INTERNATIONALS', icon: Icons.outlined_flag),
];

class ChoiceCard extends StatelessWidget {
  const ChoiceCard({Key key, this.choice}) : super(key: key);

  final Choice choice;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: FutureBuilder<List<TeamsModel>>(
      future: TeamsRepository().findAllAsync(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return buildListView(snapshot.data);
        } else {
          return Center(
            child: CircularProgressIndicator(),
          );
        }
      },
    ));
  }

  ListView buildListView(List<TeamsModel> teams) {
    return ListView.builder(
      itemCount: teams == null ? 0 : teams.length,
      //itemCount: teams.length,
      itemBuilder: (BuildContext ctx, int index) {
        return teamCard(teams[index]);
      },
    );
  }

  Widget teamCard(TeamsModel team) {
    if (team.nacionalidade == choice.title) {
      return Card(
        child: Text(team.name),
      );
    } else {
      return Container();
    }
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: TeamsScreen(),
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM