Browse Source

完成广场排版

ios
王子贤 3 months ago
parent
commit
4daef13fdd
15 changed files with 1144 additions and 20 deletions
  1. BIN
      assets/images/comment_icon.png
  2. BIN
      assets/images/img.png
  3. BIN
      assets/images/like_icon.png
  4. BIN
      assets/images/publish.png
  5. 21
      lib/controller/home/home_controller.dart
  6. 107
      lib/controller/home/send_timeline_controller.dart
  7. 7
      lib/generated/assets.dart
  8. 156
      lib/pages/home/all_timeline.dart
  9. 16
      lib/pages/home/home_page.dart
  10. 92
      lib/pages/home/recommend_window.dart
  11. 263
      lib/pages/home/send_timeline.dart
  12. 212
      lib/pages/home/timeline_info.dart
  13. 119
      lib/pages/home/timeline_item.dart
  14. 111
      lib/pages/home/timeline_window.dart
  15. 60
      lib/pages/main/main_page.dart

BIN
assets/images/comment_icon.png

Before After
Width: 62  |  Height: 62  |  Size: 1000 B

BIN
assets/images/img.png

Before After
Width: 80  |  Height: 70  |  Size: 1.1 KiB

BIN
assets/images/like_icon.png

Before After
Width: 55  |  Height: 50  |  Size: 824 B

BIN
assets/images/publish.png

Before After
Width: 238  |  Height: 238  |  Size: 12 KiB

21
lib/controller/home/home_controller.dart

