parent
b025d6dfa0
commit
19e23f66a4
@ -0,0 +1,146 @@
|
|||||||
|
import 'package:akuCommunity/model/common/img_model.dart';
|
||||||
|
|
||||||
|
class CommunityTopicModel {
|
||||||
|
int id;
|
||||||
|
int createId;
|
||||||
|
int isComment;
|
||||||
|
int isLike;
|
||||||
|
String createName;
|
||||||
|
String content;
|
||||||
|
String gambitTitle;
|
||||||
|
String createDate;
|
||||||
|
List<LikeNames> likeNames;
|
||||||
|
List<ImgModel> imgUrls;
|
||||||
|
List<ImgModel> headSculptureImgUrl;
|
||||||
|
List<GambitThemeCommentVoList> gambitThemeCommentVoList;
|
||||||
|
|
||||||
|
CommunityTopicModel(
|
||||||
|
{this.id,
|
||||||
|
this.createId,
|
||||||
|
this.isComment,
|
||||||
|
this.isLike,
|
||||||
|
this.createName,
|
||||||
|
this.content,
|
||||||
|
this.gambitTitle,
|
||||||
|
this.createDate,
|
||||||
|
this.likeNames,
|
||||||
|
this.imgUrls,
|
||||||
|
this.headSculptureImgUrl,
|
||||||
|
this.gambitThemeCommentVoList});
|
||||||
|
|
||||||
|
CommunityTopicModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
createId = json['createId'];
|
||||||
|
isComment = json['isComment'];
|
||||||
|
isLike = json['isLike'];
|
||||||
|
createName = json['createName'];
|
||||||
|
content = json['content'];
|
||||||
|
gambitTitle = json['gambitTitle'];
|
||||||
|
createDate = json['createDate'];
|
||||||
|
if (json['likeNames'] != null) {
|
||||||
|
likeNames = new List<LikeNames>();
|
||||||
|
json['likeNames'].forEach((v) {
|
||||||
|
likeNames.add(new LikeNames.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (json['imgUrls'] != null) {
|
||||||
|
imgUrls = new List<ImgModel>();
|
||||||
|
json['imgUrls'].forEach((v) {
|
||||||
|
imgUrls.add(new ImgModel.fromJson(v));
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
imgUrls = [];
|
||||||
|
if (json['headSculptureImgUrl'] != null) {
|
||||||
|
headSculptureImgUrl = new List<ImgModel>();
|
||||||
|
json['headSculptureImgUrl'].forEach((v) {
|
||||||
|
headSculptureImgUrl.add(new ImgModel.fromJson(v));
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
headSculptureImgUrl = [];
|
||||||
|
if (json['gambitThemeCommentVoList'] != null) {
|
||||||
|
gambitThemeCommentVoList = new List<GambitThemeCommentVoList>();
|
||||||
|
json['gambitThemeCommentVoList'].forEach((v) {
|
||||||
|
gambitThemeCommentVoList.add(new GambitThemeCommentVoList.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['createId'] = this.createId;
|
||||||
|
data['isComment'] = this.isComment;
|
||||||
|
data['isLike'] = this.isLike;
|
||||||
|
data['createName'] = this.createName;
|
||||||
|
data['content'] = this.content;
|
||||||
|
data['gambitTitle'] = this.gambitTitle;
|
||||||
|
data['createDate'] = this.createDate;
|
||||||
|
if (this.likeNames != null) {
|
||||||
|
data['likeNames'] = this.likeNames.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
if (this.imgUrls != null) {
|
||||||
|
data['imgUrls'] = this.imgUrls.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
if (this.headSculptureImgUrl != null) {
|
||||||
|
data['headSculptureImgUrl'] =
|
||||||
|
this.headSculptureImgUrl.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
if (this.gambitThemeCommentVoList != null) {
|
||||||
|
data['gambitThemeCommentVoList'] =
|
||||||
|
this.gambitThemeCommentVoList.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LikeNames {
|
||||||
|
int id;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
LikeNames({this.id, this.name});
|
||||||
|
|
||||||
|
LikeNames.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
name = json['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['name'] = this.name;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GambitThemeCommentVoList {
|
||||||
|
int id;
|
||||||
|
String parentName;
|
||||||
|
String content;
|
||||||
|
String createName;
|
||||||
|
String createDate;
|
||||||
|
|
||||||
|
GambitThemeCommentVoList(
|
||||||
|
{this.id,
|
||||||
|
this.parentName,
|
||||||
|
this.content,
|
||||||
|
this.createName,
|
||||||
|
this.createDate});
|
||||||
|
|
||||||
|
GambitThemeCommentVoList.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
parentName = json['parentName'];
|
||||||
|
content = json['content'];
|
||||||
|
createName = json['createName'];
|
||||||
|
createDate = json['createDate'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['parentName'] = this.parentName;
|
||||||
|
data['content'] = this.content;
|
||||||
|
data['createName'] = this.createName;
|
||||||
|
data['createDate'] = this.createDate;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
import 'package:akuCommunity/ui/community/community_views/my_community_view.dart';
|
||||||
|
import 'package:akuCommunity/ui/community/community_views/new_community_view.dart';
|
||||||
|
import 'package:akuCommunity/ui/community/community_views/topic/topic_community_view.dart';
|
||||||
|
import 'package:akuCommunity/utils/headers.dart';
|
||||||
|
import 'package:akuCommunity/widget/bee_scaffold.dart';
|
||||||
|
import 'package:akuCommunity/widget/buttons/column_action_button.dart';
|
||||||
|
import 'package:akuCommunity/widget/tab_bar/bee_tab_bar.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CommunityPage extends StatefulWidget {
|
||||||
|
CommunityPage({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_CommunityPageState createState() => _CommunityPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CommunityPageState extends State<CommunityPage>
|
||||||
|
with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
|
||||||
|
TabController _tabController;
|
||||||
|
List<String> _tabs = ['最新', '话题', '我的'];
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_tabController = TabController(
|
||||||
|
vsync: this,
|
||||||
|
length: _tabs.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
super.build(context);
|
||||||
|
return BeeScaffold(
|
||||||
|
title: '社区',
|
||||||
|
actions: [
|
||||||
|
ColumnActionButton(
|
||||||
|
onPressed: () {},
|
||||||
|
title: '消息',
|
||||||
|
path: R.ASSETS_ICONS_ALARM_PNG,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
appBarBottom: PreferredSize(
|
||||||
|
preferredSize: Size.fromHeight(48),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: BeeTabBar(
|
||||||
|
controller: _tabController,
|
||||||
|
tabs: _tabs,
|
||||||
|
scrollable: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: TabBarView(
|
||||||
|
children: [
|
||||||
|
NewCommunityView(),
|
||||||
|
TopicCommunityView(),
|
||||||
|
MyCommunityView(),
|
||||||
|
],
|
||||||
|
controller: _tabController,
|
||||||
|
),
|
||||||
|
bodyColor: Colors.white,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class MyCommunityView extends StatefulWidget {
|
||||||
|
MyCommunityView({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_MyCommunityViewState createState() => _MyCommunityViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MyCommunityViewState extends State<MyCommunityView>
|
||||||
|
with AutomaticKeepAliveClientMixin {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
super.build(context);
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class NewCommunityView extends StatefulWidget {
|
||||||
|
NewCommunityView({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_NewCommunityViewState createState() => _NewCommunityViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NewCommunityViewState extends State<NewCommunityView>
|
||||||
|
with AutomaticKeepAliveClientMixin {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
super.build(context);
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:akuCommunity/ui/community/community_views/topic/topic_detail_page.dart';
|
||||||
|
import 'package:akuCommunity/utils/headers.dart';
|
||||||
|
import 'package:akuCommunity/constants/api.dart';
|
||||||
|
import 'package:akuCommunity/model/community/community_topic_model.dart';
|
||||||
|
import 'package:akuCommunity/pages/things_page/widget/bee_list_view.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_easyrefresh/easy_refresh.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class TopicCommunityView extends StatefulWidget {
|
||||||
|
TopicCommunityView({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_TopicCommunityViewState createState() => _TopicCommunityViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TopicCommunityViewState extends State<TopicCommunityView>
|
||||||
|
with AutomaticKeepAliveClientMixin {
|
||||||
|
EasyRefreshController _refreshController = EasyRefreshController();
|
||||||
|
|
||||||
|
_buildItem(CommunityTopicModel model) {
|
||||||
|
var firstImg = '';
|
||||||
|
if (model?.imgUrls?.isNotEmpty ?? false) {
|
||||||
|
firstImg = model?.imgUrls?.first?.url ?? '';
|
||||||
|
}
|
||||||
|
return MaterialButton(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 53.w, vertical: 20.w),
|
||||||
|
onPressed: () {
|
||||||
|
Get.to(TopicDetailPage(id: model.id));
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8.w),
|
||||||
|
color: Colors.black12,
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
FadeInImage.assetNetwork(
|
||||||
|
placeholder: R.ASSETS_IMAGES_LOGO_PNG,
|
||||||
|
image: API.image(firstImg),
|
||||||
|
height: 160.w,
|
||||||
|
width: 250.w,
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.vertical(
|
||||||
|
bottom: Radius.circular(8.w),
|
||||||
|
),
|
||||||
|
child: BackdropFilter(
|
||||||
|
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
|
||||||
|
//TODO 等待后端接口补充话题摘要
|
||||||
|
// model.summary
|
||||||
|
child: ('#${''}')
|
||||||
|
.text
|
||||||
|
.center
|
||||||
|
.size(28.sp)
|
||||||
|
.white
|
||||||
|
.make()
|
||||||
|
.material(color: Colors.black26),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
12.wb,
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
(model?.gambitTitle ?? '')
|
||||||
|
.text
|
||||||
|
.maxLines(2)
|
||||||
|
.size(28.sp)
|
||||||
|
.bold
|
||||||
|
.overflow(TextOverflow.ellipsis)
|
||||||
|
.make(),
|
||||||
|
(model?.content ?? '')
|
||||||
|
.text
|
||||||
|
.maxLines(1)
|
||||||
|
.size(22.sp)
|
||||||
|
.overflow(TextOverflow.ellipsis)
|
||||||
|
.make(),
|
||||||
|
12.hb,
|
||||||
|
],
|
||||||
|
).expand(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
super.build(context);
|
||||||
|
return BeeListView(
|
||||||
|
path: API.community.topicList,
|
||||||
|
controller: _refreshController,
|
||||||
|
convert: (model) {
|
||||||
|
return model.tableList
|
||||||
|
.map((e) => CommunityTopicModel.fromJson(e))
|
||||||
|
.toList();
|
||||||
|
},
|
||||||
|
builder: (items) {
|
||||||
|
return ListView.separated(
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return _buildItem(items[index]);
|
||||||
|
},
|
||||||
|
separatorBuilder: (_, __) => 20.hb,
|
||||||
|
itemCount: items.length,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
import 'package:akuCommunity/ui/community/community_views/topic/topic_scrollable_text.dart';
|
||||||
|
import 'package:akuCommunity/utils/headers.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class TopicDetailPage extends StatefulWidget {
|
||||||
|
final int id;
|
||||||
|
TopicDetailPage({Key key, @required this.id}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_TopicDetailPageState createState() => _TopicDetailPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TopicDetailPageState extends State<TopicDetailPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverAppBar(
|
||||||
|
expandedHeight: 500.w,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
elevation: 0,
|
||||||
|
pinned: true,
|
||||||
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
title: TopicScrollableText(title: '#TEST'),
|
||||||
|
titlePadding: EdgeInsets.zero,
|
||||||
|
collapseMode: CollapseMode.pin,
|
||||||
|
background: Container(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: 40000.hb,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
import 'package:akuCommunity/utils/headers.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class TopicScrollableText extends StatefulWidget {
|
||||||
|
final String title;
|
||||||
|
TopicScrollableText({Key key, @required this.title}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_TopicScrollableTextState createState() => _TopicScrollableTextState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TopicScrollableTextState extends State<TopicScrollableText> {
|
||||||
|
ScrollPosition _scrollPosition;
|
||||||
|
|
||||||
|
_positionListener() {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_scrollPosition?.removeListener(_positionListener);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
_scrollPosition = Scrollable.of(context)?.position;
|
||||||
|
_scrollPosition?.addListener(_positionListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
double get offset {
|
||||||
|
if (_scrollPosition.pixels >= 500.w) return 1;
|
||||||
|
if (_scrollPosition.pixels < 500.w && _scrollPosition.pixels >= 0) {
|
||||||
|
return _scrollPosition.pixels / 500.w;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 202.w - offset * 160.w),
|
||||||
|
child: Text(widget.title),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue