Флаттер: как я могу иметь дело с несколькими методами setState ()? - PullRequest
1 голос
/ 10 октября 2019

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

Я искал решения здесь, но не нашел его. Но он работал с этим кодом (ссылка на полный код github ):

  _updateIndex(int index) {
    _selectedTab(index);
    setState(() {
      _selectedIndex = index;
    });
  }

  void _selectedTab(int index) {
    setState(() {
      _lastSelected = 'TAB: $index';
    });
  }

, и теперь он не работает с этим кодом:

  _updateIndex(int index) {
    _selectedTab(index); // works fine
    setState(() {
      _selectedIndex = index; // does not work
    });
  }

  void _selectedTab(int index) {
    switch(index) {
       case 1:
          setState(() {
             _lastSelected = 'TAB: $index';
          });
          break;
       // here is other cases and default
    }
  }

Я думал, что это будет работать с переключателем, но я не думаю, что проблема заключается непосредственно в функции переключателя.

Полный код: fab_bottom_app_bar.dart

import 'package:flutter/material.dart';

class FABBottomAppBarItem {
  FABBottomAppBarItem({this.iconData, this.text});
  IconData iconData;
  String text;
}

class FABBottomAppBar extends StatefulWidget {
  FABBottomAppBar({
    this.items,
    this.centerItemText,
    this.height: 60.0,
    this.iconSize: 24.0,
    this.backgroundColor,
    this.color,
    this.selectedColor,
    this.notchedShape,
    this.onTabSelected,
  }) {
    assert(this.items.length == 2 || this.items.length == 4);
  }
  final List<FABBottomAppBarItem> items;
  final String centerItemText;
  final double height;
  final double iconSize;
  final Color backgroundColor;
  final Color color;
  final Color selectedColor;
  final NotchedShape notchedShape;
  final ValueChanged<int> onTabSelected;

  @override
  State<StatefulWidget> createState() => FABBottomAppBarState();
}

class FABBottomAppBarState extends State<FABBottomAppBar> {
  static int _selectedIndex = 0;

  _updateIndex(int index) {
    widget.onTabSelected(index);
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> items = List.generate(widget.items.length, (int index) {
      return _buildTabItem(
        item: widget.items[index],
        index: index,
        onPressed: _updateIndex,
      );
    });
    items.insert(items.length >> 1, _buildMiddleTabItem());

    return BottomAppBar(
      shape: widget.notchedShape,
      child: Row(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: items,
      ),
      color: widget.backgroundColor,
    );
  }

  Widget _buildMiddleTabItem() {
    return Expanded(
      child: SizedBox(
        height: widget.height,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SizedBox(height: widget.iconSize),
            Text(
              widget.centerItemText ?? '',
              style: TextStyle(color: widget.color, fontSize: 14),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildTabItem({
    FABBottomAppBarItem item,
    int index,
    ValueChanged<int> onPressed,
  }) {
    Color color = _selectedIndex == index ? widget.selectedColor : widget.color;
    print(Text('COLOR CHANGED $_selectedIndex - $index = $color ---------------------------------'));
    return Expanded(
      child: SizedBox(
        height: widget.height,
        child: Material(
          type: MaterialType.transparency,
          child: InkWell(
            onTap: () => onPressed(index),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Icon(item.iconData, color: color, size: widget.iconSize),
                Text(
                  item.text,
                  style: TextStyle(fontSize: 10, color: color),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

и home.dart, где фактически внизуиспользуется бар:

import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flushbar/flushbar.dart';
import 'package:flutter_picker/Picker.dart';

import '../assets/colors.dart';
import '../models/fab_bottom_app_bar.dart';

import 'content/main.dart';
import 'content/results.dart';
import 'content/wallet.dart';
import 'content/questions.dart';
import 'content/profile.dart';

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  static const int MAIN_PAGE = 0;
  static const int RESULTS_PAGE = 1;
  static const int QUESTIONS_PAGE = 2;
  static const int WALLET_PAGE = 3;

  Widget _navigator = mainContent();

  void _selectedTab(int index) {
    print(Text('FAB SELECTED ---------------------------'));
    switch (index) {
      case MAIN_PAGE:
        setState(() {
          _navigator = mainContent();
        });
        break;
      case RESULTS_PAGE:
        setState(() {
          _navigator = resultContent();
        });
        break;
      case QUESTIONS_PAGE:
        setState(() {
          _navigator = questionsContent();
        });
        break;
      case WALLET_PAGE:
        setState(() {
          _navigator = walletContent();
        });
        break;
      default:
        setState(() {
          _navigator = mainContent();
        });
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    final GlobalKey<ScaffoldState> _scaffoldKey =
        new GlobalKey<ScaffoldState>();

    return Scaffold(
        bottomNavigationBar: FABBottomAppBar(
          color: Colors.grey,
          selectedColor: Colors.white,
          notchedShape: CircularNotchedRectangle(),
          onTabSelected: _selectedTab,
          backgroundColor: AppColors.mainColor,
          items: [
            FABBottomAppBarItem(iconData: Icons.home, text: 'Вплюсе'),
            FABBottomAppBarItem(iconData: Icons.whatshot, text: 'Результаты'),
            FABBottomAppBarItem(iconData: Icons.thumbs_up_down, text: 'Опросы'),
            FABBottomAppBarItem(
                iconData: Icons.account_balance_wallet, text: 'Кошельки')
          ],
        ),
        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
        floatingActionButton: _buildFab(context));
  }

  Widget _buildFab(BuildContext context) {
    return FloatingActionButton(
      onPressed: () {
        _promoDialog();
      },
      tooltip: 'Increment',
      child: Icon(Icons.add),
      elevation: 2.0,
      backgroundColor: AppColors.mainColor,
    );
  }
}

1 Ответ

1 голос
/ 11 октября 2019

Существует несколько решений:

  1. Используйте другие панели навигации, предоставленные pskink в комментариях:

    class MyNavigationBar extends StatefulWidget {
      final List<String> list;
    
      MyNavigationBar(this.list);
    
      @override
      _MyState createState() => _MyState();
    }
    
    class _MyState extends State<MyNavigationBar> {
      var current;
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: widget.list.map((t) {
              current ??= t;
              return InkWell(
                onTap: () => setState(() => current = t),
                child: Text(
                  t,
                  style: TextStyle(
                    fontSize: 32,
                    color: current == t ? Colors.red : Colors.grey,
                  ),
                ),
              );
            }).toList(),
          ),
        );
      }
    }
    

    itего легко настроить.

  2. , чтобы сделать _selectedIndex в fab_bottom_app_bar.dart static.

...