2017-10-18 18 views
0

我在学习Flutter,想要制作Widget就像内置的CircleAvatar。不过,我想的行为是扑动:CircleAvatar带后备文本

  • 同时指定影像(NetworkImage)和缩写(即BB)
  • 而没有加载图像,显示缩写
  • 如果影像负载,显示图像和删除缩写

下面的代码排序的作品,但在聊天室演示使用时分崩离析多重MyAvatars添加。 在initState上突出显示它始终使用输入的第一个消息文本进行调用 - 而不是我所期望的。 它也闪烁为图像“重新加载”。看来这些小工具正以我不明白的方式被重用。

class MyAvatar extends StatefulWidget {      
    NetworkImage image; 
    MyAvatar({this.text}) { 
    debugPrint("MyAvatar " + this.text); 
    if (text.contains('fun')) { 
     this.image = new NetworkImage("https://cdn3.iconfinder.com/data/icons/minicons-for-web-sites/24/minicons2-14-512.png"); 
    } 
    } 
    final String text; 
    @override               
    MyAvatarState createState() { 
    return new MyAvatarState(); 
    }      
} 

class MyAvatarState extends State<MyAvatar> { 
    bool showImage = false; 
    @override 
    initState() { 
    super.initState(); 
    if (widget.image != null) { 
     var completer = widget.image.load(widget.image); 
     completer.addListener((info, sync) { 
     setState(() { 
      showImage = true; 
     }); 
     }); 
    } 
    } 

    @override 
    Widget build(BuildContext context) { 
    return !showImage ? new CircleAvatar(radius: 40.0, child: new Text(widget.text[0])) 
     : new CircleAvatar(radius: 40.0, backgroundImage: widget.image); 
    } 
} 

我仍然有麻烦 - 全码

import 'package:flutter/material.dart'; 
// Modify the ChatScreen class definition to extend StatefulWidget. 

class ChatScreen extends StatefulWidget {      //modified 
    ChatScreen() { 
    debugPrint("ChatScreen - called on hot reload"); 
    } 
    @override              //new 
    State createState() { 
    debugPrint("NOT on hot reload"); 
    return new ChatScreenState(); 
    }     //new 
} 

// Add the ChatScreenState class definition in main.dart. 

class ChatScreenState extends State<ChatScreen> { 
    final List<ChatMessage> _messages = <ChatMessage>[]; 
    final TextEditingController _textController = new TextEditingController(); //new 
    ChatScreenState() { 
    debugPrint("ChatScreenState - not called on hot reload"); 
    } 

    @override //new 
    Widget build(BuildContext context) { 
    return new Scaffold(
     appBar: new AppBar(title: new Text("Friendlychat")), 
     body: new Column(          //modified 
      children: <Widget>[           //new 
      new Flexible(            //new 
       child: new ListView.builder(        //new 
        padding: new EdgeInsets.all(8.0),      //new 
        reverse: true,           //new 
        itemBuilder: (_, int index) => _messages[index],  //new 
        itemCount: _messages.length,       //new 
       )               //new 
      ),               //new 
      new Divider(height: 1.0),         //new 
      new Container(            //new 
       decoration: new BoxDecoration(
        color: Theme.of(context).cardColor),     //new 
       child: _buildTextComposer(),       //modified 
      ),               //new 
      ]               //new 
    ),                //new 
    ); 
    } 

    Widget _buildTextComposer() { 

    return new IconTheme(
     data: new IconThemeData(color: Theme 
      .of(context) 
      .accentColor), 
     child: 
     new Container(
      margin: const EdgeInsets.symmetric(horizontal: 8.0), 
      child: new Row(
       children: <Widget>[ 
        new Container(//new 
        margin: new EdgeInsets.symmetric(horizontal: 4.0), //new 
        child: new IconButton(//new 
         icon: new Icon(Icons.send), 
         onPressed:() => 
          _handleSubmitted(_textController.text)), //new 
       ), 
        new Flexible(
         child: new TextField(
         controller: _textController, 
         onSubmitted: _handleSubmitted, 
         decoration: new InputDecoration.collapsed(
          hintText: "Send a message"), 
        ) 
       ), 
       ]) 
     ) 
    ); 
    } 

    void _handleSubmitted(String text) { 


    _textController.clear(); 
    ChatMessage message = new ChatMessage(text: text); 
    setState(() { 
     _messages.insert(0, message); 
    }); 
    } 
} 

const String _name = "Hardcoded Name"; 

