나는 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 당신 내용에 따라 다른 이미지를로드 할 수도 있고로드하지 않을 수도 있습니다. '실패한로드'의 경우, 이니셜이 남아 있어야합니다. 여기
당신이ImageConfiguration
에서 얻을 수
ImageStream
에 리스너를 추가하여이 기능을 달성 할 수
는 - 대단히 감사합니다, 그것은 완벽했다. 왜 지금 이해 : – bradbeveridge
@bradbeveridge 나는 그것이 도움이되어 기쁘다, 당신은 내가 받고있는 오류를 재현 할 수있는 무언가를 줄 수있다 – aziza
나는 내가 틀렸을 까봐 두렵다. 나는 아직도 내가 무엇을 얻을 수 있는지 모르겠다. 나는 원래 질문을 업데이트했습니다. 시간과 도움을 많이 주셔서 감사합니다. – bradbeveridge