Merge branch 'master' of http://192.168.2.201:8099/laiiihz/akuCommunity
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,107 @@
|
||||
import 'package:akuCommunity/const/resource.dart';
|
||||
import 'package:akuCommunity/pages/convenient_phone/convenient_phone_page.dart';
|
||||
import 'package:akuCommunity/pages/fitup_manage/fitup_manage_page.dart';
|
||||
import 'package:akuCommunity/pages/goods_deto_page/goods_deto_page.dart';
|
||||
import 'package:akuCommunity/pages/goods_manage_page/goods_manage_page.dart';
|
||||
import 'package:akuCommunity/pages/industry_committee/industry_committee_page.dart';
|
||||
import 'package:akuCommunity/pages/life_pay/life_pay_page.dart';
|
||||
import 'package:akuCommunity/pages/one_alarm/widget/alarm_page.dart';
|
||||
import 'package:akuCommunity/pages/open_door_page/open_door_page.dart';
|
||||
import 'package:akuCommunity/pages/opening_code_page/opening_code_page.dart';
|
||||
import 'package:akuCommunity/pages/questionnaire_page/questionnaire_details_page/questionnaire_details_page.dart';
|
||||
import 'package:akuCommunity/pages/things_page/fixed_submit_page.dart';
|
||||
import 'package:akuCommunity/pages/visitor_access_page/visitor_access_page.dart';
|
||||
import 'package:akuCommunity/ui/home/application/all_application.dart';
|
||||
import 'package:akuCommunity/ui/manager/advice/advice_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
///应用对象
|
||||
///Application Object
|
||||
class AO {
|
||||
String title = '';
|
||||
String path = '';
|
||||
Widget page = Scaffold();
|
||||
|
||||
AO(
|
||||
this.title,
|
||||
this.path,
|
||||
this.page,
|
||||
);
|
||||
|
||||
AO.fromRaw(String raw) {
|
||||
appObjects.forEach((element) {
|
||||
if (element.title == raw) {
|
||||
this.title = element.title;
|
||||
this.path = element.path;
|
||||
this.page = element.page;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
other is AO && runtimeType == other.runtimeType && title == other.title;
|
||||
|
||||
@override
|
||||
int get hashCode => title.hashCode;
|
||||
}
|
||||
|
||||
///所有应用
|
||||
List<AO> appObjects = [
|
||||
AO('一键开门', R.ASSETS_APPLICATIONS_OEPN_DOOR_PNG, OpenDoorPage()),
|
||||
AO('开门码', R.ASSETS_APPLICATIONS_DOOR_CODE_PNG, OpeningCodePage()),
|
||||
AO('访客邀请', R.ASSETS_APPLICATIONS_VISITOR_INVITE_PNG, VisitorAccessPage()),
|
||||
AO('报事报修', R.ASSETS_APPLICATIONS_FIX_PNG, FixedSubmitPage()),
|
||||
AO('生活缴费', R.ASSETS_APPLICATIONS_PAYMENT_PNG, LifePayPage()),
|
||||
AO('业委会', R.ASSETS_APPLICATIONS_COMMITTEE_PNG, IndustryCommitteePage()),
|
||||
AO('建议咨询', R.ASSETS_APPLICATIONS_ADVICE_PNG,
|
||||
AdvicePage(type: AdviceType.SUGGESTION)),
|
||||
AO('便民电话', R.ASSETS_APPLICATIONS_COMMUNITY_PHONE_PNG, ConvenientPhonePage()),
|
||||
AO('活动投票', R.ASSETS_APPLICATIONS_VOTE_PNG, SizedBox()),
|
||||
AO('物品出门', R.ASSETS_APPLICATIONS_GOODS_OUT_PNG, GoodsDetoPage()),
|
||||
AO('投诉表扬', R.ASSETS_APPLICATIONS_COMPLAINT_PNG,
|
||||
AdvicePage(type: AdviceType.COMPLAIN)),
|
||||
AO('问卷调查', R.ASSETS_APPLICATIONS_QUESTION_PNG, QuestionnaireDetailsPage()),
|
||||
AO('装修管理', R.ASSETS_APPLICATIONS_DECORATION_PNG, FitupManagePage()),
|
||||
AO('借还管理', R.ASSETS_APPLICATIONS_BORROW_PNG, GoodsManagePage()),
|
||||
AO('一键报警', R.ASSETS_APPLICATIONS_POLICE_PNG, AlarmPage()),
|
||||
];
|
||||
|
||||
///全部应用按钮
|
||||
AO allApp = AO('全部应用', R.ASSETS_APPLICATIONS_ALL_APP_PNG, AllApplicationPage());
|
||||
|
||||
///为您推荐 original value
|
||||
List<String> _recommendApp = [
|
||||
'一键开门',
|
||||
'访客邀请',
|
||||
'报事报修',
|
||||
'建议咨询',
|
||||
'一键报警',
|
||||
];
|
||||
|
||||
///为您推荐
|
||||
List<AO> get recommendApp => _recommendApp.map((e) => AO.fromRaw(e)).toList();
|
||||
|
||||
///智慧管家 original value
|
||||
List<String> _smartManagerApp = [
|
||||
'一键开门',
|
||||
'开门码',
|
||||
'访客邀请',
|
||||
'报事报修',
|
||||
'生活缴费',
|
||||
'业委会',
|
||||
'建议咨询',
|
||||
'便民电话',
|
||||
'活动投票',
|
||||
'物品出门',
|
||||
'投诉表扬',
|
||||
'问卷调查',
|
||||
'装修管理',
|
||||
'借还管理',
|
||||
'一键报警',
|
||||
];
|
||||
|
||||
///智慧管家
|
||||
List<AO> get smartManagerApp =>
|
||||
_smartManagerApp.map((e) => AO.fromRaw(e)).toList();
|
@ -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,57 @@
|
||||
import 'package:akuCommunity/constants/application_objects.dart';
|
||||
import 'package:akuCommunity/utils/hive_store.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppProvider extends ChangeNotifier {
|
||||
///初始值为
|
||||
///
|
||||
///```
|
||||
///'一键开门',
|
||||
/// '访客邀请',
|
||||
/// '报事报修',
|
||||
/// '生活缴费',
|
||||
/// '业委会',
|
||||
/// '建议投诉',
|
||||
/// '便民电话',
|
||||
///```
|
||||
List<AO> _myApplications = [
|
||||
'一键开门',
|
||||
'访客邀请',
|
||||
'报事报修',
|
||||
'生活缴费',
|
||||
'业委会',
|
||||
'建议咨询',
|
||||
'便民电话',
|
||||
].map((e) => AO.fromRaw(e)).toList();
|
||||
|
||||
///我的应用
|
||||
List<AO> get myApplications {
|
||||
return _myApplications;
|
||||
}
|
||||
|
||||
///初始化我的应用
|
||||
initApplications() {
|
||||
if (HiveStore.appBox.containsKey('app'))
|
||||
_myApplications = (HiveStore.appBox.get('app') as List<String>)
|
||||
.map((e) => AO.fromRaw(e))
|
||||
.toList();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
///添加我的应用
|
||||
insertApplication(AO app) {
|
||||
if (!_myApplications.contains(app) && _myApplications.length < 7)
|
||||
_myApplications.insert(0, app);
|
||||
if (!_myApplications.contains(app) && _myApplications.length >= 7) {
|
||||
_myApplications.insert(0, app);
|
||||
_myApplications.removeLast();
|
||||
}
|
||||
HiveStore.appBox.put('app', _myApplications.map((e) => e.title).toList());
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
///移除我的应用
|
||||
removeApplication(AO obj) {
|
||||
if (_myApplications.remove(obj)) notifyListeners();
|
||||
}
|
||||
}
|
@ -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),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,266 @@
|
||||
import 'package:akuCommunity/base/base_style.dart';
|
||||
import 'package:akuCommunity/constants/application_objects.dart';
|
||||
import 'package:akuCommunity/provider/app_provider.dart';
|
||||
import 'package:akuCommunity/utils/headers.dart';
|
||||
import 'package:akuCommunity/widget/bee_back_button.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:velocity_x/velocity_x.dart';
|
||||
|
||||
class AllApplicationPage extends StatefulWidget {
|
||||
AllApplicationPage({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AllApplicationPageState createState() => _AllApplicationPageState();
|
||||
}
|
||||
|
||||
class _AllApplicationPageState extends State<AllApplicationPage> {
|
||||
bool _editMode = false;
|
||||
|
||||
int _index = 0;
|
||||
|
||||
PageController _pageController = PageController();
|
||||
|
||||
_buildTile(AO object, {bool editMode = false}) {
|
||||
return MaterialButton(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.w)),
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: editMode ? null : () => Get.to(object.page),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
object.path,
|
||||
height: 75.w,
|
||||
width: 75.w,
|
||||
),
|
||||
8.hb,
|
||||
object.title.text.size(24.sp).make(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_buildEditTile() {
|
||||
return Row(
|
||||
children: [
|
||||
74.hb,
|
||||
'我的应用'.text.make(),
|
||||
Spacer(),
|
||||
MaterialButton(
|
||||
padding: EdgeInsets.zero,
|
||||
elevation: 0,
|
||||
height: 52.w,
|
||||
minWidth: 90.w,
|
||||
onPressed: () {
|
||||
_editMode = !_editMode;
|
||||
setState(() {});
|
||||
},
|
||||
color: kPrimaryColor,
|
||||
child: (_editMode ? '完成' : '编辑').text.bold.size(28.sp).make(),
|
||||
),
|
||||
],
|
||||
).pSymmetric(h: 32.w).material(color: Colors.white);
|
||||
}
|
||||
|
||||
_buildMyApp() {
|
||||
final appProvider = Provider.of<AppProvider>(context);
|
||||
return GridView.builder(
|
||||
padding: EdgeInsets.symmetric(horizontal: 32.w),
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
|
||||
itemBuilder: (context, index) {
|
||||
return Stack(
|
||||
children: [
|
||||
_buildTile(
|
||||
appProvider.myApplications[index],
|
||||
editMode: _editMode,
|
||||
),
|
||||
Positioned(
|
||||
right: 0,
|
||||
top: 0,
|
||||
child: AnimatedOpacity(
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOutCubic,
|
||||
opacity: _editMode ? 1 : 0,
|
||||
child: CupertinoButton(
|
||||
minSize: 60.w,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: _editMode
|
||||
? () {
|
||||
appProvider.removeApplication(
|
||||
appProvider.myApplications[index],
|
||||
);
|
||||
}
|
||||
: null,
|
||||
child: Image.asset(
|
||||
R.ASSETS_ICONS_APP_REDUCE_PNG,
|
||||
height: 24.w,
|
||||
width: 24.w,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
itemCount: appProvider.myApplications.length,
|
||||
).material(color: Colors.white);
|
||||
}
|
||||
|
||||
_buildListTile(String title, int index) {
|
||||
bool sameIndex = _index == index;
|
||||
return Stack(
|
||||
fit: StackFit.passthrough,
|
||||
children: [
|
||||
MaterialButton(
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
padding: EdgeInsets.zero,
|
||||
color: sameIndex ? Colors.white : Color(0xFFEFEFEF),
|
||||
elevation: 0,
|
||||
height: 88.w,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_index = index;
|
||||
});
|
||||
_pageController.animateToPage(
|
||||
index,
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOutCubic,
|
||||
);
|
||||
},
|
||||
child: title.text.size(28.sp).make(),
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: 24.w,
|
||||
bottom: 24.w,
|
||||
child: AnimatedContainer(
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOutCubic,
|
||||
width: sameIndex ? 3.w : 10.w,
|
||||
color: sameIndex ? kPrimaryColor : kPrimaryColor.withOpacity(0),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildView(List<AO> objects) {
|
||||
final appProvider = Provider.of<AppProvider>(context);
|
||||
return GridView.builder(
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
|
||||
itemBuilder: (context, index) {
|
||||
return Stack(
|
||||
children: [
|
||||
_buildTile(objects[index], editMode: _editMode),
|
||||
Positioned(
|
||||
right: 0,
|
||||
top: 0,
|
||||
child: AnimatedOpacity(
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOutCubic,
|
||||
opacity: _editMode ? 1 : 0,
|
||||
child: CupertinoButton(
|
||||
minSize: 60.w,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: _editMode
|
||||
? () => appProvider.insertApplication(objects[index])
|
||||
: null,
|
||||
child: Image.asset(
|
||||
R.ASSETS_ICONS_APP_ADD_PNG,
|
||||
height: 24.w,
|
||||
width: 24.w,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
itemCount: objects.length,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAppList() {
|
||||
return Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 172.w,
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
_buildListTile('为您推荐', 0),
|
||||
_buildListTile('智慧管家', 1),
|
||||
// _buildListTile('商城购物', 2),
|
||||
],
|
||||
),
|
||||
).material(color: Color(0xFFEFEFEF)),
|
||||
PageView(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
scrollDirection: Axis.vertical,
|
||||
controller: _pageController,
|
||||
children: [
|
||||
_buildView(recommendApp),
|
||||
_buildView(smartManagerApp),
|
||||
],
|
||||
).expand(),
|
||||
],
|
||||
).material(color: Colors.white);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Color(0xFFF4F4F4),
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
leading: BeeBackButton(),
|
||||
title: MaterialButton(
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
height: 72.w,
|
||||
shape: StadiumBorder(),
|
||||
elevation: 0,
|
||||
minWidth: double.infinity,
|
||||
color: Color(0xFFF3F3F3),
|
||||
onPressed: () {},
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.search,
|
||||
size: 32.w,
|
||||
color: Color(0xFF666666),
|
||||
),
|
||||
10.wb,
|
||||
'搜索商品、活动、帖子、应用'
|
||||
.text
|
||||
.size(28.sp)
|
||||
.color(ktextSubColor)
|
||||
.make()
|
||||
.expand(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
_buildEditTile(),
|
||||
Divider(
|
||||
indent: 32.w,
|
||||
endIndent: 32.w,
|
||||
height: 1.w,
|
||||
).material(color: Colors.white),
|
||||
_buildMyApp(),
|
||||
32.hb,
|
||||
_buildAppList().expand(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
import 'package:akuCommunity/utils/headers.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:velocity_x/velocity_x.dart';
|
||||
|
||||
class ColumnActionButton extends StatelessWidget {
|
||||
final VoidCallback onPressed;
|
||||
final String title;
|
||||
final String path;
|
||||
const ColumnActionButton({Key key, this.onPressed, this.title, this.path})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialButton(
|
||||
minWidth: 72.w,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: onPressed,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Image.asset(path, height: 48.w, width: 48.w),
|
||||
4.hb,
|
||||
title.text.size(20.sp).black.make(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
import 'package:akuCommunity/utils/headers.dart';
|
||||
import 'package:akuCommunity/constants/application_objects.dart';
|
||||
import 'package:akuCommunity/provider/app_provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:velocity_x/velocity_x.dart';
|
||||
|
||||
class ApplicationView extends StatefulWidget {
|
||||
final List<AO> items;
|
||||
ApplicationView({Key key})
|
||||
: items = null,
|
||||
super(key: key);
|
||||
|
||||
ApplicationView.custom({Key key, @required this.items})
|
||||
: assert(items != null),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
_ApplicationViewState createState() => _ApplicationViewState();
|
||||
}
|
||||
|
||||
class _ApplicationViewState extends State<ApplicationView> {
|
||||
_buildTile(AO object) {
|
||||
return MaterialButton(
|
||||
shape: StadiumBorder(),
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () => Get.to(object.page),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
object.path,
|
||||
height: 75.w,
|
||||
width: 75.w,
|
||||
),
|
||||
8.hb,
|
||||
object.title.text.size(24.sp).make(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool get _isCustom => widget.items != null;
|
||||
List<AO> get _items {
|
||||
final appProvider = Provider.of<AppProvider>(context);
|
||||
|
||||
return _isCustom ? widget.items : appProvider.myApplications;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GridView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
|
||||
itemBuilder: (context, index) {
|
||||
if (index == _items.length) return _buildTile(allApp);
|
||||
return _buildTile(_items[index]);
|
||||
},
|
||||
itemCount: _items.length + 1,
|
||||
shrinkWrap: true,
|
||||
);
|
||||
}
|
||||
}
|