下面是我的页面的源代码,代码很简单不进行详述了。
import 'package:flutter/material.dart';
import 'package:wechat_demo/pages/discover/discover_cell.dart';
class MinePage extends StatefulWidget {
String name = '周佳兴';
String weChatNum = '微信号: 天青色无敌';
@override
_MinePageState createState() => _MinePageState();
}
class _MinePageState extends State<MinePage> {
Widget headWidget() {
return Container(
color: Colors.white,
height: 200,
child: Container(
// color: Colors.yellow,
margin: EdgeInsets.only(top: 100, bottom: 20),
padding: EdgeInsets.all(10),
child: Container(
// color: Colors.blue,
child: Row(
children: [
Container(
width: 50, height: 50,
margin: EdgeInsets.only(left: 20),
padding: EdgeInsets.all(5),
// child: Image(
// image: AssetImage('images/截屏2021-01-05 下午7.12.15.png'),
// ), // 图片不能设置圆角
// 设置圆角
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
image: AssetImage('images/截屏2021-01-05 下午7.12.15.png'),
fit: BoxFit.fill)), // 设置填充模式
),
Container(
// color: Colors.red,
margin: EdgeInsets.only(left: 10, right: 5),
width: MediaQuery.of(context).size.width - 115,
child: Column(
textBaseline: TextBaseline.alphabetic,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
// margin: EdgeInsets.only(left: 10),
child: Text(
widget.name,
style: TextStyle(
fontSize: 25,
color: Colors.black,
),
),
),
Container(
child: Row(
children: [
Text(
widget.weChatNum,
style: TextStyle(
fontSize: 14,
color: Colors.grey,
),
),
Image(
image: AssetImage('images/icon_right.png'),
width: 15,
),
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
)
],
),
),
],
),
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Container(
color: Color.fromRGBO(220, 220, 220, 1),
child: MediaQuery.removePadding(
// 去掉默认的刘海
removeTop: true,
context: context,
child: ListView(
children: [
headWidget(),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/微信 支付.png',
title: '支付',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/微信收藏.png',
title: '收藏',
),
Row(
children: [
Container(
width: 50,
height: 0.5,
color: Colors.white,
),
],
),
DiscoverCell(
imageName: 'images/微信相册.png',
title: '朋友圈',
),
Row(
children: [
Container(
width: 50,
height: 0.5,
color: Colors.white,
),
],
),
DiscoverCell(
imageName: 'images/微信卡包.png',
title: '卡包',
),
Row(
children: [
Container(
width: 50,
height: 0.5,
color: Colors.white,
),
],
),
DiscoverCell(
imageName: 'images/微信表情.png',
title: '表情',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/微信设置.png',
title: '设置',
),
],
),
)), // 列表
Container(
margin: EdgeInsets.only(right: 10, top: 40),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Image(image: AssetImage('images/相机.png')),
],
),
color: Color.fromRGBO(0, 0, 0, 0),
height: 25,
), // 相机
],
),
);
}
}
下面是通讯里页面源码
先说一下通讯录页面简单思路:
通讯录页面有导航、列表、索引条,我的思路为:导航包裹一个Stack小部件,Stack 部件包裹 ListView和索引条部件。
Scaffold(
AppBar:
body: Stack (
children:[
ListView.builder(),
Container()]
)
)
下面是主页面
import 'package:flutter/material.dart';
import 'package:wechat_demo/const.dart';
import 'package:wechat_demo/pages/discover/discover_child_page.dart';
import 'package:wechat_demo/pages/friends/friend_bar.dart';
import 'package:wechat_demo/pages/pages.friends/friends_data.dart';
class FriendPage extends StatefulWidget {
@override
_FriendPageState createState() => _FriendPageState();
}
class _FriendPageState extends State<FriendPage> {
// 字典放 item 和高度的对应数据
final Map groupOffSetMap = {
// INDEX_WORDS[0]: 0.0,
// INDEX_WORDS[1]: 0.0,
};
ScrollController scrollerController;
final List<Friends> _headerData = [
Friends(imageUrl: 'images/新的朋友.png', name: '新的朋友'),
Friends(imageUrl: 'images/群聊.png', name: '群聊'),
Friends(imageUrl: 'images/标签.png', name: '标签'),
Friends(imageUrl: 'images/公众号.png', name: '公众号'),
];
List<Friends> newDatas = [];
@override
void initState() {
// TODO: implement initState
super.initState();
newDatas.addAll(datas);
newDatas.addAll(datas);
newDatas..addAll(datas);
newDatas.sort((Friends a, Friends b) {
return a.indexLetter.compareTo(b.indexLetter);
});
var groupOffset = 54.5 * 4;
for (var item in newDatas) {
int index = newDatas.indexOf(item);
if (index < 1 && groupOffSetMap[item.indexLetter] == null) {
groupOffSetMap.addAll({item.indexLetter: groupOffset});
groupOffset += 84.5;
} else if (groupOffSetMap[item.indexLetter] != null) {
groupOffset += 54.5;
} else if (groupOffSetMap[item.indexLetter] == null) {
groupOffSetMap.addAll({item.indexLetter: groupOffset});
groupOffset += 84.5;
}
}
scrollerController = ScrollController();
}
@override
Widget build(BuildContext context) {
Widget _itemForRow(BuildContext context, int index) {
if (index < _headerData.length) {
return _FriendCell(
imageAssets: _headerData[index].imageUrl,
name: _headerData[index].name,
);
}
bool hideIndexLetter = index - 5 >= 0 &&
newDatas[index - 4].indexLetter == newDatas[index - 5].indexLetter;
return _FriendCell(
imageUrl: newDatas[index - 4].imageUrl,
name: newDatas[index - 4].name,
groupTitle: hideIndexLetter ? null : newDatas[index - 4].indexLetter,
);
}
return Scaffold(
appBar: AppBar(
backgroundColor: weChatThemColor,
title: Text(
'通讯录',
style: TextStyle(color: Colors.black),
),
actions: [
GestureDetector(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => DiscoverChildPage(
title: '添加朋友',
),
));
},
child: Container(
margin: EdgeInsets.only(right: 10),
child: Image(
image: AssetImage('images/icon_friends_add.png'),
width: 25,
),
),
)
],
),
body: Stack(
children: [
ListView.builder(
controller: scrollerController, // 控制滚动的
itemCount: _headerData.length + newDatas.length,
itemBuilder: _itemForRow,
),
FriendBar(
friendBarCallBack: (str) {
if (groupOffSetMap[str] == null) {
return;
}
;
scrollerController.animateTo(groupOffSetMap[str],
duration: Duration(microseconds: 100),
curve: Curves.easeIn);
},
),
],
));
}
}
class _FriendCell extends StatelessWidget {
final String imageUrl;
final String name;
final String groupTitle;
final String imageAssets;
const _FriendCell(
{this.imageUrl, this.name, this.groupTitle, this.imageAssets});
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: 10),
height: groupTitle != null ? 30 : 0,
color: Color.fromRGBO(1, 1, 1, 0),
child: groupTitle != null
? Text(
groupTitle,
style: TextStyle(color: Colors.grey),
)
: null,
),
Container(
color: Colors.white,
child: Row(
children: [
Container(
margin: EdgeInsets.all(10),
width: 34,
height: 34,
decoration: BoxDecoration(
image: DecorationImage(
image: imageUrl != null
? NetworkImage(imageUrl)
: AssetImage(imageAssets)),
borderRadius: BorderRadius.circular(6))),
Container(
child: Text(
name,
style: TextStyle(fontSize: 17),
),
),
],
),
),
Container(
height: 0.5,
color: weChatThemColor,
margin: EdgeInsets.only(left: 50),
)
],
);
}
}
下面是自定义搜索条
import 'package:flutter/material.dart';
import 'package:wechat_demo/const.dart';
class FriendBar extends StatefulWidget {
final void Function(String str) friendBarCallBack;
FriendBar({this.friendBarCallBack});
@override
_FriendBarState createState() => _FriendBarState();
}
class _FriendBarState extends State<FriendBar> {
Color bColor = Color.fromRGBO(1, 1, 1, 0);
Color textColor = Colors.black;
double indicatorY = 0;
String indictorText = 'A';
bool indocatorHidden = true;
int getIndex(BuildContext context, Offset globalPosition) {
// 坐标转换
RenderBox box = context.findRenderObject();
// 转换为当前视图的位置, details.globalPosition 是相对于全屏幕的
double y = box.globalToLocal(globalPosition).dy;
var itemHeight = ScreenHeight(context) / 2 / INDEX_WORDS.length;
int index = (y ~/ itemHeight).clamp(0, INDEX_WORDS.length - 1);
return index;
}
@override
Widget build(BuildContext context) {
List<Widget> words = [];
for (var item in INDEX_WORDS) {
words.add(Expanded(
child: Text(
item,
style: TextStyle(fontSize: 10, color: textColor),
)));
}
return Container(
child: Positioned(
child: Row(
children: [
Container(
alignment: Alignment(0, indicatorY),
width: 100,
child: Stack(
alignment: Alignment(-0.2, 0),
children: indocatorHidden
? []
: [
Image(
image: AssetImage('images/气泡.png'),
width: 60,
),
Text(indictorText),
],
),
),
GestureDetector(
onVerticalDragUpdate: (details) {
setState(() {
int index = getIndex(context, details.globalPosition);
widget.friendBarCallBack(INDEX_WORDS[index]);
indocatorHidden = false;
indictorText =
INDEX_WORDS[getIndex(context, details.globalPosition)];
indicatorY =
2.2 / 26 * getIndex(context, details.globalPosition) -
1.1;
});
},
onVerticalDragDown: (details) {
setState(() {
bColor = Color.fromRGBO(1, 1, 1, 0.5);
textColor = Colors.white;
indocatorHidden = false;
indictorText =
INDEX_WORDS[getIndex(context, details.globalPosition)];
indicatorY =
2.2 / 26 * getIndex(context, details.globalPosition) -
1.1;
});
},
onVerticalDragEnd: (details) {
setState(() {
bColor = Color.fromRGBO(1, 1, 1, 0);
textColor = Colors.black;
indocatorHidden = true;
});
},
child: Container(
width: 20,
color: bColor,
child: Column(
children: words,
),
),
),
],
),
right: 0,
bottom: ScreenHeight(context) / 8,
height: ScreenHeight(context) / 2,
width: 120,
),
);
}
}
const INDEX_WORDS = [
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'y',
'Z'
];
网友评论