@ -21,7 +21,11 @@ class HomeController extends GetxController {
//
final selectedTabIndex = 0.obs;
final topTab = 0.obs;
final timelineTab = 0.obs;
//
final pageSize = 10;
@ -268,6 +272,21 @@ class HomeController extends GetxController {
update();
}
void setTopTab(int index) {
print('Setting selected tab index to: $index');
topTab.value = index;
// UI能够更新
update();
}
void setTimelineTab(int index) {
print('Setting selected tab index to: $index');
timelineTab.value = index;
// UI能够更新
update();
}
///
List<MarriageData> getFeedListByTab(int tabIndex) {
return tabIndex == 0 ? List.from(recommendFeed) : List.from(nearbyFeed);

107
lib/controller/home/send_timeline_controller.dart

@ -0,0 +1,107 @@
import 'package:dating_touchme_app/config/emoji_config.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
class SendTimelineController extends GetxController {
final title = "".obs;
final message = ''.obs;
final TextEditingController messageController = TextEditingController();
final focusNode = FocusNode().obs;
final isEmojiVisible = false.obs;
@override
void onInit() {
super.onInit();
focusNode.value.addListener(() {
if (focusNode.value.hasFocus) {
//
isEmojiVisible.value = false;
}
});
}
@override
void onClose() {
super.onClose();
focusNode.value.dispose();
}
void toggleEmojiPanel() {
isEmojiVisible.value = !isEmojiVisible.value;
FocusManager.instance.primaryFocus?.unfocus();
}
void handleEmojiSelected(EmojiItem emoji) {
//
final currentText = messageController.text;
final emojiText = '[emoji:${emoji.id}]';
messageController.text = currentText + emojiText;
//
messageController.selection = TextSelection.fromPosition(
TextPosition(offset: messageController.text.length),
);
}
/// +
List<Widget> buildInputContentWidgets() {
final List<Widget> widgets = [];
final text = messageController.value.text;
final RegExp emojiRegex = RegExp(r'\[emoji:(\d+)\]');
int lastMatchEnd = 0;
final matches = emojiRegex.allMatches(text);
for (final match in matches) {
//
if (match.start > lastMatchEnd) {
final textPart = text.substring(lastMatchEnd, match.start);
widgets.add(
Text(
textPart,
style: TextStyle(fontSize: 14.sp, color: Colors.black),
),
);
}
//
final emojiId = match.group(1);
if (emojiId != null) {
final emoji = EmojiConfig.getEmojiById(emojiId);
if (emoji != null) {
widgets.add(
Padding(
padding: EdgeInsets.symmetric(horizontal: 2.w),
child: Image.asset(
emoji.path,
width: 24.w,
height: 24.w,
fit: BoxFit.contain,
),
),
);
}
}
lastMatchEnd = match.end;
}
//
if (lastMatchEnd < text.length) {
final textPart = text.substring(lastMatchEnd);
widgets.add(
Text(
textPart,
style: TextStyle(fontSize: 14.sp, color: Colors.black),
),
);
}
return widgets;
}
}

7
lib/generated/assets.dart

@ -94,6 +94,7 @@ class Assets {
static const String imagesChatUserBgBottom = 'assets/images/chat_user_bg_bottom.png';
static const String imagesCheck = 'assets/images/check.png';
static const String imagesCloseArrow = 'assets/images/close_arrow.png';
static const String imagesCommentIcon = 'assets/images/comment_icon.png';
static const String imagesCustomer = 'assets/images/customer.png';
static const String imagesDiscoverNol = 'assets/images/discover_nol.png';
static const String imagesDiscoverPre = 'assets/images/discover_pre.png';
@ -124,8 +125,11 @@ class Assets {
static const String imagesHiIcon = 'assets/images/hi_icon.png';
static const String imagesHomeNol = 'assets/images/home_nol.png';
static const String imagesHomePre = 'assets/images/home_pre.png';
static const String imagesImCoinIcon = 'assets/images/im_coin_icon.png';
static const String imagesImg = 'assets/images/img.png';
static const String imagesInformationBg = 'assets/images/information_bg.png';
static const String imagesLastMsgIcon = 'assets/images/last_msg_icon.png';
static const String imagesLikeIcon = 'assets/images/like_icon.png';
static const String imagesLimitTime = 'assets/images/limit_time.png';
static const String imagesLiveIcon = 'assets/images/live_icon.png';
static const String imagesLocationIcon = 'assets/images/location_icon.png';
@ -163,6 +167,7 @@ class Assets {
static const String imagesPlatVoiceMessageSelf = 'assets/images/plat_voice_message_self.png';
static const String imagesPlayIcon = 'assets/images/play_icon.png';
static const String imagesPlayer = 'assets/images/player.png';
static const String imagesPublish = 'assets/images/publish.png';
static const String imagesQuestionIcon = 'assets/images/question_icon.png';
static const String imagesRealChecked = 'assets/images/real_checked.png';
static const String imagesRealName = 'assets/images/real_name.png';
@ -221,5 +226,5 @@ class Assets {
static const String imagesWallet = 'assets/images/wallet.png';
static const String imagesWechatPay = 'assets/images/wechat_pay.png';
static const String imagesWomenIcon = 'assets/images/women_icon.png';
static const String imagesImCoinIcon = 'assets/images/im_coin_icon.png';
}

156
lib/pages/home/all_timeline.dart

@ -0,0 +1,156 @@
import 'package:dating_touchme_app/pages/home/timeline_item.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:dating_touchme_app/controller/home/home_controller.dart';
import 'package:dating_touchme_app/pages/home/content_card.dart';
/// Tab
class AllTimeline extends StatefulWidget {
const AllTimeline({super.key});
@override
State<AllTimeline> createState() => _AllTimelineState();
}
class _AllTimelineState extends State<AllTimeline>
with AutomaticKeepAliveClientMixin {
final HomeController controller = Get.find<HomeController>();
late final EasyRefreshController _refreshController;
@override
void initState() {
super.initState();
_refreshController = EasyRefreshController(controlFinishRefresh: true, controlFinishLoad: true);
}
@override
void dispose() {
_refreshController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);
// tabbar 64
final bottomPadding = MediaQuery.of(context).padding.bottom;
final tabBarHeight = 64.0;
final totalBottomPadding = bottomPadding + tabBarHeight;
return Obx(() {
if (controller.recommendIsLoading.value && controller.recommendFeed.isEmpty) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 16),
Text('加载数据中...'),
],
),
);
}
return EasyRefresh(
controller: _refreshController,
header: const ClassicHeader(
dragText: '下拉刷新',
armedText: '释放刷新',
readyText: '刷新中...',
processingText: '刷新中...',
processedText: '刷新完成',
failedText: '刷新失败',
noMoreText: '没有更多数据',
showMessage: false
),
footer: ClassicFooter(
dragText: '上拉加载',
armedText: '释放加载',
readyText: '加载中...',
processingText: '加载中...',
processedText: '加载完成',
failedText: '加载失败',
noMoreText: '没有更多数据',
showMessage: false
),
//
onRefresh: () async {
print('推荐列表下拉刷新被触发');
try {
await controller.refreshRecommendData();
print( '推荐列表刷新完成, hasMore: $controller.recommendHasMore.value');
_refreshController.finishRefresh();
_refreshController.resetFooter();
} catch (e) {
print('推荐列表刷新失败: $e');
_refreshController.finishRefresh(IndicatorResult.fail);
}
},
//
onLoad: () async {
print('推荐列表上拉加载被触发, hasMore: $controller.recommendHasMore.value');
try {
await controller.loadRecommendMoreData();
//
if (controller.recommendHasMore.value) {
_refreshController.finishLoad(IndicatorResult.success);
print('推荐列表加载更多成功');
} else {
_refreshController.finishLoad(IndicatorResult.noMore);
print('推荐列表没有更多数据了');
}
} catch (e) {
print('推荐列表加载更多失败: $e');
_refreshController.finishLoad(IndicatorResult.fail);
}
},
child: ListView.separated(
// 使
// padding AppBar
padding: EdgeInsets.only(left: 12, right: 12),
itemBuilder: (context, index) {
//
if (controller.recommendFeed.isEmpty && index == 0) {
// 使
if (controller.recommendIsLoading.value) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 16),
Text('加载数据中...'),
],
),
);
} else {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('暂无数据'),
],
),
);
}
}
//
// final item = controller.recommendFeed[index];
return TimelineItem();
},
separatorBuilder: (context, index) {
//
if (controller.recommendFeed.isEmpty) {
return const SizedBox.shrink();
}
return const SizedBox(height: 12);
},
// item
itemCount: 10,
)
);
});
}
@override
bool get wantKeepAlive => true;
}

