聊天列表优化,适配.
This commit is contained in:
parent
0a226a06c8
commit
e4bb070d08
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 26 KiB |
|
|
@ -4,6 +4,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
|||
import 'package:expandable_text/expandable_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
|
||||
|
||||
import '../../beans/character_info_bean.dart';
|
||||
import '../../beans/chat_info_bean.dart';
|
||||
|
|
@ -52,12 +53,15 @@ class _ChatPageState extends State<ChatPage> {
|
|||
|
||||
int delIndex = 0;
|
||||
|
||||
///聊天列表滑动到底部
|
||||
void _scrollToBottom() {
|
||||
_scrollController.animateTo(
|
||||
_scrollController.position.maxScrollExtent,
|
||||
curve: Curves.easeOut,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
);
|
||||
Future.delayed(Duration(milliseconds: 300), () {
|
||||
_scrollController.animateTo(
|
||||
_scrollController.position.maxScrollExtent,
|
||||
curve: Curves.easeOut,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -77,9 +81,7 @@ class _ChatPageState extends State<ChatPage> {
|
|||
chatList.addAll(newData['data']);
|
||||
EasyLoading.dismiss();
|
||||
setState(() {});
|
||||
Future.delayed(Duration(milliseconds: 100), () {
|
||||
_scrollToBottom();
|
||||
});
|
||||
_scrollToBottom();
|
||||
break;
|
||||
case "sendMessage":
|
||||
sendMessageBean = newData['data'];
|
||||
|
|
@ -122,6 +124,21 @@ class _ChatPageState extends State<ChatPage> {
|
|||
}
|
||||
});
|
||||
|
||||
// 创建键盘可见性监测器
|
||||
final keyboardVisibilityController = KeyboardVisibilityController();
|
||||
// 订阅键盘可见性变化
|
||||
keyboardVisibilityController.onChange.listen((bool visible) {
|
||||
// 在这里处理键盘可见性变化的逻辑
|
||||
if (visible) {
|
||||
// 键盘弹出时的处理逻辑
|
||||
print('Keyboard is visible');
|
||||
_scrollToBottom();
|
||||
} else {
|
||||
// 键盘隐藏时的处理逻辑
|
||||
print('Keyboard is hidden');
|
||||
}
|
||||
});
|
||||
|
||||
loadData();
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +172,9 @@ class _ChatPageState extends State<ChatPage> {
|
|||
children: [
|
||||
characterInfoBean != null && characterInfoBean?.bgUrl != null
|
||||
? CachedNetworkImage(
|
||||
fit: BoxFit.fitHeight,
|
||||
fit: BoxFit.cover,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
imageUrl: "${characterInfoBean?.bgUrl}",
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
|
||||
import '../../beans/category_info_list_bean.dart';
|
||||
import '../chat/chat_page.dart';
|
||||
import 'find_model.dart';
|
||||
|
||||
class MultiplexPage extends StatefulWidget {
|
||||
|
|
@ -51,6 +52,16 @@ class _MultiplexPageState extends State<MultiplexPage> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
goChatPage(String id) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ChatPage(
|
||||
characterId: id,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
|
|
@ -64,69 +75,75 @@ class _MultiplexPageState extends State<MultiplexPage> {
|
|||
}
|
||||
|
||||
_item(index, CategoryInfoListBean data) {
|
||||
return Container(
|
||||
height: 130,
|
||||
width: 50,
|
||||
margin: EdgeInsets.only(bottom: 23),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFF202021),
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
border: Border.all(color: Color(0xFF7E7E7E), width: 0.3),
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned(
|
||||
left: 7,
|
||||
child: CachedNetworkImage(
|
||||
width: 83,
|
||||
height: 115,
|
||||
imageUrl: data.iconImage!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {
|
||||
goChatPage(data.id.toString());
|
||||
},
|
||||
child: Container(
|
||||
height: 130,
|
||||
width: 50,
|
||||
margin: EdgeInsets.only(bottom: 23),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFF202021),
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
border: Border.all(color: Color(0xFF7E7E7E), width: 0.3),
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned(
|
||||
left: 7,
|
||||
child: CachedNetworkImage(
|
||||
width: 83,
|
||||
height: 115,
|
||||
imageUrl: data.iconImage!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 101,
|
||||
top: 19,
|
||||
child: Text(
|
||||
'${data.name}',
|
||||
style: TextStyle(color: Colors.white, fontSize: 14),
|
||||
)),
|
||||
Positioned(
|
||||
left: 101,
|
||||
top: 45,
|
||||
child: SizedBox(
|
||||
width: 200,
|
||||
height: 16,
|
||||
child: ListView.builder(
|
||||
itemCount: data.label?.length,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: 11),
|
||||
margin: EdgeInsets.only(right: 5),
|
||||
decoration: BoxDecoration(border: Border.all(color: Color(0xFFFF9000)), borderRadius: BorderRadius.all(Radius.circular(7))),
|
||||
child: Text(
|
||||
'${data.label?[index].name}',
|
||||
style: TextStyle(fontSize: 10, color: Color(0xFFFF9000)),
|
||||
),
|
||||
);
|
||||
}),
|
||||
)),
|
||||
Positioned(
|
||||
left: 102,
|
||||
top: 70,
|
||||
child: Container(
|
||||
width: 200,
|
||||
Positioned(
|
||||
left: 101,
|
||||
top: 19,
|
||||
child: Text(
|
||||
maxLines: 3,
|
||||
'${data.biography}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Colors.white, fontSize: 10),
|
||||
),
|
||||
))
|
||||
],
|
||||
'${data.name}',
|
||||
style: TextStyle(color: Colors.white, fontSize: 14),
|
||||
)),
|
||||
Positioned(
|
||||
left: 101,
|
||||
top: 45,
|
||||
child: SizedBox(
|
||||
width: 200,
|
||||
height: 16,
|
||||
child: ListView.builder(
|
||||
itemCount: data.label?.length,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: 11),
|
||||
margin: EdgeInsets.only(right: 5),
|
||||
decoration: BoxDecoration(border: Border.all(color: Color(0xFFFF9000)), borderRadius: BorderRadius.all(Radius.circular(7))),
|
||||
child: Text(
|
||||
'${data.label?[index].name}',
|
||||
style: TextStyle(fontSize: 10, color: Color(0xFFFF9000)),
|
||||
),
|
||||
);
|
||||
}),
|
||||
)),
|
||||
Positioned(
|
||||
left: 102,
|
||||
top: 70,
|
||||
child: Container(
|
||||
width: 200,
|
||||
child: Text(
|
||||
maxLines: 3,
|
||||
'${data.biography}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Colors.white, fontSize: 10),
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import 'package:flutter_easyloading/flutter_easyloading.dart';
|
|||
import '../../beans/find_banner_bean.dart';
|
||||
import '../../beans/recommend_bean.dart';
|
||||
import '../../custom/custom_swiper_pagination.dart';
|
||||
import '../chat/chat_page.dart';
|
||||
import 'find_model.dart';
|
||||
|
||||
///推荐
|
||||
|
|
@ -18,7 +19,7 @@ class RecommendPage extends StatefulWidget {
|
|||
State<RecommendPage> createState() => _RecommendPageState();
|
||||
}
|
||||
|
||||
class _RecommendPageState extends State<RecommendPage> {
|
||||
class _RecommendPageState extends State<RecommendPage> with AutomaticKeepAliveClientMixin {
|
||||
late StreamSubscription subscription;
|
||||
|
||||
final FindModel _viewmodel = FindModel();
|
||||
|
|
@ -74,6 +75,16 @@ class _RecommendPageState extends State<RecommendPage> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
goChatPage(String id) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ChatPage(
|
||||
characterId: id,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
|
|
@ -92,10 +103,15 @@ class _RecommendPageState extends State<RecommendPage> {
|
|||
return Container(
|
||||
key: ValueKey<int>(index),
|
||||
padding: EdgeInsets.only(bottom: 30),
|
||||
child: CachedNetworkImage(
|
||||
fit: BoxFit.fill,
|
||||
imageUrl: bannerList[index].imageUrl!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
goChatPage(bannerList[index].actionId.toString());
|
||||
},
|
||||
child: CachedNetworkImage(
|
||||
fit: BoxFit.fill,
|
||||
imageUrl: bannerList[index].imageUrl!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
@ -115,19 +131,35 @@ class _RecommendPageState extends State<RecommendPage> {
|
|||
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 21),
|
||||
height: 360,
|
||||
child: ListView.builder(
|
||||
itemCount: recommendList.length,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return _item(index, recommendList[index]);
|
||||
}),
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Container(
|
||||
// width: 500,
|
||||
alignment: Alignment.centerLeft,
|
||||
margin: EdgeInsets.only(top: 21),
|
||||
padding: EdgeInsets.only(left: 16),
|
||||
height: 330,
|
||||
child: GridView.count(
|
||||
shrinkWrap: true,
|
||||
//水平子Widget之间间距
|
||||
crossAxisSpacing: 12.0,
|
||||
//垂直子Widget之间间距
|
||||
mainAxisSpacing: 9.0,
|
||||
//GridView内边距
|
||||
padding: EdgeInsets.zero,
|
||||
//一行的Widget数量
|
||||
crossAxisCount: 2,
|
||||
//子Widget宽高比例
|
||||
childAspectRatio: 1.4,
|
||||
//子Widget列表
|
||||
children: _item(recommendList),
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
//类似 cellForRow 函数
|
||||
scrollDirection: Axis.horizontal)),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
margin: EdgeInsets.only(left: 16),
|
||||
margin: EdgeInsets.only(left: 16, top: 34),
|
||||
child: Text(
|
||||
'热门小说角色',
|
||||
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||
|
|
@ -150,48 +182,17 @@ class _RecommendPageState extends State<RecommendPage> {
|
|||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_item(int index, RecommendBean data) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(right: 9, left: index == 0 ? 16 : 0),
|
||||
child: Column(
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(15)),
|
||||
child: CachedNetworkImage(
|
||||
width: 113,
|
||||
height: 159,
|
||||
fit: BoxFit.fill,
|
||||
imageUrl: data.imageUrl!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 7,
|
||||
bottom: 21,
|
||||
child: Text(
|
||||
'${data.name}',
|
||||
style: TextStyle(color: Colors.white, fontSize: 12),
|
||||
)),
|
||||
Positioned(
|
||||
left: 7,
|
||||
bottom: 9,
|
||||
child: Container(
|
||||
width: 105,
|
||||
child: Text(
|
||||
'${data.biography}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Color(0xFFC2C2C2), fontSize: 9),
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 12),
|
||||
_item(List<RecommendBean> list) {
|
||||
return list.map((res) {
|
||||
int index = recommendList.indexOf(res);
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
goChatPage(res.id.toString());
|
||||
},
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
// margin: EdgeInsets.only(right: 9, left: 16),
|
||||
child: Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
|
|
@ -200,7 +201,7 @@ _item(int index, RecommendBean data) {
|
|||
width: 113,
|
||||
height: 159,
|
||||
fit: BoxFit.fill,
|
||||
imageUrl: data.imageUrl!,
|
||||
imageUrl: res.imageUrl!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
),
|
||||
),
|
||||
|
|
@ -208,7 +209,7 @@ _item(int index, RecommendBean data) {
|
|||
left: 7,
|
||||
bottom: 21,
|
||||
child: Text(
|
||||
'${data.name}',
|
||||
'${res.name}',
|
||||
style: TextStyle(color: Colors.white, fontSize: 12),
|
||||
)),
|
||||
Positioned(
|
||||
|
|
@ -217,7 +218,7 @@ _item(int index, RecommendBean data) {
|
|||
child: Container(
|
||||
width: 105,
|
||||
child: Text(
|
||||
'${data.biography}',
|
||||
'${res.biography}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Color(0xFFC2C2C2), fontSize: 9),
|
||||
|
|
@ -225,80 +226,90 @@ _item(int index, RecommendBean data) {
|
|||
)),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_item2(index, RecommendBean data) {
|
||||
return Container(
|
||||
height: 130,
|
||||
width: 50,
|
||||
margin: EdgeInsets.only(bottom: 20),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFF202021),
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
border: Border.all(color: Color(0xFF7E7E7E), width: 0.3),
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned(
|
||||
left: 7,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(15)),
|
||||
child: CachedNetworkImage(
|
||||
width: 83,
|
||||
height: 115,
|
||||
fit: BoxFit.fill,
|
||||
imageUrl: data.imageUrl!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 101,
|
||||
top: 19,
|
||||
child: Text(
|
||||
'${data.name}',
|
||||
style: TextStyle(color: Colors.white, fontSize: 14),
|
||||
)),
|
||||
Positioned(
|
||||
left: 101,
|
||||
top: 45,
|
||||
child: SizedBox(
|
||||
width: 200,
|
||||
height: 16,
|
||||
child: ListView.builder(
|
||||
itemCount: data.label?.length,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: 11),
|
||||
margin: EdgeInsets.only(right: 5),
|
||||
decoration: BoxDecoration(border: Border.all(color: Color(0xFFFF9000)), borderRadius: BorderRadius.all(Radius.circular(7))),
|
||||
child: Text(
|
||||
'${data.label?[index].name}',
|
||||
style: TextStyle(fontSize: 10, color: Color(0xFFFF9000)),
|
||||
),
|
||||
);
|
||||
}),
|
||||
)),
|
||||
Positioned(
|
||||
left: 102,
|
||||
top: 70,
|
||||
child: Container(
|
||||
width: 200,
|
||||
child: Text(
|
||||
maxLines: 3,
|
||||
'${data.biography}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Colors.white, fontSize: 10),
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
_item2(index, RecommendBean data) {
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {
|
||||
goChatPage(data.id.toString());
|
||||
},
|
||||
child: Container(
|
||||
height: 130,
|
||||
width: 50,
|
||||
margin: EdgeInsets.only(bottom: 20),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFF202021),
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
border: Border.all(color: Color(0xFF7E7E7E), width: 0.3),
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned(
|
||||
left: 7,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(15)),
|
||||
child: CachedNetworkImage(
|
||||
width: 83,
|
||||
height: 115,
|
||||
fit: BoxFit.fill,
|
||||
imageUrl: data.imageUrl!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
),
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
),
|
||||
Positioned(
|
||||
left: 101,
|
||||
top: 19,
|
||||
child: Text(
|
||||
'${data.name}',
|
||||
style: TextStyle(color: Colors.white, fontSize: 14),
|
||||
)),
|
||||
Positioned(
|
||||
left: 101,
|
||||
top: 45,
|
||||
child: SizedBox(
|
||||
width: 200,
|
||||
height: 16,
|
||||
child: ListView.builder(
|
||||
itemCount: data.label?.length,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: 11),
|
||||
margin: EdgeInsets.only(right: 5),
|
||||
decoration: BoxDecoration(border: Border.all(color: Color(0xFFFF9000)), borderRadius: BorderRadius.all(Radius.circular(7))),
|
||||
child: Text(
|
||||
'${data.label?[index].name}',
|
||||
style: TextStyle(fontSize: 10, color: Color(0xFFFF9000)),
|
||||
),
|
||||
);
|
||||
}),
|
||||
)),
|
||||
Positioned(
|
||||
left: 102,
|
||||
top: 70,
|
||||
child: Container(
|
||||
width: 200,
|
||||
child: Text(
|
||||
maxLines: 3,
|
||||
'${data.biography}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Colors.white, fontSize: 10),
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
// TODO: implement wantKeepAlive
|
||||
bool get wantKeepAlive => true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@ import 'package:cached_network_image/cached_network_image.dart';
|
|||
import 'package:expandable_text/expandable_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
|
||||
|
||||
import '../../beans/character_info_bean.dart';
|
||||
import '../../beans/chat_info_bean.dart';
|
||||
import '../../beans/send_message_bean.dart';
|
||||
import '../../network/NetworkConfig.dart';
|
||||
import '../chat/chat_info_page.dart';
|
||||
import '../chat/chat_model.dart';
|
||||
|
||||
|
|
@ -20,7 +22,7 @@ class HomeChatPage extends StatefulWidget {
|
|||
State<HomeChatPage> createState() => _HomeChatPageState();
|
||||
}
|
||||
|
||||
class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClientMixin {
|
||||
class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClientMixin, WidgetsBindingObserver {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
final TextEditingController _chatController = TextEditingController();
|
||||
|
||||
|
|
@ -69,9 +71,7 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
|
|||
case "getChatInfo":
|
||||
chatList.addAll(newData['data']);
|
||||
setState(() {});
|
||||
Future.delayed(Duration(milliseconds: 100), () {
|
||||
_scrollToBottom();
|
||||
});
|
||||
_scrollToBottom();
|
||||
EasyLoading.dismiss();
|
||||
break;
|
||||
case "sendMessage":
|
||||
|
|
@ -115,6 +115,21 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
|
|||
}
|
||||
});
|
||||
|
||||
// 创建键盘可见性监测器
|
||||
final keyboardVisibilityController = KeyboardVisibilityController();
|
||||
// 订阅键盘可见性变化
|
||||
keyboardVisibilityController.onChange.listen((bool visible) {
|
||||
// 在这里处理键盘可见性变化的逻辑
|
||||
if (visible) {
|
||||
// 键盘弹出时的处理逻辑
|
||||
print('Keyboard is visible');
|
||||
_scrollToBottom();
|
||||
} else {
|
||||
// 键盘隐藏时的处理逻辑
|
||||
print('Keyboard is hidden');
|
||||
}
|
||||
});
|
||||
|
||||
loadData();
|
||||
}
|
||||
|
||||
|
|
@ -131,12 +146,15 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
|
|||
_viewmodel.delChatByIds(ids, widget.characterId);
|
||||
}
|
||||
|
||||
///聊天列表滑动到底部
|
||||
void _scrollToBottom() {
|
||||
_scrollController.animateTo(
|
||||
_scrollController.position.maxScrollExtent,
|
||||
curve: Curves.easeOut,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
);
|
||||
Future.delayed(Duration(milliseconds: 300), () {
|
||||
_scrollController.animateTo(
|
||||
_scrollController.position.maxScrollExtent,
|
||||
curve: Curves.easeOut,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -151,339 +169,364 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return Stack(
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
fit: BoxFit.fitHeight,
|
||||
imageUrl: characterInfoBean.bgUrl!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: 311.67,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [Color(0x00000000), Color(0xFF0C0909)], // 三色渐变数组
|
||||
begin: Alignment.topCenter, // 渐变开始位置
|
||||
end: Alignment.bottomCenter, // 渐变结束位置
|
||||
return Scaffold(
|
||||
backgroundColor: Color(0xFF121213),
|
||||
body: Stack(
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
fit: BoxFit.cover,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
imageUrl: characterInfoBean.bgUrl!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: 311.67,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [Color(0x00000000), Color(0xFF0C0909)], // 三色渐变数组
|
||||
begin: Alignment.topCenter, // 渐变开始位置
|
||||
end: Alignment.bottomCenter, // 渐变结束位置
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
Container(
|
||||
child: Column(
|
||||
children: [
|
||||
///title
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 30,
|
||||
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top + 9, left: 16, right: 16),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 105,
|
||||
child: Text(
|
||||
"+1",
|
||||
style: TextStyle(color: Color(0xFFF14476), fontSize: 10),
|
||||
)),
|
||||
Positioned(
|
||||
left: 0,
|
||||
child: Container(
|
||||
width: 101,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(color: Color(0x33000000), borderRadius: BorderRadius.all(Radius.circular(14))),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
///AI头像
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ChatInfoPage(
|
||||
data: characterInfoBean,
|
||||
)),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(left: 2),
|
||||
child: CachedNetworkImage(
|
||||
width: 23,
|
||||
imageUrl: characterInfoBean.icon!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
)),
|
||||
Container(
|
||||
child: Column(
|
||||
children: [
|
||||
///title
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 30,
|
||||
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top + 9, left: 16, right: 16),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 105,
|
||||
child: Text(
|
||||
"+1",
|
||||
style: TextStyle(color: Color(0xFFF14476), fontSize: 10),
|
||||
)),
|
||||
Positioned(
|
||||
left: 0,
|
||||
child: Container(
|
||||
width: 101,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(color: Color(0x33000000), borderRadius: BorderRadius.all(Radius.circular(14))),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
///AI头像
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (NetworkConfig.userId == "") {
|
||||
Navigator.of(context).pushNamed('/LoginPage');
|
||||
return;
|
||||
}
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ChatInfoPage(
|
||||
data: characterInfoBean,
|
||||
)),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(left: 2),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||
child: CachedNetworkImage(
|
||||
width: 23,
|
||||
height: 23,
|
||||
imageUrl: characterInfoBean.icon!,
|
||||
errorWidget: (context, url, error) => const Icon(Icons.error),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
///AI名
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 35,
|
||||
child: Text(
|
||||
characterInfoBean.characterName!,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 10, color: Colors.white),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${characterInfoBean.lookCount} 聊过',
|
||||
style: TextStyle(fontSize: 7, color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
///心动值
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 6, right: 6),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => ChatPage(
|
||||
// characterId: characterInfoBean.characterId.toString(),
|
||||
// )),
|
||||
// );
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
///AI名
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image(
|
||||
width: 24,
|
||||
height: 21,
|
||||
image: AssetImage('assets/images/ic_beckoning.png'),
|
||||
SizedBox(
|
||||
width: 35,
|
||||
child: Text(
|
||||
characterInfoBean.characterName!,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 10, color: Colors.white),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
characterInfoBean.intimacy.toString(),
|
||||
style: TextStyle(fontSize: 8, color: Colors.white),
|
||||
)
|
||||
'${characterInfoBean.lookCount} 聊过',
|
||||
style: TextStyle(fontSize: 7, color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
///关注
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
isHalf = !isHalf;
|
||||
setState(() {});
|
||||
},
|
||||
child: Container(
|
||||
width: 50,
|
||||
height: 24,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(color: Color(0x33000000), borderRadius: BorderRadius.all(Radius.circular(12))),
|
||||
child: Text(
|
||||
'+ 关注',
|
||||
style: TextStyle(fontSize: 12, color: Colors.white),
|
||||
///心动值
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 6, right: 6),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => ChatPage(
|
||||
// characterId: characterInfoBean.characterId.toString(),
|
||||
// )),
|
||||
// );
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Image(
|
||||
width: 24,
|
||||
height: 21,
|
||||
image: AssetImage('assets/images/ic_beckoning.png'),
|
||||
),
|
||||
Text(
|
||||
characterInfoBean.intimacy.toString(),
|
||||
style: TextStyle(fontSize: 8, color: Colors.white),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
isHalf
|
||||
? Container(
|
||||
height: MediaQuery.of(context).size.height / 3.5,
|
||||
)
|
||||
: Container(),
|
||||
|
||||
///聊天列表
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemCount: chatList.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return _item(index);
|
||||
})),
|
||||
Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
margin: EdgeInsets.only(left: 16, bottom: 3),
|
||||
child: Image(width: 63, height: 18, image: AssetImage('assets/images/ic_memory.png')),
|
||||
),
|
||||
|
||||
///输入 功能
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
margin: EdgeInsets.only(left: 16, right: 16, bottom: !isMore ? 60 : 0),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
///输入框
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
decoration: const BoxDecoration(
|
||||
color: Color(0x33FFFFFF),
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
///关注
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (NetworkConfig.userId == "") {
|
||||
Navigator.of(context).pushNamed('/LoginPage');
|
||||
return;
|
||||
}
|
||||
isHalf = !isHalf;
|
||||
setState(() {});
|
||||
},
|
||||
child: Container(
|
||||
width: 50,
|
||||
height: 24,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(color: Color(0x33000000), borderRadius: BorderRadius.all(Radius.circular(12))),
|
||||
child: Text(
|
||||
'+ 关注',
|
||||
style: TextStyle(fontSize: 12, color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(left: 15),
|
||||
child: TextField(
|
||||
controller: _chatController,
|
||||
onChanged: _textFieldChanged,
|
||||
maxLines: null,
|
||||
cursorColor: const Color(0xFFFF9000),
|
||||
decoration: const InputDecoration(
|
||||
border: InputBorder.none,
|
||||
// 移除非聚焦状态下的边框
|
||||
enabledBorder: InputBorder.none,
|
||||
// 移除获得焦点但未输入内容时的边框
|
||||
focusedBorder: InputBorder.none,
|
||||
isCollapsed: true,
|
||||
// 移除输入时的边框
|
||||
hintText: "打个招呼吧...",
|
||||
hintStyle: TextStyle(color: Color(0xFFB6B6B6), fontSize: 13),
|
||||
],
|
||||
),
|
||||
),
|
||||
isHalf
|
||||
? Container(
|
||||
height: MediaQuery.of(context).size.height / 3.5,
|
||||
)
|
||||
: Container(),
|
||||
|
||||
///聊天列表
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemCount: chatList.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return _item(index);
|
||||
})),
|
||||
Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
margin: EdgeInsets.only(left: 16, bottom: 3),
|
||||
child: Image(width: 63, height: 18, image: AssetImage('assets/images/ic_memory.png')),
|
||||
),
|
||||
|
||||
///输入 功能
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
margin: EdgeInsets.only(left: 16, right: 16, bottom: !isMore ? 60 : 0),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
///输入框
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
decoration: const BoxDecoration(
|
||||
color: Color(0x33FFFFFF),
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(left: 15),
|
||||
child: TextField(
|
||||
controller: _chatController,
|
||||
onChanged: _textFieldChanged,
|
||||
maxLines: null,
|
||||
cursorColor: const Color(0xFFFF9000),
|
||||
decoration: const InputDecoration(
|
||||
border: InputBorder.none,
|
||||
// 移除非聚焦状态下的边框
|
||||
enabledBorder: InputBorder.none,
|
||||
// 移除获得焦点但未输入内容时的边框
|
||||
focusedBorder: InputBorder.none,
|
||||
isCollapsed: true,
|
||||
// 移除输入时的边框
|
||||
hintText: "打个招呼吧...",
|
||||
hintStyle: TextStyle(color: Color(0xFFB6B6B6), fontSize: 13),
|
||||
),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
///发送
|
||||
Container(
|
||||
margin: const EdgeInsets.only(right: 7),
|
||||
child: text == ""
|
||||
? const Image(
|
||||
width: 27,
|
||||
image: AssetImage('assets/images/ic_send_n.png'),
|
||||
)
|
||||
: GestureDetector(
|
||||
onTap: () {
|
||||
EasyLoading.show(status: 'loading...');
|
||||
chatList.add(ChatInfoBean(0, "user", text, "timestamp", "claudeType", 0, "userIcon"));
|
||||
_viewmodel.sendMessage(widget.characterId, text);
|
||||
_chatController.clear();
|
||||
text = "";
|
||||
Future.delayed(Duration(milliseconds: 200), () {
|
||||
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
|
||||
});
|
||||
setState(() {});
|
||||
},
|
||||
child: Image(
|
||||
///发送
|
||||
Container(
|
||||
margin: const EdgeInsets.only(right: 7),
|
||||
child: text == ""
|
||||
? const Image(
|
||||
width: 27,
|
||||
image: AssetImage('assets/images/ic_send.png'),
|
||||
image: AssetImage('assets/images/ic_send_n.png'),
|
||||
)
|
||||
: GestureDetector(
|
||||
onTap: () {
|
||||
if (NetworkConfig.userId == "") {
|
||||
Navigator.of(context).pushNamed('/LoginPage');
|
||||
return;
|
||||
}
|
||||
EasyLoading.show(status: 'loading...');
|
||||
chatList.add(ChatInfoBean(0, "user", text, "timestamp", "claudeType", 0, "userIcon"));
|
||||
_viewmodel.sendMessage(widget.characterId, text);
|
||||
_chatController.clear();
|
||||
text = "";
|
||||
Future.delayed(Duration(milliseconds: 200), () {
|
||||
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
|
||||
});
|
||||
setState(() {});
|
||||
},
|
||||
child: Image(
|
||||
width: 27,
|
||||
image: AssetImage('assets/images/ic_send.png'),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
|
||||
///智能输入
|
||||
Container(
|
||||
margin: const EdgeInsets.only(left: 14, right: 14),
|
||||
child: GestureDetector(
|
||||
///智能输入
|
||||
Container(
|
||||
margin: const EdgeInsets.only(left: 14, right: 14),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed('/LoginPage');
|
||||
},
|
||||
child: Image(
|
||||
width: 27,
|
||||
image: AssetImage('assets/images/ic_smart_chat.png'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
///功能 更多
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed('/LoginPage');
|
||||
if (NetworkConfig.userId == "") {
|
||||
Navigator.of(context).pushNamed('/LoginPage');
|
||||
return;
|
||||
}
|
||||
isMore = !isMore;
|
||||
setState(() {});
|
||||
},
|
||||
child: Image(
|
||||
width: 27,
|
||||
image: AssetImage('assets/images/ic_smart_chat.png'),
|
||||
image: AssetImage('assets/images/ic_more.png'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
///功能 更多
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
isMore = !isMore;
|
||||
setState(() {});
|
||||
},
|
||||
child: Image(
|
||||
width: 27,
|
||||
image: AssetImage('assets/images/ic_more.png'),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
isMore
|
||||
? Container(
|
||||
height: 70,
|
||||
alignment: Alignment.centerLeft,
|
||||
margin: EdgeInsets.only(left: 16, right: 16, bottom: 60),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 23),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image(width: 26, image: AssetImage('assets/images/ic_album.png')),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 9),
|
||||
child: Text(
|
||||
'角色相册',
|
||||
style: TextStyle(fontSize: 10, color: Color(0xFFA2A2A2)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 23),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
EasyLoading.show(status: 'loading...');
|
||||
_viewmodel.delChat(widget.characterId);
|
||||
},
|
||||
isMore
|
||||
? Container(
|
||||
height: 70,
|
||||
alignment: Alignment.centerLeft,
|
||||
margin: EdgeInsets.only(left: 16, right: 16, bottom: 60),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 23),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image(width: 26, height: 26, image: AssetImage('assets/images/ic_restart.png')),
|
||||
Image(width: 26, image: AssetImage('assets/images/ic_album.png')),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 9),
|
||||
child: Text(
|
||||
'重启对话',
|
||||
'角色相册',
|
||||
style: TextStyle(fontSize: 10, color: Color(0xFFA2A2A2)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
],
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 23),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
EasyLoading.show(status: 'loading...');
|
||||
_viewmodel.delChat(widget.characterId);
|
||||
},
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image(width: 26, height: 26, image: AssetImage('assets/images/ic_restart.png')),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 9),
|
||||
child: Text(
|
||||
'重启对话',
|
||||
style: TextStyle(fontSize: 10, color: Color(0xFFA2A2A2)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
///记忆提升中
|
||||
Positioned(
|
||||
top: 65,
|
||||
left: 16,
|
||||
child: Image(
|
||||
width: 47,
|
||||
height: 12,
|
||||
image: AssetImage('assets/images/ic_memory_p.png'),
|
||||
)),
|
||||
],
|
||||
///记忆提升中
|
||||
Positioned(
|
||||
top: (MediaQuery.of(context).padding.top) * 2 + 10,
|
||||
left: 16,
|
||||
child: Image(
|
||||
width: 47,
|
||||
height: 12,
|
||||
image: AssetImage('assets/images/ic_memory_p.png'),
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'dart:io';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:talk/network/NetworkConfig.dart';
|
||||
import 'package:talk/tools/home/my_home_page.dart';
|
||||
import 'package:talk/tools/me/me_page.dart';
|
||||
import 'package:talk/tools/message/message_page.dart';
|
||||
|
|
@ -74,6 +75,11 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
|
|||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (NetworkConfig.userId == "") {
|
||||
Navigator.of(context).pushNamed('/LoginPage');
|
||||
return;
|
||||
}
|
||||
|
||||
currentIndex = 1;
|
||||
_tabController.animateTo(1);
|
||||
setState(() {});
|
||||
|
|
@ -89,6 +95,10 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
|
|||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (NetworkConfig.userId == "") {
|
||||
Navigator.of(context).pushNamed('/LoginPage');
|
||||
return;
|
||||
}
|
||||
currentIndex = 2;
|
||||
_tabController.animateTo(2);
|
||||
setState(() {});
|
||||
|
|
@ -100,6 +110,10 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
|
|||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (NetworkConfig.userId == "") {
|
||||
Navigator.of(context).pushNamed('/LoginPage');
|
||||
return;
|
||||
}
|
||||
currentIndex = 3;
|
||||
_tabController.animateTo(3);
|
||||
setState(() {});
|
||||
|
|
|
|||
|
|
@ -105,168 +105,169 @@ class _LoginPageState extends State<LoginPage> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Image(fit: BoxFit.fill, image: AssetImage('assets/images/login_bj.png')),
|
||||
Positioned(
|
||||
left: 22,
|
||||
top: 28,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Image(
|
||||
height: 23,
|
||||
image: AssetImage('assets/images/ic_left_arrow.png'),
|
||||
),
|
||||
)),
|
||||
Positioned(
|
||||
left: 36,
|
||||
top: 76,
|
||||
child: Text(
|
||||
'妙语',
|
||||
style: TextStyle(color: Colors.white, fontSize: 33),
|
||||
)),
|
||||
Positioned(
|
||||
left: 36,
|
||||
top: 115,
|
||||
child: Text(
|
||||
'登陆 / 注册',
|
||||
style: TextStyle(color: Color(0xFFD5D5D5), fontSize: 18),
|
||||
)),
|
||||
Positioned(
|
||||
bottom: 35,
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
isCheck = !isCheck;
|
||||
setState(() {});
|
||||
},
|
||||
child: Image(width: 16, image: isCheck ? AssetImage('assets/images/ic_ck_s.png') : AssetImage('assets/images/ic_ck.png')),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 10),
|
||||
child: RichText(
|
||||
text: TextSpan(children: <TextSpan>[
|
||||
TextSpan(text: '我已阅读并同意', style: TextStyle(fontSize: 12, color: Color(0xFF5F5F5F))),
|
||||
TextSpan(text: '用户协议', style: TextStyle(fontSize: 12, color: Color(0xFFFF9000))),
|
||||
TextSpan(text: '和', style: TextStyle(fontSize: 12, color: Color(0xFF5F5F5F))),
|
||||
TextSpan(text: '隐私协议', style: TextStyle(fontSize: 12, color: Color(0xFFFF9000))),
|
||||
]),
|
||||
body: SingleChildScrollView(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Image(fit: BoxFit.cover, height: MediaQuery.of(context).size.height, image: AssetImage('assets/images/login_bj.png')),
|
||||
Positioned(
|
||||
left: 22,
|
||||
top: MediaQuery.of(context).padding.top + 9,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Image(
|
||||
height: 23,
|
||||
image: AssetImage('assets/images/ic_left_arrow.png'),
|
||||
),
|
||||
)),
|
||||
Positioned(
|
||||
left: 36,
|
||||
top: 76,
|
||||
child: Text(
|
||||
'妙语',
|
||||
style: TextStyle(color: Colors.white, fontSize: 33),
|
||||
)),
|
||||
Positioned(
|
||||
left: 36,
|
||||
top: 115,
|
||||
child: Text(
|
||||
'登陆 / 注册',
|
||||
style: TextStyle(color: Color(0xFFD5D5D5), fontSize: 18),
|
||||
)),
|
||||
Positioned(
|
||||
bottom: 35,
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
isCheck = !isCheck;
|
||||
setState(() {});
|
||||
},
|
||||
child: Image(width: 16, image: isCheck ? AssetImage('assets/images/ic_ck_s.png') : AssetImage('assets/images/ic_ck.png')),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
Positioned(
|
||||
bottom: 70,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (phoneText != "" && codeText != "") {
|
||||
if (isCheck) {
|
||||
EasyLoading.showToast("登录");
|
||||
_viewmodel.login(phoneText, codeText, 0,
|
||||
"eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJOaWNrTmFtZSI6IuaWsOeUqOaItyIsIlVzZXJJZCI6IjMiLCJleHAiOjE3MjEyMjQzNjksImlzcyI6Ikh1YW5NZW5nIiwiYXVkIjoiSHVhbk1lbmdBcHAifQ.gxf2y47qWuNtEf2xvGSG6ATEgaXOrTWbJpi_Bp6eU2k");
|
||||
} else {
|
||||
EasyLoading.showToast("请选中协议");
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 10),
|
||||
child: RichText(
|
||||
text: TextSpan(children: <TextSpan>[
|
||||
TextSpan(text: '我已阅读并同意', style: TextStyle(fontSize: 12, color: Color(0xFF5F5F5F))),
|
||||
TextSpan(text: '用户协议', style: TextStyle(fontSize: 12, color: Color(0xFFFF9000))),
|
||||
TextSpan(text: '和', style: TextStyle(fontSize: 12, color: Color(0xFF5F5F5F))),
|
||||
TextSpan(text: '隐私协议', style: TextStyle(fontSize: 12, color: Color(0xFFFF9000))),
|
||||
]),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
Positioned(
|
||||
bottom: 70,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (phoneText != "" && codeText != "") {
|
||||
if (isCheck) {
|
||||
EasyLoading.showToast("登录");
|
||||
_viewmodel.login(phoneText, codeText, 1, "");
|
||||
} else {
|
||||
EasyLoading.showToast("请选中协议");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
child: Container(
|
||||
height: 43,
|
||||
width: 288,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(phoneText != "" && codeText != "" ? 0xFFFF9000 : 0xFFAC6D1C),
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
),
|
||||
child: Text(
|
||||
'登录',
|
||||
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
)),
|
||||
Positioned(
|
||||
bottom: 125,
|
||||
child: Container(
|
||||
height: 43,
|
||||
width: 288,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(phoneText != "" && codeText != "" ? 0xFFFF9000 : 0xFFAC6D1C),
|
||||
color: Color(0x33FFFFFF),
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
),
|
||||
child: Text(
|
||||
'登录',
|
||||
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
)),
|
||||
Positioned(
|
||||
bottom: 125,
|
||||
child: Container(
|
||||
height: 43,
|
||||
width: 288,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0x33FFFFFF),
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 17, bottom: 6),
|
||||
child: TextField(
|
||||
controller: _codeController,
|
||||
onChanged: _codeChanged,
|
||||
cursorColor: Color(0xFFFF9000),
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
hintText: "请输入验证码",
|
||||
hintStyle: TextStyle(color: Color(0xFFB5B5B5), fontSize: 15),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 17, bottom: 6),
|
||||
child: TextField(
|
||||
controller: _codeController,
|
||||
onChanged: _codeChanged,
|
||||
cursorColor: Color(0xFFFF9000),
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
hintText: "请输入验证码",
|
||||
hintStyle: TextStyle(color: Color(0xFFB5B5B5), fontSize: 15),
|
||||
),
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (!_isCountingDown) {
|
||||
getCode();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(right: 14),
|
||||
child: Text(
|
||||
!_isCountingDown ? "获取验证码" : "$_timeLeft后重新获取",
|
||||
style: TextStyle(fontSize: 15, color: Color(0xFFB5B5B5)),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (!_isCountingDown) {
|
||||
getCode();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(right: 14),
|
||||
child: Text(
|
||||
!_isCountingDown ? "获取验证码" : "$_timeLeft后重新获取",
|
||||
style: TextStyle(fontSize: 15, color: Color(0xFFB5B5B5)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)),
|
||||
Positioned(
|
||||
bottom: 178,
|
||||
child: Container(
|
||||
height: 43,
|
||||
width: 288,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.only(left: 17, bottom: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0x33FFFFFF),
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
),
|
||||
child: TextField(
|
||||
controller: _phoneController,
|
||||
onChanged: _phoneChanged,
|
||||
cursorColor: Color(0xFFFF9000),
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
hintText: "请输入手机号",
|
||||
hintStyle: TextStyle(color: Color(0xFFB5B5B5), fontSize: 15),
|
||||
],
|
||||
),
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
)),
|
||||
],
|
||||
)),
|
||||
Positioned(
|
||||
bottom: 178,
|
||||
child: Container(
|
||||
height: 43,
|
||||
width: 288,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.only(left: 17, bottom: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0x33FFFFFF),
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
),
|
||||
child: TextField(
|
||||
controller: _phoneController,
|
||||
onChanged: _phoneChanged,
|
||||
cursorColor: Color(0xFFFF9000),
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
hintText: "请输入手机号",
|
||||
hintStyle: TextStyle(color: Color(0xFFB5B5B5), fontSize: 15),
|
||||
),
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,9 +61,10 @@ class _StartPageState extends State<StartPage> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Image(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
fit: BoxFit.cover,
|
||||
image: AssetImage('assets/images/img_start.png'),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ dependencies:
|
|||
expandable_text: ^2.3.0
|
||||
card_swiper: ^3.0.1
|
||||
flutter_slidable: ^3.1.0
|
||||
flutter_keyboard_visibility: ^6.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user