Как напрямую добавить blo c в виджет вида - PullRequest
1 голос
/ 24 апреля 2020

У меня есть экран, который создает виджет.

Как мне добавить blo c в мой виджет?

class UserView extends StatelessWidget {
   final AnimationController aController;
   final Animation animation;

   @override
   Widget build(BuildContext context) {
     // Add Scafold here?
      return AnimationBuilder(
         animation: aController;
         builder: (BuildContext context, Widget child) {
            ...
         },
      );
   }
}

Blo c

class UserBloc extends Bloc<UserEvent, UserState> {
    final UserRepo userRepo;
    UserBloc({@required this.userRepo}) : assert(userRepo != null);
}

Если я добавлю Scaffold(), то получаю ошибку, говорящую «объекту был задан бесконечный размер во время макета».

Я использую это https://bloclibrary.dev/# / для blo c.

При необходимости я могу показать больше кода, я стараюсь, чтобы он был легким для удобства чтения. Пожалуйста, спросите, и я могу добавить больше.


Приложение

void main() async {
  final UserRepo userRepo = UserRepo();
  BlocSupervisor.delegate = SimpleBlocDelegate();

  WidgetsFlutterBinding.ensureInitialized();
  await SystemChrome.setPreferredOrientations(<DeviceOrientation>[
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown
  ]).then((_) => runApp(MultiBlocProvider(
        providers: [
          BlocProvider<UserBloc>(
            create: (context) => UserBloc(userRepo: userRepo),
          )
        ],
        child: MyApp(),
      )));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      title: 'Test App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        textTheme: AppTheme.textTheme,
        platform: TargetPlatform.iOS,
      ),
      home: HomeScreen(),
    );
  }
}

Главный экран

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen>
    with TickerProviderStateMixin {
  AnimationController animationController;

  Widget tabBody = Container(
    color: AppTheme.background,
  );

  @override
  void initState() {
    animationController = AnimationController(
        duration: const Duration(milliseconds: 800), vsync: this);
    tabBody = DashboardScreen(animationController: animationController);
    super.initState();
  }

  @override
  void dispose() {
    animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: AppTheme.background,
      child: Scaffold(
        backgroundColor: Colors.transparent,
        body: FutureBuilder<bool>(
          future: getData(),
          builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
            if (!snapshot.hasData) {
              return const SizedBox();
            } else {
              return Stack(
                children: <Widget>[
                  tabBody
                ],
              );
            }
          },
        ),
      ),
    );
  }
}

Панель управления

class DashboardScreen extends StatefulWidget {
  const DashboardScreen({Key key, this.animationController}) : super(key: key);

  final AnimationController animationController;
  @override
  _DashboardScreenState createState() => _DashboardScreenState();
}

class _DashboardScreenState extends State<DashboardScreen>
    with TickerProviderStateMixin {
  Animation<double> topBarAnimation;

  List<Widget> listViews = <Widget>[];
  final ScrollController scrollController = ScrollController();
  double topBarOpacity = 0.0;

  @override
  void initState() {
    listViews.add(
      UserView(
        animation: Tween<double>(begin: 0.0, end: 1.0).animate(CurvedAnimation(
            parent: widget.animationController,
            curve:
                Interval((1 / count) * 1, 1.0, curve: Curves.fastOutSlowIn))),
        animationController: widget.animationController,
      ),
    );
    super.initState();
  }

}

1 Ответ

1 голос
/ 24 апреля 2020

Полагаю, что UserBloc должно быть доступно всему приложению, если нет, просто измените уровень провайдера ниже, чтобы он был чуть выше виджетов, которые он должен охватывать:

Здесь вы предоставляете блок c должен быть выше MaterialApp виджет, чтобы использовать его позже в любом потомке этого виджета: (внутри файла приложения)

 return BlocProvider(
    create: (_)=>UserBloc(userRepo:UserRep()),
    child: MaterialApp(
      title: 'Test App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        textTheme: AppTheme.textTheme,
        platform: TargetPlatform.iOS,
      ),
      home: HomeScreen(),
    ),
  );

сейчас, если вы хотите использовать свой blo c для отправлять события и прослушивать состояния в любом виджете-потомке MaterialApp, вы просто заключаете этот виджет в BlocListener или BlocConsumer или BlocBuilder (см. разницу между ними здесь ):

Полагаю, вы хотите сделать это в HomeScreen:

class _HomeScreenState extends State<HomeScreen>
    with TickerProviderStateMixin {
  AnimationController animationController;

  Widget tabBody = Container(
    color: AppTheme.background,
  );

  @override
  void initState() {
    animationController = AnimationController(
        duration: const Duration(milliseconds: 800), vsync: this);
    tabBody = DashboardScreen(animationController: animationController);
    super.initState();
  }

  @override
  void dispose() {
    animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: AppTheme.background,
      child: Scaffold(
        backgroundColor: Colors.transparent,
        body: FutureBuilder<bool>(
          future: getData(),
          builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
            if (!snapshot.hasData) {
              return const SizedBox();
            } else {
              return Stack(
                children: <Widget>[
                  //tabBody
                  //Don't save widgets as fields, just create them on the fly
                  BlocBuilder<UserBloc,UserState>(
                    builder: (ctx,state){
                      //return widget that depends on state and which should rebuild when state changes
                      return DashboardScreen(animationController: animationController);
                    },
                  )
                ],
              );
            }
          },
        ),
      ),
    );
  }
}

и все.

Для получения дополнительной документации см. Ссылку выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...