16
lib/pages/home/home_page.dart

@ -1,4 +1,6 @@
import 'package:dating_touchme_app/generated/assets.dart';
import 'package:dating_touchme_app/pages/home/recommend_window.dart';
import 'package:dating_touchme_app/pages/home/timeline_window.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:dating_touchme_app/controller/home/home_controller.dart';
@ -43,12 +45,12 @@ class _HomePageState extends State<HomePage>
body: Obx(() {
// 使 IndexedStack
return IndexedStack(
index: controller.selectedTabIndex.value,
index: controller.topTab.value,
children: const [
//
RecommendTab(),
RecommendWindow(),
//
NearbyTab(),
TimelineWindow(),
],
);
}),
@ -72,7 +74,7 @@ class _HomePageState extends State<HomePage>
children: [
_buildTabButton(title: '推荐', index: 0, controller: controller),
const SizedBox(width: 28),
_buildTabButton(title: '同城', index: 1, controller: controller),
_buildTabButton(title: '广场', index: 1, controller: controller),
],
),
bottom: const PreferredSize(
@ -87,12 +89,12 @@ class _HomePageState extends State<HomePage>
required int index,
required HomeController controller,
}) {
final bool selected = controller.selectedTabIndex.value == index;
final bool selected = controller.topTab.value == index;
return GestureDetector(
onTap: () {
print('Tab $index clicked');
if (controller.selectedTabIndex.value != index) {
controller.setSelectedTabIndex(index);
if (controller.topTab.value != index) {
controller.setTopTab(index);
// UI
controller.update();
}

92
lib/pages/home/recommend_window.dart

@ -0,0 +1,92 @@
import 'package:dating_touchme_app/controller/home/home_controller.dart';
import 'package:dating_touchme_app/pages/home/nearby_tab.dart';
import 'package:dating_touchme_app/pages/home/recommend_tab.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
class RecommendWindow extends StatefulWidget {
const RecommendWindow({super.key});
@override
State<RecommendWindow> createState() => _RecommendWindowState();
}
class _RecommendWindowState extends State<RecommendWindow> with AutomaticKeepAliveClientMixin, SingleTickerProviderStateMixin {
late TabController tabController;
final HomeController controller = Get.find<HomeController>();
@override
void initState() {
super.initState();
tabController = TabController(length: 2, vsync: this);
}
@override
Widget build(BuildContext context) {
super.build(context);
return Column(
children: [
TDTabBar(
tabs: [
TDTab(
child: Padding(
padding: EdgeInsets.only(right: 16, left: 16),
child: Text('推荐'),
),
),
TDTab(
child: Padding(
padding: EdgeInsets.only(right: 16, left: 16),
child: Text('同城'),
),
),
],
backgroundColor: Colors.transparent,
labelPadding: const EdgeInsets.only(right: 4, top: 10, bottom: 10, left: 4),
selectedBgColor: const Color.fromRGBO(108, 105, 244, 1),
unSelectedBgColor: Colors.transparent,
labelColor: Colors.white,
dividerHeight: 0,
tabAlignment: TabAlignment.start,
outlineType: TDTabBarOutlineType.capsule,
controller: tabController,
showIndicator: false,
isScrollable: true,
onTap: (index) async {
print('相亲页面 Tab: $index');
if (controller.selectedTabIndex.value != index) {
controller.setSelectedTabIndex(index);
// UI
controller.update();
}
},
),
Expanded(
child: Obx(() {
// 使 IndexedStack
return IndexedStack(
index: controller.selectedTabIndex.value,
children: const [
//
RecommendTab(),
//
NearbyTab(),
],
);
}),
),
],
);
}
@override
bool get wantKeepAlive => true;
}

263
lib/pages/home/send_timeline.dart

@ -0,0 +1,263 @@
import 'package:dating_touchme_app/components/page_appbar.dart';
import 'package:dating_touchme_app/config/emoji_config.dart';
import 'package:dating_touchme_app/controller/home/send_timeline_controller.dart';
import 'package:dating_touchme_app/extension/ex_widget.dart';
import 'package:dating_touchme_app/generated/assets.dart';
import 'package:dating_touchme_app/widget/emoji_panel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
class SendTimeline extends StatefulWidget {
const SendTimeline({super.key});
@override
State<SendTimeline> createState() => _SendTimelineState();
}
class _SendTimelineState extends State<SendTimeline> {
String title = "";
String message = '';
final TextEditingController messageController = TextEditingController();
final FocusNode focusNode = FocusNode();
bool isEmojiVisible = false;
@override
void initState() {
super.initState();
focusNode.addListener(() {
if (focusNode.hasFocus) {
//
isEmojiVisible = false;
setState(() {
});
}
});
}
@override
void dispose() {
super.dispose();
focusNode.dispose();
}
void toggleEmojiPanel() {
isEmojiVisible = !isEmojiVisible;
FocusManager.instance.primaryFocus?.unfocus();
setState(() {
});
}
void handleEmojiSelected(EmojiItem emoji) {
//
final currentText = messageController.text;
final emojiText = '[emoji:${emoji.id}]';
messageController.text = currentText + emojiText;
//
messageController.selection = TextSelection.fromPosition(
TextPosition(offset: messageController.text.length),
);
setState(() {}); //
}
/// +
List<Widget> buildInputContentWidgets() {
final List<Widget> widgets = [];
final text = messageController.value.text;
final RegExp emojiRegex = RegExp(r'\[emoji:(\d+)\]');
int lastMatchEnd = 0;
final matches = emojiRegex.allMatches(text);
for (final match in matches) {
//
if (match.start > lastMatchEnd) {
final textPart = text.substring(lastMatchEnd, match.start);
widgets.add(
Text(
textPart,
style: TextStyle(fontSize: 14.sp, color: Colors.black),
),
);
}
//
final emojiId = match.group(1);
if (emojiId != null) {
final emoji = EmojiConfig.getEmojiById(emojiId);
if (emoji != null) {
widgets.add(
Padding(
padding: EdgeInsets.symmetric(horizontal: 2.w),
child: Image.asset(
emoji.path,
width: 24.w,
height: 24.w,
fit: BoxFit.contain,
),
),
);
}
}
lastMatchEnd = match.end;
}
//
if (lastMatchEnd < text.length) {
final textPart = text.substring(lastMatchEnd);
widgets.add(
Text(
textPart,
style: TextStyle(fontSize: 14.sp, color: Colors.black),
),
);
}
return widgets;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PageAppbar(title: "", right: Container(
width: 53.w,
height: 26.w,
margin: EdgeInsets.only(right: 17.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8.w)),
color: const Color.fromRGBO(117, 98, 249, 1)
),
child: Center(
child: Text(
"发送",
style: TextStyle(
fontSize: 13.w,
color: Colors.white
),
),
),
),),
body: Container(
padding: EdgeInsets.symmetric(horizontal: 17.w, vertical: 10.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Stack(
children: [
TextField(
controller: messageController,
focusNode: focusNode,
minLines: 1,
maxLines: null, //
style: TextStyle(
fontSize: 14.sp,
color: messageController.text.contains('[emoji:')
? Colors.transparent
: Colors.black,
),
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(
vertical: 0,
horizontal: 0
),
hintText: "分享你的日常,让缘分更早来临~",
hintStyle: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
),
border: const OutlineInputBorder(
borderSide: BorderSide.none, // //
),
// focusedBorder enabledBorder
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
),
onChanged: (value){
setState(() {
});
},
),
if (messageController.text.contains('[emoji:'))
Positioned.fill(
child: IgnorePointer(
child: SingleChildScrollView(
child: Wrap(
children: buildInputContentWidgets(),
),
),
),
),
],
),
),
Container(
width: 98.w,
height: 26.w,
margin: EdgeInsets.symmetric(vertical: 16.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(26.w)),
color: const Color.fromRGBO(245, 245, 245, 1)
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.location_on,
size: 16.w,
color: const Color.fromRGBO(51, 51, 51, 1),
),
SizedBox(width: 5.w,),
Text(
"开启定位",
style: TextStyle(
fontSize: 12.w,
fontWeight: FontWeight.w500
),
)
],
),
),
Row(
children: [
Image.asset(
Assets.imagesImg,
width: 20.w,
),
SizedBox(width: 25.w,),
Image.asset(
Assets.imagesEmoji,
width: 18.w,
).onTap(toggleEmojiPanel)
],
),
//
EmojiPanel(
isVisible: isEmojiVisible,
onEmojiSelected: handleEmojiSelected,
),
],
),
),
);
}
}

212
lib/pages/home/timeline_info.dart

@ -0,0 +1,212 @@
import 'package:dating_touchme_app/components/page_appbar.dart';
import 'package:dating_touchme_app/generated/assets.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class TimelineInfo extends StatefulWidget {
const TimelineInfo({super.key});
@override
State<TimelineInfo> createState() => _TimelineInfoState();
}
class _TimelineInfoState extends State<TimelineInfo> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PageAppbar(title: "详情"),
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 16.w,
vertical: 10.w
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Image.asset(
Assets.imagesUserAvatar,
width: 40.w,
height: 40.w,
),
SizedBox(width: 8.w,),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"刘美玲",
style: TextStyle(
fontSize: 13.w,
fontWeight: FontWeight.w500
),
),
Text(
"15:16",
style: TextStyle(
fontSize: 11.w,
color: const Color.fromRGBO(51, 51, 51, .6),
fontWeight: FontWeight.w500
),
)
],
)
],
),
Icon(
Icons.keyboard_control,
size: 15.w,
color: const Color.fromRGBO(51, 51, 51, 1),
)
],
),
Container(
margin: EdgeInsets.symmetric(vertical: 11.w),
child: Text(
"你总顾及别人,那谁来顾及你。你总顾及别人,那谁来顾及你。你总顾及别人,那谁来顾及你。你总顾及别人,那谁来顾及你。"
),
),
Image.asset(
Assets.imagesRoseBanner,
width: 343.w,
),
SizedBox(height: 15.w,),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
children: [
Image.asset(
Assets.imagesLikeIcon,
width: 14.w,
height: 12.w,
),
SizedBox(width: 6.w,),
Text(
"47",
style: TextStyle(
fontSize: 11.w,
color: const Color.fromRGBO(144, 144, 144, .6)
),
)
],
),
SizedBox(width: 33.w,),
Row(
children: [
Image.asset(
Assets.imagesCommentIcon,
width: 15.w,
height: 15.w,
),
SizedBox(width: 6.w,),
Text(
"23",
style: TextStyle(
fontSize: 11.w,
color: const Color.fromRGBO(144, 144, 144, .6)
),
)
],
),
],
),
SizedBox(height: 18.w,),
Text(
"全部评论(23)",
style: TextStyle(
fontSize: 13.w,
color: const Color.fromRGBO(144, 144, 144, 1),
fontWeight: FontWeight.w500
),
),
SizedBox(height: 20.w,),
CommentItem(),
CommentItem(),
CommentItem(),
CommentItem(),
CommentItem(),
CommentItem(),
CommentItem(),
],
),
),
),
);
}
}
class CommentItem extends StatefulWidget {
const CommentItem({super.key});
@override
State<CommentItem> createState() => _CommentItemState();
}
class _CommentItemState extends State<CommentItem> {
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(bottom: 20.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(
Assets.imagesUserAvatar,
width: 40.w,
height: 40.w,
),
SizedBox(width: 8.w,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"刘美玲",
style: TextStyle(
fontSize: 13.w,
color: const Color.fromRGBO(144, 144, 144, 1),
),
),
SizedBox(height: 5.w,),
SizedBox(
child: Text(
"看起来还不错!看起来还不错!看起来还不错!看起来还不错!看起来还不错!看起来还不错!看起来还不错!看起来还不错!",
style: TextStyle(
fontSize: 13.w,
fontWeight: FontWeight.w500
),
),
),
SizedBox(height: 5.w,),
Text(
"15:16·回复",
style: TextStyle(
fontSize: 11.w,
color: const Color.fromRGBO(51, 51, 51, .6),
),
),
],
),
)
],
),
),
Image.asset(
Assets.imagesLikeIcon,
width: 14.w,
)
],
),
);
}
}

