Flutter перезапускает виджет Stateful, изменяя параметр из родительского - PullRequest
0 голосов
/ 11 марта 2020

Я пытаюсь выполнить sh это:

  1. У меня есть PageModule Stateid Widget, который содержит PageView с нижней панелью
  2. Как только я нажимаю центральную кнопку, он открывает нижнюю таблицу, чтобы выбрать, хочу ли я выбрать изображение с камеры или из галереи
  3. В зависимости от выбора мне нужно открыть виджет NewPost с учетом выбора для использования пакета image_picker.

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

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

Надеюсь, мой запрос ясен. В приведенном ниже коде я попытался реализовать пакет Provider, надеясь решить эту проблему, но я, безусловно, упускаю из этого суть.

PageModule

class PageModule extends StatefulWidget {
  static const String id = 'start';
  @override
  _PageModuleState createState() => _PageModuleState();
}

class _PageModuleState extends State<PageModule> {
  int _selectedIndex = 0;
  String source = 'gallery';

  PageController pageController = PageController(
    initialPage: 0,
    keepPage: true,
  );

  void onPageChange(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  void onTabChange(int index) {
    setState(() {
      _selectedIndex = index;
      pageController.jumpToPage(index);
    });
  }

  void _bottomSheet() {
    showModalBottomSheet(
      shape: kBottomSheetShape,
      context: context,
      builder: (context) => CameraSelector(
        onAction: (String value) {
          Provider.of<SharedData>(context).changeSource(value);
          onTabChange(2);
        },
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Provider<SharedData>(
      create: (context) => SharedData(),
      child: Scaffold(
        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
        floatingActionButton: FloatingActionButton(
          child: const Icon(Icons.camera),
          onPressed: () {
            _bottomSheet();
          },
        ),
        bottomNavigationBar: BottomAppBar(
          shape: CircularNotchedRectangle(),
          notchMargin: 4.0,
          child: new Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              IconButton(
                icon: Icon(Icons.home),
                onPressed: () {
                  onTabChange(0);
                },
              ),
              IconButton(
                icon: Icon(Icons.search),
                onPressed: () {
                  onTabChange(1);
                },
              ),
              SizedBox(
                width: 50.0,
              ),
              IconButton(
                icon: Icon(Icons.notifications),
                onPressed: () {
                  onTabChange(3);
                },
              ),
              IconButton(
                icon: Icon(Icons.person_pin),
                onPressed: () {
                  onTabChange(4);
                },
              ),
            ],
          ),
        ),
        body: PageView(
          controller: pageController,
          physics: NeverScrollableScrollPhysics(),
          onPageChanged: (index) {
            onPageChange(index);
          },
          children: <Widget>[
            HomeScreen(),
            SearchScreen(),
            NewPostScreen(),
            NotificationScreen(),
            ProfileScreen(),
          ],
        ),
      ),
    );
  }
}

CameraSelector нижний лист

class CameraSelector extends StatelessWidget {
  final Function onAction;

  CameraSelector({@required this.onAction});

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Container(
          padding: EdgeInsets.only(bottom: 45, top: 25),
          child: Column(
            children: <Widget>[
              Heading(
                size: kH2,
                text: 'Scegli una opzione',
                bold: true,
              ),
              SizedBox(
                height: 20,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  SelectorButton(
                    icon: Icons.photo_size_select_actual,
                    label: 'Libreria',
                    source: Source.gallery,
                    action: (String value) {
                      onAction(value.toLowerCase());
                    },
                  ),
                  SizedBox(
                    width: 20,
                  ),
                  SelectorButton(
                    icon: Icons.camera_alt,
                    label: 'Camera',
                    source: Source.camera,
                    action: (String value) {
                      onAction(value.toLowerCase());
                    },
                  ),
                ],
              ),
            ],
          )),
    );
  }
}

class SelectorButton extends StatelessWidget {
  final IconData icon;
  final String label;
  final String source;
  final Function action;

