Flutter не перестраивает один и тот же виджет с разными параметрами - PullRequest
7 голосов
/ 19 марта 2019

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

Дочерний элемент 1: enter image description here

Ребенок 2: enter image description here

Фактический результат: enter image description here

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

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

class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
Widget body;
@override
void initState() {
//    body = getBody(0);
super.initState();
}

@override
Widget build(BuildContext context) {
return Scaffold(
  appBar: AppBar(
    title: Text(widget.title),
    elevation: 0,
  ),
  body: body,
  bottomNavigationBar: BottomNavigationBar(
    currentIndex: _counter,
    onTap: (index){
      _counter = index;
      setState(() {
        body = getBody(index);
      });
    },items: [
    BottomNavigationBarItem(icon: Icon(Icons.language),title: 
 Text('HELLO')),
    BottomNavigationBarItem(icon: Icon(Icons.security),title: 
Text('BYE'))
  ]),
 );
}
Widget getBody(int pos){
if(pos==0){
//      return new Mx(category: 'ALPHA',type: '@',);
  return new MyTAbs(category: 'ALPHA',type: '@',);
}
else{
//      return new Mx(category:'BETA',type: '#',);
  return new MyTAbs(category:'BETA',type: '#',);
  }
 }
}
class Mx extends StatelessWidget{
final String type,category;
Mx({this.type,this.category});
@override
Widget build(BuildContext context) {
 return new Scaffold(
  backgroundColor: getColor(),
  body: new Center(
    child: Text(category+' '+type),
  ),
 );
}
Color getColor(){
if(category=='ALPHA'){
  return Colors.red;
}
else{
  return Colors.green;
  }
 }
}
class MyTAbs extends StatefulWidget{
final String type,category;
MyTAbs({this.type,this.category});
Tabs createState() => new Tabs(title: category,type: type);
}
class Tabs extends State<MyTAbs>{
final String title,type;
Tabs({this.title,this.type});
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
  backgroundColor: getColor(),
  appBar: AppBar(
    title: Text(title+' '+type),
  ),
);
}
Color getColor(){
if(title=='ALPHA'){
  return Colors.red;
}
else{
  return Colors.green;
  }
 }
}

и я не могу использовать statelessWidget , потому что внутри есть динамическая вкладка.

Ответы [ 3 ]

1 голос
/ 19 марта 2019

ваша проблема в классе передаваемых параметров "MyTAbs"

после редактирования, теперь его работа

вам не нужно передавать дату из класса "Stateful" в "State", просто вызовите его с помощью "widget.parameterName" в состоянии Ваш код после редактирования:

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

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  Widget body;
  @override
  void initState() {
//    body = getBody(0);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        elevation: 0,
      ),
      body: body,
      bottomNavigationBar: BottomNavigationBar(
          currentIndex: _counter,
          onTap: (index){
            _counter = index;
            setState(() {
              body = getBody(index);
            });
          },items: [
        BottomNavigationBarItem(icon: Icon(Icons.language),title:
        Text('HELLO')),
        BottomNavigationBarItem(icon: Icon(Icons.security),title:
        Text('BYE'))
      ]),
    );
  }
  Widget getBody(int pos){
    if(pos==0){
//      return new Mx(category: 'ALPHA',type: '@',);
      return new MyTAbs(category: 'ALPHA',type: '@',);
    }
    else{

//      return new Mx(category:'BETA',type: '#',);
      return new MyTAbs(category:'BETA',type: '#',);
    }
  }
}
class Mx extends StatelessWidget{
  final String type,category;
  Mx({this.type,this.category});
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      backgroundColor: getColor(),
      body: new Center(
        child: Text(category+' '+type),
      ),
    );
  }
  Color getColor(){
    if(category=='ALPHA'){
      return Colors.red;
    }
    else{
      return Colors.green;
    }
  }
}
class MyTAbs extends StatefulWidget{
  final String type,category;
  MyTAbs({this.type,this.category});
  Tabs createState() => new Tabs();
}
class Tabs extends State<MyTAbs>{


  @override
  Widget build(BuildContext context) {
    print(widget.type);
// TODO: implement build
    return new Scaffold(
      backgroundColor: getColor(),
      appBar: AppBar(
        title: Text(widget.category+' '+widget.type),
      ),
    );
  }
  Color getColor(){
    if(widget.category=='ALPHA'){
      return Colors.red;
    }
    else{
      return Colors.green;
    }
  }
}
1 голос
/ 19 марта 2019

Решил эту проблему, добавив новый ключ в качестве параметра и передав UniqueKey как

return new MyTAbs(category: 'ALPHA',type: '@',key: UniqueKey(),);

MyTAbs класс

class MyTAbs extends StatefulWidget{
  final String type,category;
  final Key key;
  MyTAbs({@required this.key,this.type,this.category});
  Tabs createState() => new Tabs(title: category,type: type,key: key);
}

Вкладки класса

class Tabs extends State<MyTAbs>{
  final String title,type;
  final Key key;
  Tabs({this.title,this.type,@required this.key});
  @override
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
      backgroundColor: getColor(),
      appBar: AppBar(
        title: Text(title+' '+type),
      ),
    );
  }
  Color getColor(){
    if(title=='ALPHA'){
      return Colors.red;
    }
    else{
      return Colors.green;
    }
  }
}

немного о Ключ

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

1 голос
/ 19 марта 2019

Измени свой Tabs класс

class Tabs extends State<MyTAbs> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      backgroundColor: getColor(),
      appBar: AppBar(
        title: Text(widget.category + ' ' + widget.type),
      ),
    );
  }

  Color getColor() {
    if (widget.category == 'ALPHA') {
      return Colors.red;
    } else {
      return Colors.green;
    }
  }
}

Класс State (Tabs) создается только один раз. Поэтому после этого вы не можете вызвать конструктор с новыми параметрами. Но у вас есть доступ к полям виджетов

...