119
lib/pages/home/timeline_item.dart

@ -0,0 +1,119 @@
import 'package:dating_touchme_app/extension/ex_widget.dart';
import 'package:dating_touchme_app/generated/assets.dart';
import 'package:dating_touchme_app/pages/home/timeline_info.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
class TimelineItem extends StatefulWidget {
const TimelineItem({super.key});
@override
State<TimelineItem> createState() => _TimelineItemState();
}
class _TimelineItemState extends State<TimelineItem> {
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(bottom: 15.w),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Image.asset(
Assets.imagesUserAvatar,
width: 40.w,
height: 40.w,
),
SizedBox(width: 8.w,),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"刘美玲",
style: TextStyle(
fontSize: 13.w,
fontWeight: FontWeight.w500
),
),
Text(
"15:16",
style: TextStyle(
fontSize: 11.w,
color: const Color.fromRGBO(51, 51, 51, .6),
fontWeight: FontWeight.w500
),
)
],
)
],
),
Icon(
Icons.keyboard_control,
size: 15.w,
color: const Color.fromRGBO(51, 51, 51, 1),
)
],
),
Container(
margin: EdgeInsets.symmetric(vertical: 11.w),
child: Text(
"你总顾及别人,那谁来顾及你。你总顾及别人,那谁来顾及你。你总顾及别人,那谁来顾及你。你总顾及别人,那谁来顾及你。"
),
),
Image.asset(
Assets.imagesRoseBanner,
width: 375.w - 24,
),
SizedBox(height: 14.w,),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
children: [
Image.asset(
Assets.imagesLikeIcon,
width: 14.w,
height: 12.w,
),
SizedBox(width: 6.w,),
Text(
"47",
style: TextStyle(
fontSize: 11.w,
color: const Color.fromRGBO(144, 144, 144, .6)
),
)
],
),
SizedBox(width: 33.w,),
Row(
children: [
Image.asset(
Assets.imagesCommentIcon,
width: 15.w,
height: 15.w,
),
SizedBox(width: 6.w,),
Text(
"23",
style: TextStyle(
fontSize: 11.w,
color: const Color.fromRGBO(144, 144, 144, .6)
),
)
],
),
],
)
],
),
).onTap((){
Get.to(() => TimelineInfo());
});
}
}

