This is the 13th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021.
1. The macro definition
We use some common classes in our project, such as our iOS macro definition, and have similar ones in Flutter. We create a file directly, similar to our iOS header file, and then define some common classes, such as colors, title styles, etc. When using option+ Enter automatically import error can be
Color ThemeColor = const Color.fromRGBO(220.220.220.1.0);
TextStyle TitleStyle = const TextStyle(fontSize: 16,fontWeight: FontWeight.bold,color: Colors.black);
Copy the code
2. The navigation bar
appBar: AppBar(
title: const Text('Contacts Page'),
centerTitle: true,
elevation: 0.0,
backgroundColor: ThemeColor,
actions: [
GestureDetector(
onTap: (){
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => DiscoverChildPage("Add a friend")));
},
child:Container(
padding: EdgeInsets.only(right: 15),
child: Image.asset('images/icon_friends_add.png',width: 30,),
)
),
],
leading: IconButton(onPressed: (){
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => DiscoverChildPage("More")));
}, icon: Icon(Icons.menu)) ,
),
Copy the code
Mainly introduce actions and leading
actions
Is aAn array of
Element is a controlwidget
We’re adding one
Equivalent to rightButtonItems in the iOS navigation bar we can add multiple Widege
- leading
Equivalent to the navigation bar left control returns a widget
leading: IconButton(onPressed: (){
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => DiscoverChildPage("More")));
}, icon: Icon(Icons.menu)) ,
Copy the code
If you add 2, you need to pay attention to the size. Here I directly use IconButton size error report
3. Data processing
We define the data
class Friends {
Friends({this.imageUrl, this.name, this.indexLetter, this.imageAssets});
final String? imageAssets;
final String? imageUrl;
final String? name;
final String? indexLetter;
}
List<Friends> datas = [
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/27.jpg',
name: 'Lina',
indexLetter: 'L'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/17.jpg',
name: 'and',
indexLetter: 'F'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/16.jpg',
name: 'AnLi',
indexLetter: 'A'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/men/31.jpg',
name: 'pell',
indexLetter: 'A'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/22.jpg',
name: 'Bella',
indexLetter: 'B'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/37.jpg',
name: 'Lina',
indexLetter: 'L'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/18.jpg',
name: 'Nancy',
indexLetter: 'N'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/men/47.jpg',
name: '扣扣',
indexLetter: 'K'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/men/3.jpg',
name: 'Jack',
indexLetter: 'J'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/5.jpg',
name: 'Emma',
indexLetter: 'E'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/24.jpg',
name: 'Abby',
indexLetter: 'A'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/men/15.jpg',
name: 'Betty',
indexLetter: 'B'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/men/13.jpg',
name: 'Tony',
indexLetter: 'T'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/men/26.jpg',
name: 'Jerry',
indexLetter: 'J'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/men/36.jpg',
name: 'Colin',
indexLetter: 'C'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/12.jpg',
name: 'Haha',
indexLetter: 'H'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/11.jpg',
name: 'Ketty',
indexLetter: 'K'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/13.jpg',
name: 'Lina',
indexLetter: 'L'),
Friends(
imageUrl: 'https://randomuser.me/api/portraits/women/23.jpg',
name: 'Lina',
indexLetter: 'L')];Copy the code
The data contains a fixed header of the top 4 and the following contacts
final List<Friends> _headerData = [
Friends(imageAssets: 'Images/new friend.png', name: 'New friends'),
Friends(imageAssets: 'images/group chat. PNG', name: 'chatting'),
Friends(imageAssets: 'images/tag. PNG', name: 'tags'),
Friends(imageAssets: 'images/ public number.png ', name: 'Public Account')];Copy the code
4. Create a Cell
Cell is a header view that contains an avatar, a title, an underscore, and a group
class FriendCell extends StatelessWidget {
FriendCell({this.imageUrl, this.name, this.groupTitle, this.imageAssets});
final String? imageUrl;
final String? name;
final String? groupTitle;
final String? imageAssets;
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
// The header is not displayed without a headerContainer( child: groupTitle ! =null? Text(groupTitle! ,style: TextStyle(color: Colors.grey),) :null, height: groupTitle ! =null ?30:0,
color: ThemeColor,
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: 15),
),
Container(/ / cell content
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(margin: EdgeInsets.all(10),child:imageAssets == null? Image.network(imageUrl! ,width:34,height: 34,) : Image.asset(imageAssets!) ,height:34,width: 34,),/ / avatar
Container(
alignment: Alignment.centerLeft,
width: screenWidth(context) - 54,
child: Column(
children: [
Container(alignment: Alignment.centerLeft,padding: EdgeInsets.only(left: 15),child: Text(name! ,style: TitleStyle,),height:54,),/ / name
Container(color: ThemeColor,height: 0.5() [() [() [() [() [() [() [() [() }}Copy the code
We define the listView and use the listView. builder form to handle it, similar to our iOS cell reuse representation rather than static cells
- itemBuilder
We define the header array and the contact number group, and the data is the one we defined before
final List<Friends> _headerData = [
Friends(imageAssets: 'Images/new friend.png', name: 'New friends'),
Friends(imageAssets: 'images/group chat. PNG', name: 'chatting'),
Friends(imageAssets: 'images/tag. PNG', name: 'tags'),
Friends(imageAssets: 'images/ public number.png ', name: 'Public Account')];final List<Friends> _listDatas = [];
Widget _itemBuilder(BuildContext context, int index) {
if (index < _headerData.length) {
/ / before four
return FriendCell(imageAssets: _headerData[index].imageAssets,
name: _headerData[index].name,);
} else {
returnFriendCell(imageAssets: _listDatas[index - _headerData.length].imageAssets, name: _listDatas[index - _headerData.length].name,); }}Copy the code
Here’s the distinction, the first four and the last. In a listView display
child: ListView.builder(itemBuilder: _itemBuilder,
itemCount: _headerData.length+_listDatas.length,
Copy the code
The effect is roughly as follows
Let’s add the _listDatas data
@override
void initState() {
// TODO: implement initState
super.initState(); _listDatas .. addAll(datas) .. addAll(datas);/ / sorting
_listDatas.sort((Friends a, Friends b) {
returna.indexLetter! .compareTo(b.indexLetter!) ; }); }Copy the code
When we initialize the state, we add and process the data, sort the array using the sort method, compare their first letters and sort them in order.
- Grouping title
Our cell will only be displayed when the group title is passed in, so we only need to compare each element of the current array with the next one. If the first letter is the same, we will not display it
bool isHideGroupTitle = (index -_headerData.length>0 &&_listDatas[index-_headerData.length].indexLetter == _listDatas[index-_headerData.length- 1].indexLetter);
Copy the code
The header group is fixed. If index =4, then index – _headerdata. length>0 is false. So the show head
Widget _itemBuilder(BuildContext context, int index) {
bool isHideGroupTitle = (index -_headerData.length>0 &&_listDatas[index-_headerData.length].indexLetter == _listDatas[index-_headerData.length- 1].indexLetter);
if (index < _headerData.length) {
/ / before four
return FriendCell(imageAssets: _headerData[index].imageAssets,
name: _headerData[index].name,);
} else {
return FriendCell(
imageUrl: _listDatas[index - _headerData.length].imageUrl,
name: _listDatas[index - _headerData.length].name,
groupTitle: isHideGroupTitle?null: _listDatas[index - _headerData.length ].indexLetter,); }}Copy the code
The next article realizes the right indicator bar, and the linkage of the indicator bar.