Флаттер - Как изменить текст в нижней части навигации от дочернего виджета? - PullRequest
0 голосов
/ 16 апреля 2019

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

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

Я пробовал несколько дней, но все еще не мог понять, как дочерний виджет может изменить текст.

Я пробовал обратный вызов, но не могу заставить его работать. Я пробовал navigation.push - маршрут страницы материала, но он перестраивает весь виджет, и мой выбор исчез Я также пытался использовать GlobalKey или Sharedpreference для захвата моего выбора, чтобы при повторном построении он использовал обратно сохраненный выбор, но я не смог заставить его работать.

Я хочу изменить только нижний текст навигации в одном из выпадающего списка текста из дочернего виджета.

Какой лучший метод для достижения этой цели?

1 Ответ

0 голосов
/ 16 апреля 2019

Я бы порекомендовал вам попробовать использовать шаблон блока с StreamBuilder.У меня есть пример ниже.Несмотря на это, в этом примере есть виджет с состоянием, блок и класс данных.Постарайтесь понять этот код и изменить его в соответствии с вашими потребностями.

import 'package:flutter/material.dart';
import 'dart:async';

class StreamScaffold extends StatefulWidget {
  @override
  _StreamScaffoldState createState() => _StreamScaffoldState();
}

class _StreamScaffoldState extends State<StreamScaffold> {
  ScaffoldDataBloc bloc;

  @override
  void initState() {
    super.initState();
    bloc = ScaffoldDataBloc();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<ScaffoldDataState>(
        stream: bloc.stream, // The stream we want to listen to.
        initialData: bloc.initial(), // The initial data the stream provides.
        builder: (context, snapshot) {
          ScaffoldDataState state = snapshot.data;

          Widget page;
          if (state.index == 0) {
            // TODO separate this into its own widget, this is messy.
            page = Center(
              child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    RaisedButton(
                      onPressed: () => bloc.updateText(state,"Sales"),
                        child: Text("Set text to Sales")

                    ),
                    RaisedButton(
                      onPressed: () => bloc.updateText(state, "Purchases"),
                      child: Text("Set text to Purchases"),
                    )
                  ]),
            );
          }

          if (state.index == 1) {
            // TODO separate this into its own widget, this is messy.
            page = Center(
                child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                  RaisedButton(
                    onPressed: () => bloc.updateText(state, "Stock"),
                    child: Text("Set text to Stock"),
                  ),
                  RaisedButton(
                    onPressed: () => bloc.updateText(state, "Budget"),
                    child: Text("Set text to Budget"),
                  )
                ]));
          }

          return Scaffold(
            body: page,
            bottomNavigationBar: BottomNavigationBar(
                currentIndex: state.index,
                onTap: (int) => bloc.updateIndex(state, int),
                items: [
                  BottomNavigationBarItem(
                      icon: Icon(Icons.play_arrow),
                      // Obtain the text from the state
                      title: Text(state.variableText)),
                  BottomNavigationBarItem(
                      icon: Icon(Icons.play_arrow), title: Text("Test")),
                ]),
          );
        });
  }

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

// A data class to hold the required data.
class ScaffoldDataState {
  int index;
  String variableText;

  ScaffoldDataState({this.index = 0, this.variableText = "Hello"});
}

// A bloc to handle updates of the state.
class ScaffoldDataBloc {
  StreamController<ScaffoldDataState> scaffoldDataStateController = StreamController<ScaffoldDataState>();
  Sink get updateScaffoldDataState => scaffoldDataStateController.sink;
  Stream<ScaffoldDataState> get stream => scaffoldDataStateController.stream;

  ScaffoldDataBloc();

  ScaffoldDataState initial() {
    return ScaffoldDataState();
  }

  void dispose() {
    scaffoldDataStateController.close();
  }

  // Needs to be called every time a change should happen in the UI
  // Add updated states into the Sink to get the Stream to update.
  void _update(ScaffoldDataState state) {
    updateScaffoldDataState.add(state);
  }

  // Specific methods for updating the different fields in the state object
  void updateText(ScaffoldDataState state, String text) {
    state.variableText = text;
    _update(state);
  }

  void updateIndex(ScaffoldDataState state, int index) {
    state.index = index;
    _update(state);
  }
}

Надеюсь, это поможет!

Дополнительные вопросы из комментария:

Самым простым решением было бы просто передать блок в качестве параметра виджету.Создайте новый файл dart в своем проекте, создайте там StatelessWidget, создайте код для страницы в методе сборки.Примечание. Было бы целесообразно разделить блок на отдельный файл вместе с классом данных.

import 'package:flutter/material.dart';

// Import the file where the bloc and data class is located
// You have to have a similar import in the parent widget. 
// Your dart files should be located in the lib folder, hit ctrl+space for 
// suggestions while writing an import, or alt+enter on a unimported class.
import 'package:playground/scaffold_in_stream_builder.dart'; 


class ChildPage extends StatelessWidget {
  final ScaffoldDataBloc bloc;
  final ScaffoldDataState state;

  const ChildPage({Key key, this.bloc, this.state}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(); // TODO replace with your page
  }
}

Однако, если эти дочерние виджеты получают своих собственных дочерних элементов в отдельных файлах, было бы лучшеиспользуйте вместо этого InheritedWidget с блоком и состоянием.Это позволяет избежать «прохождения состояния вниз».Смотрите эту статью о унаследованных виджетах

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