class ChatMessage extends StatelessWidget { 
    ChatMessage({this.text, this.image, this.useImage}); 
    final String text; 
    final NetworkImage image; 
    final Map useImage; 
    @override 
    Widget build(BuildContext context) { 
    var use = true; //useImage != null && useImage['use']; 

    var image = new NetworkImage("https://cdn3.iconfinder.com/data/icons/minicons-for-web-sites/24/minicons2-14-512.png"); 
    if (text.contains('bad')) { 
     image = new NetworkImage("https://cdn3.iconfinder.com/data/icons/minicons-for-web-sites/24/minicons2-14-512.pngz"); 
    } 
    return new Container(
     margin: const EdgeInsets.symmetric(vertical: 10.0), 
     child: new Row(
     crossAxisAlignment: CrossAxisAlignment.start, 
     children: <Widget>[ 
      new Container(
      margin: const EdgeInsets.only(right: 16.0), 
      child : new CustomCircleAvatar(initials: text[0], myImage: image) 
     ), 
      new Column(
      crossAxisAlignment: CrossAxisAlignment.start, 
      children: <Widget>[ 
       new Text(_name, style: Theme.of(context).textTheme.subhead), 
       new Container(
       margin: const EdgeInsets.only(top: 5.0), 
       child: new Text(text), 
      ), 
      ], 
     ), 
     ], 
    ), 
    ); 
    } 
} 

class CustomCircleAvatar extends StatefulWidget { 
    NetworkImage myImage; 

    String initials; 


    CustomCircleAvatar({this.myImage, this.initials}) { 
    debugPrint(initials); 
    } 

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

class _CustomCircleAvatarState extends State<CustomCircleAvatar>{ 

    bool _checkLoading = true; 

    @override 
    void initState() { 
    if (widget.myImage != null) { 
     widget.myImage.resolve(new ImageConfiguration()).addListener((image, sync) { 
     if (mounted && image != null) { 
      setState(() { 
      _checkLoading = false; 
      }); 
     } 
     }); 
    } 
    } 

    @override 
    Widget build(BuildContext context) { 
    return _checkLoading == true ? new CircleAvatar(child: new Text(widget.initials)) 
     : new CircleAvatar(backgroundImage: widget.myImage); 
    } 
} 

输入“乐趣”作为消息,那么“坏”作为第二个 - image 的想法是,这取决于你是什么输入,不同的图像可能会加载(或不加载)。在'未能加载'的情况下,首字母应该保持不变。

回答

1

可以实现通过添加一个监听器,ImageStream此功能,您可以从ImageConfiguration获得,

在这里,我喂相同的数据我ListView当然你也可以通过添加图像的List定制这个自己并在任何一个类的首字母缩写为一个字段,并使用ListView.builder而不是通过索引在它们上循环。

enter image description here

class CustomCircleAvatar extends StatefulWidget { 
    NetworkImage myImage; 

    String initials; 


    CustomCircleAvatar({this.myImage, this.initials}); 

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

class _CustomCircleAvatarState extends State<CustomCircleAvatar>{ 

    bool _checkLoading = true; 

    @override 
    void initState() { 
    widget.myImage.resolve(new ImageConfiguration()).addListener((_, __) { 
     if (mounted) { 
     setState(() { 
      _checkLoading = false; 
     }); 
     } 
    }); 
    } 

    @override 
    Widget build(BuildContext context) { 
    return _checkLoading == true ? new CircleAvatar(
     child: new Text(widget.initials)) : new CircleAvatar(
     backgroundImage: widget.myImage,); 
    } 
} 

现在你可以使用这样的:

void main() { 
    runApp(new MaterialApp (home: new MyApp())); 
} 

    class MyApp extends StatefulWidget { 
     @override 
     _MyAppState createState() => new _MyAppState(); 
    } 

    class _MyAppState extends State<MyApp> { 
     @override 
     Widget build(BuildContext context) { 
     return new Scaffold(
      appBar: new AppBar(title: new Text("Custom Circle Avatar"),), 
      body: new ListView(children: new List.generate(20, (int index) { 
      return new Container(
       height: 100.0, 
       width: 100.0, 
       child: new CustomCircleAvatar(myImage: new NetworkImage(
        "https://www.doginni.cz/front_path/images/dog_circle.png"), 
       initials: "Dog", 
      ), 
      ); 
      }),), 
     ); 
     } 
    } 
+0

这是极好的 - 非常感谢你,它的工作完美。现在明白为什么:) – bradbeveridge

+0

@bradbeveridge我很高兴它的帮助,你可以给我一些能够重现你正在得到的错误 – aziza

+0

恐怕我错了,我仍然不能很好地得到我'试图做:)我已经更新了原来的问题。非常感谢您的时间和帮助。 – bradbeveridge