  SelectorButton({
    @required this.icon,
    @required this.label,
    @required this.source,
    @required this.action,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        borderRadius: BorderRadius.all(Radius.circular(20)),
      ),
      child: InkWell(
        onTap: () {
          Navigator.pop(context);
          action(source);
        },
        borderRadius: BorderRadius.all(Radius.circular(20)),
        child: Container(
          padding: EdgeInsets.symmetric(
            vertical: 20,
            horizontal: 30,
          ),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.all(Radius.circular(20)),
            border: Border.all(color: Colors.grey[850], width: 1.5),
          ),
          child: Column(
            children: <Widget>[
              Icon(
                icon,
                size: 50.0,
                color: Colors.grey[850],
              ),
              SizedBox(
                height: 5,
              ),
              Text(
                label.toUpperCase(),
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  fontSize: 15,
                  color: Colors.grey[850],
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

NewPost

  static const String id = 'newpost';
  @override
  _NewPostScreenState createState() => _NewPostScreenState();
}

class _NewPostScreenState extends State<NewPostScreen> {
  File _image;

  Future getImage() async {
    var image = await ImagePicker.pickImage(
      source: Provider.of<SharedData>(context).source == 'gallery' ? ImageSource.gallery : ImageSource.camera,
      imageQuality: 100,
      maxWidth: 1200,
    );

    setState(() {
      _image = image;
    });
  }

  @override
  void initState() {
    super.initState();
    getImage();
  }

  Widget _bodyBuild() {
    if (_image != null) {
      return ListView(
        shrinkWrap: true,
        padding: EdgeInsets.all(20.0),
        children: <Widget>[
          Heading(
            size: kH1,
            text: 'Dettagli del post',
            bold: true,
          ),
          SizedBox(
            height: 20.0,
          ),
          Container(
            height: 100.0,
            child: Center(
              child: Row(
                children: <Widget>[
                  Container(
                    width: 100,
                    child: _image == null
                        ? Text('')
                        : ProfileImage(
                            size: 50,
                            image: _image,
                          ),
                  ),
                  SizedBox(
                    width: 20.0,
                  ),
                  Text('qui box per descrizione')
                ],
              ),
            ),
          ),
          SizedBox(
            height: 20.0,
          ),
          Container(
            decoration: BoxDecoration(
              border: Border(top: BorderSide(width: 1.0, color: Colors.grey[400])),
            ),
          ),
          SizedBox(
            height: 20.0,
          ),
          Heading(
            size: kH3,
            text: 'Tagga gli amici',
            bold: true,
          ),
          SizedBox(
            height: 20.0,
          ),
          Text('lista dei tag degli amici con un input di ricerca con autocompletamento dei risultati'),
          SizedBox(
            height: 20.0,
          ),
          Container(
            decoration: BoxDecoration(
              border: Border(top: BorderSide(width: 1.0, color: Colors.grey[400])),
            ),
          ),
          SizedBox(
            height: 20.0,
          ),
          Heading(
            size: kH3,
            text: 'Aggiungi tag',
            bold: true,
          ),
          SizedBox(
            height: 20.0,
          ),
          Text('lista dei tag argomenti con un input di ricerca con autocompletamento dei risultati')
        ],
      );
    } else {
      return Container();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Nuovo Post'),
      ),
      body: _bodyBuild(),
    );
  }
}

1 Ответ

1 голос
/ 11 марта 2020

Поскольку вы используете provider вместо initState, то, что вы ищете, это didChangeDependencies / build

Идея состоит в том, что вместо инициализации вашего состояния один раз при создании вы инициализируете его при изменении состояния провайдера

Вот как это будет выглядеть:

class _MyState extends State<MyStatefulWidget> {
  SomeClass previousSomeClass;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final someClass = Provider.of<Something>(context).someClass;
    if (someClass != previousSomeClass) {
      previousSomeClass = someClass;
      getImage();
    }
  }

  void getImage() {...}
}
...