111
lib/pages/home/timeline_window.dart

@ -0,0 +1,111 @@
import 'package:dating_touchme_app/controller/home/home_controller.dart';
import 'package:dating_touchme_app/pages/home/all_timeline.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
class TimelineWindow extends StatefulWidget {
const TimelineWindow({super.key});
@override
State<TimelineWindow> createState() => _TimelineWindowState();
}
class _TimelineWindowState extends State<TimelineWindow> with AutomaticKeepAliveClientMixin, SingleTickerProviderStateMixin {
late TabController tabController;
final HomeController controller = Get.find<HomeController>();
@override
void initState() {
super.initState();
tabController = TabController(length: 2, vsync: this);
}
@override
Widget build(BuildContext context) {
super.build(context);
return Column(
children: [
Container(
height: 25.w,
color: const Color.fromRGBO(128, 91, 253, 1),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.location_on,
size: 14.w,
color: Colors.white,
),
SizedBox(width: 7.w,),
Text(
"点击开启定位,即可查看附近的人",
style: TextStyle(
fontSize: 12.w,
color: Colors.white,
fontWeight: FontWeight.w500
),
)
],
),
),
TDTabBar(
tabs: [
TDTab(
child: Padding(
padding: EdgeInsets.only(right: 16, left: 16),
child: Text('全部'),
),
),
TDTab(
child: Padding(
padding: EdgeInsets.only(right: 16, left: 16),
child: Text('好友动态'),
),
),
],
backgroundColor: Colors.transparent,
labelPadding: const EdgeInsets.only(right: 4, top: 10, bottom: 10, left: 4),
selectedBgColor: const Color.fromRGBO(108, 105, 244, 1),
unSelectedBgColor: Colors.transparent,
labelColor: Colors.white,
dividerHeight: 0,
tabAlignment: TabAlignment.start,
outlineType: TDTabBarOutlineType.capsule,
controller: tabController,
showIndicator: false,
isScrollable: true,
onTap: (index) async {
print('相亲页面 Tab: $index');
if (controller.timelineTab.value != index) {
controller.setTimelineTab(index);
// UI
controller.update();
}
},
),
Expanded(
child: Obx(() {
// 使 IndexedStack
return IndexedStack(
index: controller.timelineTab.value,
children: const [
//
AllTimeline(),
//
],
);
}),
),
],
);
}
@override
bool get wantKeepAlive => true;
}

