Flutter Listview状态问题

时间:2019-12-03 18:26:11

标签: flutter

我创建了一个示例,可以在其中动态添加元素到颤动列表视图。每个列表视图元素都有按钮和文本。当我添加新元素时,显示不正确的文本。我正在添加增量数据,并期望每个项目的值分别为1,2,3,4...。但是每个项目的值仅为1。同样,在特定项目上按下按钮的状态也不会保持,在我滚动列表之后,只会显示正确的值。

我们不能在listView中使用有状态的小部件吗? 。问题和代码如下

Recording

 import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  List<String> europeanCountries = [];
  int _counter = 0;
  int _perPage = 50;
  ScrollController _myScrollController = ScrollController();

  void _incrementCounter() async {
    const ThreeSec = const Duration(seconds: 1);
    this._counter++;
    europeanCountries.insert(0, this._counter.toString());
    print(europeanCountries);

    setState(() {});
  }

  void getMoreData() {
    print('adding More Product ');

    europeanCountries.add("New Product");

    setState(() {});
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    _myScrollController.addListener(() {
      double maxscroll = _myScrollController.position.maxScrollExtent;
      double currentScroll = _myScrollController.position.pixels;
      double delta = MediaQuery.of(context).size.height * 0.25;
      print("mac Scroll Controller - " + maxscroll.toString());
      print("Current  Scroll Controller - " + currentScroll.toString());
      print("delta  Scroll Controller - " + delta.toString());

      if ((maxscroll - currentScroll) < delta) {
        getMoreData();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: _myListView(context),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  Widget _myListView(BuildContext context) {
    // backing data

    return Container(
      child: europeanCountries.length == 0
          ? Center(
              child: Text('No Product to Display'),
            )
          : ListView.builder(
              controller: _myScrollController,
              itemCount: europeanCountries.length,
              reverse: false,
              itemBuilder: (context, index) {
                return myContainer(
                  mytext: europeanCountries[index],
                );
              },
            ),
    );
  }
}

class myContainer extends StatefulWidget {
  final String mytext;

  const myContainer({Key key, this.mytext}) : super(key: key);

  @override
  _myContainerState createState() => _myContainerState(mytext);
}

class _myContainerState extends State<myContainer> {
  final String mytext;
  String _buttontext = "inprogress";
  Color myClr = Colors.blue;

  _changeText() {
    setState(() {
      _buttontext = "Done";
      myClr = Colors.green;
    });
  }

  _myContainerState(this.mytext);
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 100,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.blue[700]),
        shape: BoxShape.rectangle,
        borderRadius: BorderRadius.all(Radius.circular(8)),
      ),
      margin: EdgeInsets.all(20),
      child: Column(
        children: <Widget>[
          Text(mytext),
          RaisedButton(
            child: Text(_buttontext),
            onPressed: _changeText,
            color: myClr,
            textColor: Colors.white,
            padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
            splashColor: Colors.black,
          )
        ],
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:1)

编辑 更新评论中提到的完整代码
使用Class保持按钮color

代码段

class EuropeanCountries {
  String myText;
  String myButtonText;
  Color myColor;

  EuropeanCountries({
    this.myText,
    this.myButtonText,
    this.myColor,
  });

}

用于编辑的演示

enter image description here

完整代码进行编辑

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class EuropeanCountries {
  String myText;
  String myButtonText;
  Color myColor;

  EuropeanCountries({
    this.myText,
    this.myButtonText,
    this.myColor,
  });

}


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

  final String title;

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

List<EuropeanCountries> europeanCountries = [];

class _MyHomePageState extends State<MyHomePage> {

  int _counter = 0;
  int _perPage = 50;
  ScrollController _myScrollController = ScrollController();

  void _incrementCounter() async {
    const ThreeSec = const Duration(seconds: 1);
    this._counter++;
    europeanCountries.insert(0, EuropeanCountries(myText:this._counter.toString(), myButtonText: "inprogress", myColor: Colors.blue));
    print(europeanCountries);

    setState(() {});
  }

  void getMoreData() {
    print('adding More Product ');

    europeanCountries.add(EuropeanCountries(myText:this._counter.toString(), myButtonText: "inprogress", myColor: Colors.blue));
    //europeanCountries.insert(0, EuropeanCountries(myText:this._counter.toString(), myButtonText: "", myColor: Colors.blue));
    setState(() {});
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    _myScrollController.addListener(() {
      double maxscroll = _myScrollController.position.maxScrollExtent;
      double currentScroll = _myScrollController.position.pixels;
      double delta = MediaQuery.of(context).size.height * 0.25;
      print("mac Scroll Controller - " + maxscroll.toString());
      print("Current  Scroll Controller - " + currentScroll.toString());
      print("delta  Scroll Controller - " + delta.toString());

      if ((maxscroll - currentScroll) < delta) {
        getMoreData();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: _myListView(context),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  Widget _myListView(BuildContext context) {
    // backing data

    return Container(
      child: europeanCountries.length == 0
          ? Center(
              child: Text('No Product to Display'),
            )
          : ListView.builder(
              controller: _myScrollController,
              itemCount: europeanCountries.length,
              reverse: false,
              itemBuilder: (context, index) {
                return myContainer(
                    index : index
                );
              },
            ),
    );
  }
}

class myContainer extends StatefulWidget {
  final int index;
   const myContainer({Key key, this.index}) : super(key: key);

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

class _myContainerState extends State<myContainer> {
  //final String mytext;
  //String _buttontext = "inprogress";
  //Color myClr = Colors.blue;

  _changeText() {
    setState(() {
      europeanCountries[widget.index].myButtonText = "Done";
      europeanCountries[widget.index].myColor= Colors.green;
    });
  }

  //_myContainerState(this.mytext);
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 100,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.blue[700]),
        shape: BoxShape.rectangle,
        borderRadius: BorderRadius.all(Radius.circular(8)),
      ),
      margin: EdgeInsets.all(20),
      child: Column(
        children: <Widget>[
          Text(europeanCountries[widget.index].myText),
          RaisedButton(
            child: Text(europeanCountries[widget.index].myButtonText),
            onPressed: _changeText,
            color: europeanCountries[widget.index].myColor,
            textColor: Colors.white,
            padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
            splashColor: Colors.black,
          )
        ],
      ),
    );
  }
}

您可以在下面复制粘贴运行完整代码
myContainer扩展StatefulWidget的使用方式不正确。

第1步:_myContainerState(mytext);删除mytext
步骤2:注释// final String mytext;
步骤3:注释//__myContainerState(this.mytext);
步骤4:Text(widget.mytext)添加widget.

工作演示

enter image description here

完整代码

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  List<String> europeanCountries = [];
  int _counter = 0;
  int _perPage = 50;
  ScrollController _myScrollController = ScrollController();

  void _incrementCounter() async {
    const ThreeSec = const Duration(seconds: 1);
    this._counter++;
    europeanCountries.insert(0, this._counter.toString());
    print(europeanCountries);

    setState(() {});
  }

  void getMoreData() {
    print('adding More Product ');

    europeanCountries.add("New Product");

    setState(() {});
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    _myScrollController.addListener(() {
      double maxscroll = _myScrollController.position.maxScrollExtent;
      double currentScroll = _myScrollController.position.pixels;
      double delta = MediaQuery.of(context).size.height * 0.25;
      print("mac Scroll Controller - " + maxscroll.toString());
      print("Current  Scroll Controller - " + currentScroll.toString());
      print("delta  Scroll Controller - " + delta.toString());

      if ((maxscroll - currentScroll) < delta) {
        getMoreData();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: _myListView(context),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  Widget _myListView(BuildContext context) {
    // backing data

    return Container(
      child: europeanCountries.length == 0
          ? Center(
              child: Text('No Product to Display'),
            )
          : ListView.builder(
              controller: _myScrollController,
              itemCount: europeanCountries.length,
              reverse: false,
              itemBuilder: (context, index) {
                return myContainer(
                  mytext: europeanCountries[index],
                );
              },
            ),
    );
  }
}

class myContainer extends StatefulWidget {
  final String mytext;

  const myContainer({Key key, this.mytext}) : super(key: key);

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

class _myContainerState extends State<myContainer> {
  //final String mytext;
  String _buttontext = "inprogress";
  Color myClr = Colors.blue;

  _changeText() {
    setState(() {
      _buttontext = "Done";
      myClr = Colors.green;
    });
  }

  //_myContainerState(this.mytext);
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 100,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.blue[700]),
        shape: BoxShape.rectangle,
        borderRadius: BorderRadius.all(Radius.circular(8)),
      ),
      margin: EdgeInsets.all(20),
      child: Column(
        children: <Widget>[
          Text(widget.mytext),
          RaisedButton(
            child: Text(_buttontext),
            onPressed: _changeText,
            color: myClr,
            textColor: Colors.white,
            padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
            splashColor: Colors.black,
          )
        ],
      ),
    );
  }
}