在使用Flutter構(gòu)建WhatsApp之前杰赛,我們創(chuàng)建了一個(gè)帶有選項(xiàng)卡和導(dǎo)航的基本appbar另患。 今天捆等,我們將使用ListView.builder創(chuàng)建聊天的滾動(dòng)列表
隨著介紹降铸,這里是我們將要構(gòu)建的截圖
#設(shè)置模型
在我們構(gòu)建List之前住拭,我們將為聊天構(gòu)建模板潭袱。 我們首先在lib文件夾中創(chuàng)建一個(gè)名為“model”的新文件夾柱嫌。 在模型文件夾中,創(chuàng)建名為chat_model.dart的文件屯换。 創(chuàng)建文件后编丘,我們現(xiàn)在可以開(kāi)始構(gòu)建結(jié)構(gòu)了。 我們將從創(chuàng)建ChatModel類開(kāi)始彤悔。
class ChatModel {
}
在這個(gè)類中嘉抓,我們將為我們想要聊天列表的功能創(chuàng)建變量。 WhatsApp通常具有消息的人物晕窑,姓名抑片,時(shí)間和消息的片段。
創(chuàng)建不同的變量杨赤,將它們分配給類型字符串敞斋。 它們被設(shè)置為final截汪,因?yàn)槲覀冎辉O(shè)置一次值。 如果您想了解有關(guān)dart中不同變量類型的更多信息渺尘,請(qǐng)查看dart變量介紹視頻
class ChatModel {
? final String username;
? final String message;?
? final String time;
? final String avatarurl;
}
很好挫鸽,聲明了變量,我們現(xiàn)在可以將它傳遞給類的構(gòu)造函數(shù)
這是通過(guò)以下代碼行完成的
ChatModel({this.username, this.message, this.time, this.avatarurl});
接下來(lái)鸥跟,我們繼續(xù)創(chuàng)建一個(gè)聊天列表丢郊。 為此,我們創(chuàng)建一個(gè)名為data的變量医咨,它將是List類型枫匾。 該列表將是ChatModel類型。 這可確保輸入的數(shù)據(jù)遵循類中列出的格式拟淮。
```
List data = [
?new ChatModel(
?? username: 'Nash',
?? message: 'Flutter is soooo cool :)',
?? time: '20:20',
? avatarurl: 'https://pbs.twimg.com/profile_images/945767488087715840/OP_ZIptm_400x400.jpg'
?),
?new ChatModel(
?? username: 'Han Solo',
?? message: 'That is not how the force works ',
? time: '20:20',
? avatarurl: 'https://pbs.twimg.com/profile_images/760249570085314560/yCrkrbl3_400x400.jpg'?
?),
? new ChatModel(
?? username: 'Ethan',
?? message: 'why hello there',
? time: '20:20',
? avatarurl: 'https://s-media-cache-ak0.pinimg.com/originals/d4/c3/ee/d4c3ee93cca0bba877318989b46b39d6.jpg'
?),
? new ChatModel(
?? username: 'Sam',
?? message: 'Lorem ipsum delor sit amet...',
? time: '20:20',
? avatarurl: 'http://clipart-library.com/images/kTMKzGyMc.jpg'
?),
? new ChatModel(
?? username: 'Ava',
?? message: 'AOT is better than JIT ;)',
? time: '20:20',
? avatarurl: 'http://clipart-library.com/images/kTMKzGyMc.jpg'
?),
? new ChatModel(
?? username: 'Jbird',
?? message: 'Stop camping in fortnite Idiot',
? time: '20:20',
? avatarurl: 'https://s-media-cache-ak0.pinimg.com/originals/d4/c3/ee/d4c3ee93cca0bba877318989b46b39d6.jpg'
?),
?? new ChatModel(
?? username: 'Jake',
?? message: 'Flutter is the best!',
? time: '20:20',
? avatarurl: 'http://clipart-library.com/images/kTMKzGyMc.jpg'
?),] ;
```
在上面的代碼中干茉,我們創(chuàng)建了七個(gè)帶有消息的用戶。 每個(gè)模型都遵循我們創(chuàng)建的格式很泊。 您可以編輯此項(xiàng)以包含任意數(shù)量的用戶角虫。 使用創(chuàng)建聊天的模板,我們現(xiàn)在可以移動(dòng)到實(shí)際列表視圖委造。
列表視圖
首先戳鹅,我們打開(kāi)chat_screen.dart并導(dǎo)入剛剛創(chuàng)建的文件。
`import '../model/chat_model.dart';
`
接下來(lái)昏兆,我們將小部件從Stateless更改為Stateful
從
```
class ChatScreen extends StatelessWidget {
? @override
? Widget build(BuildContext context){
? ? return new Container(
? ? ? child: new Center(
? ? ? ? child: new Text('Hello from Chat Screen ', style: new TextStyle(fontSize: 20.0),),
? ? ? )
? ? );
? }
}
```
到
```
class ChatScreen extends StatefulWidget {
? _ChatScreen createState() => new _ChatScreen();
}
class _ChatScreen extends State {
? @override
? Widget build(BuildContext context) {
? ? return new Container();
? }
}
```
是時(shí)候去玩有趣的東西枫虏,用ListView.builder替換Container。 ListView允許我們?cè)谄聊簧巷@示滾動(dòng)的小部件數(shù)組爬虱。 它有許多不同的屬性隶债,但我們將要使用的是itemCount和itemBuilder。 itemCount不應(yīng)等于零跑筝。 itemBuilder用于構(gòu)建列表的項(xiàng)目死讹。 它需要一種與Stateful和Stateless小部件非常相似的構(gòu)建方法。 主要區(qū)別在于添加索引變量继蜡。
Stateless/Stateful
`(BuildContext context)`
itemBuilder
`(BuildContext context, int index)
`
修改ChatScreen
```
class ChatScreen extends StatefulWidget {
? _ChatScreen createState() => new _ChatScreen();
}
class _ChatScreen extends State {
? @override
? Widget build(BuildContext context) {
? ? return new Container();
? }
}
```
To
```
class ChatScreen extends StatefulWidget {
? _ChatScreen createState() => new _ChatScreen();
}
class _ChatScreen extends State {
? @override
? Widget build(BuildContext context) {
? ? return new ListView.builder(
? ? ? itemCount:?
?? ? ? itemBuilder: (BuildContext context, int index) {}
? ? );
? }
}
```
對(duì)于我們的itemCount回俐,我們將使用之前創(chuàng)建的數(shù)據(jù)列表的長(zhǎng)度。 只需data.length的值
接下來(lái)稀并,我們將處理聊天項(xiàng)目仅颇。 在itemBuilder中,創(chuàng)建一個(gè)新列碘举。 該列是一個(gè)小部件忘瓦,它在垂直數(shù)組中顯示其子節(jié)點(diǎn)。
? 正如您在WhatsApp中所注意到的那樣,每條聊天都有一條細(xì)細(xì)的灰色線條耕皮。 要鏡像此效果境蜕,我們使用Divider小部件。 這個(gè)小部件允許我們用屏幕分隔屏幕上的元素凌停。 高度粱年,顏色和縮進(jìn)都可以改變,現(xiàn)在罚拟,我們只需要設(shè)置10.0的高度(數(shù)字必須是小數(shù)值)台诗。
? 創(chuàng)建Divider后,我們將移至ListTile赐俗。 這是另一個(gè)預(yù)制的Flutter小部件拉队,它易于使用但功能非常強(qiáng)大。 有不同的屬性阻逮,如leading, title 和 subtitle都'baked in'粱快。 在Divider下,我們通過(guò)鍵入新的ListTile()來(lái)創(chuàng)建小部件叔扼。
?您的_ChatScreen類應(yīng)如下所示
```
?class _ChatScreen extends State {
? @override
? Widget build(BuildContext context) {
? ? return new ListView.builder(
? ? ? itemCount: data.length,
? ? ? itemBuilder: (BuildContext context, int index) {
? ? ? ? return new Column(
? ? ? ? ? children: [
? ? ? ? ? ? new Divider(
? ? ? ? ? ? ? height: 10.0,
? ? ? ? ? ? ),
? ? ? ? ? ? new ListTile(
? ? ? ? ? ? ),
? ? ? ? ? ],
? ? ? ? );
? ? ? },
? ? );
? }
}
```
首先事哭,我們從Circle Avatar開(kāi)始。 這是消息左側(cè)的圖片瓜富,以用戶的圖片為特色慷蠕。 這在Flutter中創(chuàng)建非常簡(jiǎn)單。 在列表磁貼中食呻,我們將leading屬性設(shè)置為新的Circle頭像。 然后我們指定它的背景顏色和背景圖像澎现。 背景顏色可以是您喜歡的任何顏色仅胞,在此示例中我使用灰色。 對(duì)于背景圖像剑辫,我們使用網(wǎng)絡(luò)圖像干旧。 傳入我們數(shù)據(jù)列表中的頭像URL。使用以下代碼完成:
```
new ListTile(?
?leading: new CircleAvatar(
?backgroundColor: Colors.grey,?
?backgroundImage: new NetworkImage(data[index].avatarurl),?
?),
```
注意對(duì)于NetworkImage妹蔽,我們指定data [index]椎眯。 傳遞的索引來(lái)自itemBuilder中創(chuàng)建的索引。 對(duì)于每次迭代胳岂,索引都會(huì)改變编整。
創(chuàng)建我們的頭像后,我們會(huì)將注意力轉(zhuǎn)移到用戶名和時(shí)間/日期乳丰。 由于這兩個(gè)位于同一行掌测,我們可以使用Row小部件。 這與列非常相似产园,除了不是垂直對(duì)齊汞斧,小部件水平對(duì)齊夜郁。
```
title: new Row(
? ? mainAxisAlignment: MainAxisAlignment.spaceBetween,
? ? children: [
? ? ? new Text(data[index].username,
? ? ? ? ? style: new TextStyle(fontWeight: FontWeight.bold)),
? ? ? new Text(data[index].time,
? ? ? ? ? style: new TextStyle(color: Colors.grey, fontSize: 14.0))
? ? ],
? ),
```
同樣,我們使用數(shù)據(jù)列表中的信息粘勒,傳入索引竞端。 此外,我們使用Text小部件的style屬性來(lái)相應(yīng)地設(shè)置它們的樣式庙睡。
最后事富,消息片段。 為此埃撵,我們將使用subtitle屬性赵颅。 創(chuàng)建一個(gè)容器窗口小部件,它將在文本窗口小部件的頂部添加5.0填充暂刘,該窗口小部件將分配給其子窗口饺谬。 “文本”窗口小部件將顯示該用戶的數(shù)據(jù)列表中的消息。 索引再次傳入谣拣。文本的樣式也會(huì)更改募寨,以便增加字體大小和不同顏色。
您的文件現(xiàn)在應(yīng)該如下所示
```
import 'package:flutter/material.dart';
import '../model/chat_model.dart';
class ChatScreen extends StatefulWidget {
? _ChatScreen createState() => new _ChatScreen();
}
class _ChatScreen extends State {
? @override
? Widget build(BuildContext context) {
? ? return new ListView.builder(
? ? ? itemCount: data.length,
? ? ? itemBuilder: (BuildContext context, int index) {
? ? ? ? return new Column(
? ? ? ? ? children: [
? ? ? ? ? ? new Divider(
? ? ? ? ? ? ? height: 10.0,
? ? ? ? ? ? ),
? ? ? ? ? ? new ListTile(
? ? ? ? ? ? ? leading: new CircleAvatar(
? ? ? ? ? ? ? ? backgroundColor: Colors.grey,
? ? ? ? ? ? ? ? backgroundImage: new NetworkImage(data[index].avatarurl),
? ? ? ? ? ? ? ),
? ? ? ? ? ? ? title: new Row(
? ? ? ? ? ? ? ? mainAxisAlignment: MainAxisAlignment.spaceBetween,
? ? ? ? ? ? ? ? children: [
? ? ? ? ? ? ? ? ? new Text(data[index].username,
? ? ? ? ? ? ? ? ? ? ? style: new TextStyle(fontWeight: FontWeight.bold)),
? ? ? ? ? ? ? ? ? new Text(data[index].time,
? ? ? ? ? ? ? ? ? ? ? style: new TextStyle(color: Colors.grey, fontSize: 14.0))
? ? ? ? ? ? ? ? ],
? ? ? ? ? ? ? ),
? ? ? ? ? ? ? subtitle: new Container(
? ? ? ? ? ? ? ? ? padding: const EdgeInsets.only(top: 5.0),
? ? ? ? ? ? ? ? ? child: new Text(data[index].message,style: new TextStyle(color: Colors.grey, fontSize: 15.0) ), ),
? ? ? ? ? ? )
? ? ? ? ? ],
? ? ? ? );
? ? ? },
? ? );
? }
}
```
現(xiàn)在森缠,如果你重新加載你的應(yīng)用程序拔鹰,你應(yīng)該看到一個(gè)可操作的,可滾動(dòng)的聊天列表贵涵。