60
lib/pages/main/main_page.dart

@ -1,4 +1,6 @@
import 'package:dating_touchme_app/extension/ex_widget.dart';
import 'package:dating_touchme_app/generated/assets.dart';
import 'package:dating_touchme_app/pages/home/send_timeline.dart';
import 'package:dating_touchme_app/pages/message/message_page.dart';
import 'package:dating_touchme_app/pages/mine/mine_page.dart';
import 'package:dating_touchme_app/rtc/rtm_manager.dart';
@ -85,17 +87,53 @@ class _MainPageState extends State<MainPage> {
minePage,
],
),
bottomNavigationBar: TDBottomTabBar(
currentIndex: currentIndex,
TDBottomTabBarBasicType.iconText,
componentType: TDBottomTabBarComponentType.normal,
useVerticalDivider: false,
navigationTabs: [
tabItem('首页', Assets.imagesHomePre, Assets.imagesHomeNol, 0),
// tabItem('找对象', Assets.imagesDiscoverPre, Assets.imagesDiscoverNol, 1),
tabItem('消息', Assets.imagesMessagePre, Assets.imagesMessageNol, 1),
tabItem('我的', Assets.imagesMinePre, Assets.imagesMineNol, 2),
]
bottomNavigationBar: Stack(
clipBehavior: Clip.none,
children: [
TDBottomTabBar(
currentIndex: currentIndex,
TDBottomTabBarBasicType.iconText,
componentType: TDBottomTabBarComponentType.normal,
useVerticalDivider: false,
navigationTabs: [
tabItem('首页', Assets.imagesHomePre, Assets.imagesHomeNol, 0),
// tabItem('找对象', Assets.imagesDiscoverPre, Assets.imagesDiscoverNol, 1),
TDBottomTabBarTabConfig(
tabText: "",
selectedIcon: Icon(Icons.add, size: 25, color: Colors.transparent,),
unselectedIcon: Icon(Icons.add, size: 25, color: Colors.transparent,),
selectTabTextStyle: TextStyle(color: Color(0xFFED4AC3)),
unselectTabTextStyle: TextStyle(color: Color(0xFF999999)),
onTap: () {
Get.to(() => SendTimeline());
},
),
tabItem('消息', Assets.imagesMessagePre, Assets.imagesMessageNol, 1),
tabItem('我的', Assets.imagesMinePre, Assets.imagesMineNol, 2),
]
),
Positioned(
left: 110,
top: -10,
child: Image.asset(
Assets.imagesPublish,
width: 50,
height: 50,
).onTap(() {
Get.to(() => SendTimeline());
}),
),
Positioned(
left: 89.5,
bottom: 0,
child: SizedBox(
width: 89.5,
height: 55.5,
).onTap(() {
Get.to(() => SendTimeline());
}),
)
],
)
),
);

Loading…
Cancel
Save