Sfoglia il codice sorgente

1、搜索页面

tags/0.0.1
PH2 4 anni fa
parent
commit
27cd1d6e31
28 ha cambiato i file con 1614 aggiunte e 64 eliminazioni
  1. +1
    -2
      lib/pages/goods_details_page/goods_details_page.dart
  2. +54
    -0
      lib/pages/search_page/bloc/search_bloc.dart
  3. +28
    -0
      lib/pages/search_page/bloc/search_event.dart
  4. +27
    -0
      lib/pages/search_page/bloc/search_repository.dart
  5. +36
    -0
      lib/pages/search_page/bloc/search_state.dart
  6. +137
    -0
      lib/pages/search_page/search_page.dart
  7. +183
    -0
      lib/pages/search_page/search_page2.dart
  8. +148
    -0
      lib/pages/search_page/search_page3.dart
  9. +0
    -11
      lib/pages/sreach_page/sreach_page.dart
  10. +47
    -49
      lib/register.dart
  11. +2
    -2
      lib/widgets/home/home_banner/home_banner_widget.dart
  12. +26
    -0
      lib/widgets/search/appbar/model/search_appbar_model.dart
  13. +28
    -0
      lib/widgets/search/appbar/search_appbar_creater.dart
  14. +55
    -0
      lib/widgets/search/appbar/search_appbar_widget.dart
  15. +129
    -0
      lib/widgets/search/history_tag/history_tag.dart
  16. +32
    -0
      lib/widgets/search/input/model/search_input_model.dart
  17. +27
    -0
      lib/widgets/search/input/search_input_creater.dart
  18. +36
    -0
      lib/widgets/search/input/search_input_sk.dart
  19. +172
    -0
      lib/widgets/search/input/search_input_widget.dart
  20. +55
    -0
      lib/widgets/search/tabbar/model/search_tab_model.dart
  21. +24
    -0
      lib/widgets/search/tabbar/search_tab_creater.dart
  22. +22
    -0
      lib/widgets/search/tabbar/search_tab_sk.dart
  23. +105
    -0
      lib/widgets/search/tabbar/search_tab_widget.dart
  24. +19
    -0
      lib/widgets/search/widget/color_utils.dart
  25. +83
    -0
      lib/widgets/search/widget/my_tab.dart
  26. +81
    -0
      lib/widgets/search/widget/text_tag_widget.dart
  27. +56
    -0
      lib/widgets/search/widget/title_widget.dart
  28. +1
    -0
      pubspec.yaml

+ 1
- 2
lib/pages/goods_details_page/goods_details_page.dart Vedi File

@@ -55,8 +55,7 @@ class GoodsDetailsContainer extends StatefulWidget {
class _GoodsDetailsContainerState extends State<GoodsDetailsContainer> {
bool _isEnded = false;
ScrollController _controller = ScrollController();
RefreshController _refreshController =
RefreshController(initialRefresh: false);
RefreshController _refreshController = RefreshController(initialRefresh: false);

void _onLoading() async {
// await Future.delayed(Duration(milliseconds: 1000));


+ 54
- 0
lib/pages/search_page/bloc/search_bloc.dart Vedi File

@@ -0,0 +1,54 @@
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'search_repository.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

part 'search_event.dart';

part 'search_state.dart';

class SearchBloc extends Bloc<SearchEvent, SearchState> {
// SreachBloc() : super(SreachInitial());

SearchRepository repository;

SearchBloc({this.repository});

@override
SearchState get initialState => SearchInitial();

@override
Stream<SearchState> mapEventToState(
SearchEvent event,
) async* {
/// 初始化方法
if (event is SearchInitEvent) {
yield* _mapInitEventToState(event);
}

/// 搜索的方法
if (event is SearchSubmitEvent) {
yield* _mapSearchSubmitToState(event);
}
}

/// 初始化
Stream<SearchState> _mapInitEventToState(SearchInitEvent event) async* {
/// 获取数据
var result = await repository.fetchInit(event.model);
Logger.log('result = ${result.toString()}');
if (!EmptyUtil.isEmpty(result)) {
yield SearchLoadedState(model: result);
} else {
yield SearchErrorState();
}
}

/// 搜索的方法
Stream<SearchState> _mapSearchSubmitToState(SearchSubmitEvent event) async* {
var result = await repository.fetchSearchSubmit(event.model);
}
}

+ 28
- 0
lib/pages/search_page/bloc/search_event.dart Vedi File

@@ -0,0 +1,28 @@
part of 'search_bloc.dart';

abstract class SearchEvent extends Equatable {
const SearchEvent();

@override
List<Object> get props => [];
}

/// 初始化方法
class SearchInitEvent extends SearchEvent {
final Map<String, dynamic> model;

const SearchInitEvent({this.model});

@override
List<Object> get props => [model];
}

/// 搜索方法
class SearchSubmitEvent extends SearchEvent {
final String model;

const SearchSubmitEvent({@required this.model});

@override
List<Object> get props => [this.model];
}

+ 27
- 0
lib/pages/search_page/bloc/search_repository.dart Vedi File

@@ -0,0 +1,27 @@
import 'package:zhiying_comm/zhiying_comm.dart';

class SearchRepository {
List<Map<String, dynamic>> _pageData = [];

/// 获取网络数据
Future<List<Map<String, dynamic>>> fetchInit(final Map<String, dynamic> model) async {
var result = await NetUtil.post('/api/v1/mod/pub.flutter.search_index', method: NetMethod.GET);
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result)) {
try {
_pageData = List.from(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list']);
return _pageData;
} catch (e) {
Logger.error(e.toString());
}
}
return null;
}

/// 获取缓存数据
Future<List<Map<String, dynamic>>> fetchCachedData(final Map<String, dynamic> model) {}

/// 搜索的方法
Future<void> fetchSearchSubmit(final String model) async {
var result = await NetUtil.post('');
}
}

+ 36
- 0
lib/pages/search_page/bloc/search_state.dart Vedi File

@@ -0,0 +1,36 @@
part of 'search_bloc.dart';

abstract class SearchState extends Equatable {
const SearchState();

@override
List<Object> get props => [];
}

class SearchInitial extends SearchState {
@override
List<Object> get props => [];
}

/// 数据加载完毕
class SearchLoadedState extends SearchInitial {
List<Map<String, dynamic>> model;

SearchLoadedState({this.model});

@override
List<Object> get props => [this.model];
}

/// 搜索成功
class SearchSubmitSuccessState extends SearchState{

}

/// 搜索失败
class SearchSubmitErrorState extends SearchState{

}

/// 数据加载出错
class SearchErrorState extends SearchState {}

+ 137
- 0
lib/pages/search_page/search_page.dart Vedi File

@@ -0,0 +1,137 @@
import 'package:flutter/material.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'bloc/search_bloc.dart';
import 'bloc/search_repository.dart';

///
/// 搜索页
///
class SearchPage extends StatelessWidget {
final Map<String, dynamic> data;

SearchPage(this.data, {Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
return BlocProvider<SearchBloc>(
create: (_) => SearchBloc(repository: SearchRepository())..add(SearchInitEvent(model: data)),
child: SearchPageContianer(),
);
}
}

class SearchPageContianer extends StatefulWidget {
@override
_SearchPageContianerState createState() => _SearchPageContianerState();
}

class _SearchPageContianerState extends State<SearchPageContianer> {
/// tab轮播
TabController _tabController;
ScrollController _controller = ScrollController();

@override
void initState() {
_tabController = TabController(length:0, vsync: ScrollableState());
super.initState();
}

@override
void dispose() {
_controller?.dispose();
_tabController?.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return MediaQuery.removePadding(
removeTop: true,
context: context,
child: Container(
width: double.infinity,
child: BlocConsumer<SearchBloc, SearchState>(
listener: (BuildContext context, SearchState state) {
if (state is SearchErrorState) {
print('数据加载出错');
}
},
buildWhen: (previous, current) {
/// 数据加载出错不进行build
if (current is SearchErrorState) {
return false;
}

/// 搜索成功,跳转结果页面
if (current is SearchSubmitSuccessState) {
return false;
}

/// 搜索失败,不进行build
if (current is SearchSubmitErrorState) {
return false;
}

return true;
},
builder: (context, state) {
print('currente state = $state');
if (state is SearchLoadedState) {
return _getMainWidget(state?.model);
}

/// 骨架屏幕
return _getMainWidget(null);
},
),
),
);
}

/// 主视图
Widget _getMainWidget(List<Map<String, dynamic>> datas) {
return Scaffold(
backgroundColor: Colors.white,
body: CustomScrollView(
controller: _controller,
slivers: _createContent(context, datas ?? []),
),
);
}

List<Widget> _createContent(BuildContext context, List<Map<String, dynamic>> datas) {
List<Widget> list = List();

int length = datas?.length ?? 0;

if (length <= 0) {
list.add(SliverToBoxAdapter(
child: Container(
height: 200,
child: Center(
child: Text('暂时无数据哦~'),
),
),
));
return list;
}

for (int i = 0; i < 3; i++) {
WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
print('item.modName ${item.modName}');
list.addAll(WidgetFactory.create(
item.modName,
isSliver: true,
model: datas[i],
));
}

list.add(SliverFillRemaining(
child: Text('etstssss et'),
));

return list;
}
}

+ 183
- 0
lib/pages/search_page/search_page2.dart Vedi File

@@ -0,0 +1,183 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'bloc/search_bloc.dart';
import 'bloc/search_repository.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

class SearchPage2 extends StatelessWidget {
final Map<String, dynamic> data;

const SearchPage2(this.data);

@override
Widget build(BuildContext context) {
return BlocProvider<SearchBloc>(
create: (_) => SearchBloc(repository: SearchRepository())..add(SearchInitEvent(model: data)),
child: SearchPage2Container(),
);
}
}

class SearchPage2Container extends StatefulWidget {
@override
_SearchPage2ContainerState createState() => _SearchPage2ContainerState();
}

class _SearchPage2ContainerState extends State<SearchPage2Container> {

TabController _controller;

@override
void initState() {
_controller = TabController(length: tabTitle.length, vsync: ScrollableState());
super.initState();
}

@override
void dispose() {
_controller?.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return MediaQuery.removePadding(
removeTop: true,
context: context,
child: Container(
width: double.infinity,
child: BlocConsumer<SearchBloc, SearchState>(
listener: (BuildContext context, SearchState state) {
if (state is SearchErrorState) {
print('数据加载出错');
}
},
buildWhen: (previous, current) {
/// 数据加载出错不进行build
if (current is SearchErrorState) {
return false;
}

/// 搜索成功,跳转结果页面
if (current is SearchSubmitSuccessState) {
return false;
}

/// 搜索失败,不进行build
if (current is SearchSubmitErrorState) {
return false;
}

return true;
},
builder: (context, state) {
print('currente state = $state');
if (state is SearchLoadedState) {
return _getMainWidget(state?.model);
}

/// 骨架屏幕
return _getMainWidget(null);
},
),
),
);
}

/// 主视图
Widget _getMainWidget(List<Map<String, dynamic>> datas){
return Scaffold(
backgroundColor: Colors.white,
body: NestedScrollView(
headerSliverBuilder: (context, bool){
return _createHeadWidget(context, datas);
},
body: ListView(
children: <Widget>[
Text('sss')
],
),
),
);
}


/// 头部视图
List<Widget> _createHeadWidget(BuildContext context, List<Map<String, dynamic>> datas){
List<Widget> list = [];

int length = datas?.length?? 0;
if (length <= 0) {
list.add(SliverToBoxAdapter(
child: Container(
height: 200,
child: Center(
child: Text('暂时无数据哦~'),
),
),
));
return list;
}

for (int i = 0; i < 2; i++) {
WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
print('item.modName ${item.modName}');
list.addAll(WidgetFactory.create(
item.modName,
isSliver: true,
model: datas[i],
));
}
list.add(_getTabbar());
return list;

}

var tabTitle = [
'页面1',
'页面2',
'页面3',
];

Widget _getTabbar(){
/// 悬停TabBar
return SliverPersistentHeader(
delegate: new SliverTabBarDelegate(
TabBar(
controller: _controller,
tabs: tabTitle.map((f) => Tab(text: f)).toList(),
indicatorColor: Colors.red,
unselectedLabelColor: Colors.black,
labelColor: Colors.red,
),
),
pinned: true,
);
}

}

class SliverTabBarDelegate extends SliverPersistentHeaderDelegate {
final TabBar widget;


const SliverTabBarDelegate(this.widget)
: assert(widget != null);

@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container( color:Colors.white,child: this.widget);
}

@override
bool shouldRebuild(SliverTabBarDelegate oldDelegate) {
return false;
}

@override
double get maxExtent => widget.preferredSize.height;

@override
double get minExtent => widget.preferredSize.height;
}

+ 148
- 0
lib/pages/search_page/search_page3.dart Vedi File

@@ -0,0 +1,148 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'bloc/search_bloc.dart';
import 'bloc/search_repository.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

class SearchPage3 extends StatelessWidget {
final Map<String, dynamic> data;

const SearchPage3(this.data);

@override
Widget build(BuildContext context) {
return BlocProvider<SearchBloc>(
create: (_) => SearchBloc(repository: SearchRepository())..add(SearchInitEvent(model: data)),
child: SearchPage3Container(),
);
}
}

class SearchPage3Container extends StatefulWidget {
@override
_SearchPage3ContainerState createState() => _SearchPage3ContainerState();
}

class _SearchPage3ContainerState extends State<SearchPage3Container> {
@override
Widget build(BuildContext context) {
return MediaQuery.removePadding(
removeTop: true,
context: context,
child: Container(
width: double.infinity,
child: BlocConsumer<SearchBloc, SearchState>(
listener: (BuildContext context, SearchState state) {
if (state is SearchErrorState) {
print('数据加载出错');
}
},
buildWhen: (previous, current) {
/// 数据加载出错不进行build
if (current is SearchErrorState) {
return false;
}

/// 搜索成功,跳转结果页面
if (current is SearchSubmitSuccessState) {
return false;
}

/// 搜索失败,不进行build
if (current is SearchSubmitErrorState) {
return false;
}

return true;
},
builder: (context, state) {
print('currente state = $state');
if (state is SearchLoadedState) {
return _getMainWidget(state?.model);
}

/// 骨架屏幕
return _getMainWidget(null);
},
),
),
);
}

/// 主视图
Widget _getMainWidget(List<Map<String, dynamic>> datas){
return Scaffold(
backgroundColor: Colors.white,
body: NestedScrollView(
headerSliverBuilder: (context, bool){
return _createHeadWidget(context, datas);
},
body: Container(
child: Text('testssfee'),
),
),
);
}


/// 头部视图
List<Widget> _createHeadWidget(BuildContext context, List<Map<String, dynamic>> datas){
List<Widget> list = [];

int length = datas?.length?? 0;
if (length <= 0) {
list.add(SliverToBoxAdapter(
child: Container(
height: 200,
child: Center(
child: Text('暂时无数据哦~'),
),
),
));
return list;
}

for (int i = 0; i < 3; i++) {
WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
print('item.modName ${item.modName}');
list.addAll(WidgetFactory.create(
item.modName,
isSliver: true,
model: datas[i],
));
}
return list;

}


/// 子视图


List<Widget> _createContent(BuildContext context, List<Map<String, dynamic>> datas) {
List<Widget> list = List();

/// datas.length - 1 为最后一个在底部
for (int i = 0; i < datas.length; i++) {
WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
print('item.modName ${item.modName}');
list.addAll(WidgetFactory.create(
item.modName,
isSliver: true,
model: datas[i],
));
}
if (list.length <= 0) {
list.add(SliverToBoxAdapter(
child: Container(
height: 200,
child: Center(
child: Text('暂时无数据哦~'),
),
),
));
}
return list;
}
}


+ 0
- 11
lib/pages/sreach_page/sreach_page.dart Vedi File

@@ -1,11 +0,0 @@
import 'package:flutter/material.dart';

///
/// 搜索页
///
class SreachPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}

+ 47
- 49
lib/register.dart Vedi File

@@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:zhiying_base_widget/pages/goods_details_page/goods_details_page.dart';
import 'package:zhiying_base_widget/pages/home_page/home_page.dart';
import 'package:zhiying_base_widget/pages/main_page/main_page.dart';
@@ -8,7 +9,6 @@ import 'package:zhiying_base_widget/pages/security_page/security_mobile/security
import 'package:zhiying_base_widget/pages/security_page/security_page.dart';
import 'package:zhiying_base_widget/pages/security_page/security_password/security_password.dart';
import 'package:zhiying_base_widget/pages/setting_page/setting_page.dart';
import 'package:zhiying_base_widget/pages/sreach_page/sreach_page.dart';
import 'package:zhiying_base_widget/pages/sreach_result_page/sreach_result_page.dart';
import 'package:zhiying_base_widget/pages/wallet_page/wallet_page.dart';
import 'package:zhiying_base_widget/pages/webview/base_webview.dart';
@@ -36,11 +36,16 @@ import 'package:zhiying_base_widget/widgets/wallet/wallet_income/wallet_income.d
import 'package:zhiying_comm/util/defalut_widget_creater.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

import 'pages/search_page/search_page.dart';
import 'widgets/goods_details/coupon/counpon_widget.dart';
import 'widgets/goods_details/detail_img/goods_details_img.dart';
import 'widgets/goods_details/evaluate/goods_details_evaluate_widget.dart';
import 'widgets/goods_details/recommend/goods_detail_commend_creater.dart';
import 'widgets/goods_details/title/goods_details_title_widget.dart';
import 'widgets/home/home_quick_entry/home_quick_entry.dart';
import 'widgets/search/input/search_input_widget.dart';
import 'widgets/search/tabbar/search_tab_creater.dart';
import 'widgets/search/tabbar/search_tab_widget.dart';

class BaseWidgetRegister {
/// 初始化方法
@@ -56,7 +61,7 @@ class BaseWidgetRegister {
PageFactory.regist('profile', (model) => MainPage(model));
PageFactory.regist('category', (model) => WalletPage());
PageFactory.regist('goods_details', (model) => GoodsDetailsPage(model));
PageFactory.regist('sreach', (model) => SreachPage());
PageFactory.regist('sreach', (model) => SearchPage(model));
PageFactory.regist('sreach_result', (model) => SreachResultPage());
// PageFactory.regist('login', (model) => LoginPage(model));
// PageFactory.regist('login_quick', (model) => LoginQuickPage(model));
@@ -92,86 +97,79 @@ class BaseWidgetRegister {
// ==================== 首页
// WidgetFactory.regist('index_title', NormalNavCreater());
/// 首页搜索栏
// WidgetFactory.regist('index_search', HomeSreachCreater());
WidgetFactory.regist('index_search',
DefaultWidgetCreater((model) => HomeSreachWidget(model)));
WidgetFactory.regist('index_search', HomeSreachCreater());
// WidgetFactory.regist('index_search',
// DefaultWidgetCreater((model) => HomeSreachWidget(model)));

/// 可滚动banner
WidgetFactory.regist('index_carousel', HomeSlideBannerCreater());
WidgetFactory.regist('index_recommend_list', GoodsListCreater());

/// 首页快速入口
WidgetFactory.regist(
'multi_nav', DefaultWidgetCreater((model) => HomeQuickEntry(model)));
WidgetFactory.regist('multi_nav', DefaultWidgetCreater((model) => HomeQuickEntry(model)));

/// 滚动公告
WidgetFactory.regist('index_placard',
DefaultWidgetCreater((model) => HomeNoticeWidget(model)));
WidgetFactory.regist('index_placard', DefaultWidgetCreater((model) => HomeNoticeWidget(model)));

/// 不可以滚动banner
WidgetFactory.regist('index_banner_one', HomeBannerCreater());
WidgetFactory.regist('index_banner_two', HomeBannerCreater());
// WidgetFactory.regist('index_taobao_auth_tip', HomeAuthCreater());

/// ==================== 搜索页面 ==================== ///
// 搜索标题
// WidgetFactory.regist('search_index_app_bar', DefaultWidgetCreater((model) => SearchAppbarWidget(model)));
WidgetFactory.regist('search_index_app_bar', SearchAppbarCreater());
// 搜索输入框
WidgetFactory.regist('search_index_input', SearchInputCreater());
// WidgetFactory.regist('search_index_input', DefaultWidgetCreater((model) => SearchInputWidget(model)));
// // 搜索tabBar
WidgetFactory.regist('search_index_icon_list', SearcchTabCreater());
// WidgetFactory.regist('search_index_icon_list', DefaultWidgetCreater((model) => SearchTabWidget(model)));
// // 热门搜索标签
// WidgetFactory.regist('search_index', null);
// // 历史搜索标签
// WidgetFactory.regist('search_index_history', null);

/// ==================== 商品详情 ==================== ///
// 商品详情轮播图
WidgetFactory.regist('product_detail_carousel',
DefaultWidgetCreater((model) => GoodsDetailsSlideBannerWidget(model)));
WidgetFactory.regist('product_detail_carousel', DefaultWidgetCreater((model) => GoodsDetailsSlideBannerWidget(model)));
// 商品详情下载APP提示
WidgetFactory.regist('product_detail_download_tips',
DefaultWidgetCreater((model) => UpgradeTipWidget(model)));
WidgetFactory.regist('product_detail_download_tips', DefaultWidgetCreater((model) => UpgradeTipWidget(model)));
// 商品详情价格显示
WidgetFactory.regist('product_detail_price',
DefaultWidgetCreater((model) => GoodsDetailsPriceWidget(model)));
WidgetFactory.regist('product_detail_price', DefaultWidgetCreater((model) => GoodsDetailsPriceWidget(model)));
// 商品详情标题
WidgetFactory.regist('product_detail_title',
DefaultWidgetCreater((model) => GoodsDetailsTitleWidget(model)));
WidgetFactory.regist('product_detail_title', DefaultWidgetCreater((model) => GoodsDetailsTitleWidget(model)));
// 商品详情优惠劵
WidgetFactory.regist('product_detail_coupon',
DefaultWidgetCreater((model) => CounponWidget(model)));
WidgetFactory.regist('product_detail_coupon', DefaultWidgetCreater((model) => CounponWidget(model)));
// 商品详情店铺
WidgetFactory.regist('product_detail_shop',
DefaultWidgetCreater((model) => StoreWidget(model)));
WidgetFactory.regist('product_detail_shop', DefaultWidgetCreater((model) => StoreWidget(model)));
// 商品详情宝贝评价
WidgetFactory.regist('product_detail_comment',
DefaultWidgetCreater((model) => GoodsDetailsEvaluateWidget(model)));
WidgetFactory.regist('product_detail_comment', DefaultWidgetCreater((model) => GoodsDetailsEvaluateWidget(model)));
// 商品详情图片
WidgetFactory.regist('product_detail_img_list',
DefaultWidgetCreater((model) => GoodsDetailsImgWidget(model)));
WidgetFactory.regist('product_detail_img_list', DefaultWidgetCreater((model) => GoodsDetailsImgWidget(model)));
// 商品详情底部推荐列表
WidgetFactory.regist('product_detail_bottom_rec',
DefaultWidgetCreater((model) => GoodsListWidget(model)));
WidgetFactory.regist('product_detail_bottom_rec', GoodsDetailCommendCreater());
// 商品详情底部
WidgetFactory.regist('product_detail_bottom',
DefaultWidgetCreater((model) => GoodsDetailsFooterWidget(model)));
WidgetFactory.regist('product_detail_bottom', DefaultWidgetCreater((model) => GoodsDetailsFooterWidget(model)));

// ==================== 个人中心
WidgetFactory.regist('profile_appbar', MineNavCreater());
WidgetFactory.regist('profile_background',
DefaultWidgetCreater((model) => MineNavBg(model)));
WidgetFactory.regist(
'profile_header', DefaultWidgetCreater((model) => MineHeader(model)));
WidgetFactory.regist(
'profile_earning', DefaultWidgetCreater((model) => MineData(model)));
WidgetFactory.regist('profile_functions',
DefaultWidgetCreater((model) => MineQuickEntry(model)));
WidgetFactory.regist('profile_my_functions',
DefaultWidgetCreater((model) => MineQuickEntry(model)));
WidgetFactory.regist('profile_carousel',
DefaultWidgetCreater((model) => HomeBannerWidget(model)));
WidgetFactory.regist('profile_background', DefaultWidgetCreater((model) => MineNavBg(model)));
WidgetFactory.regist('profile_header', DefaultWidgetCreater((model) => MineHeader(model)));
WidgetFactory.regist('profile_earning', DefaultWidgetCreater((model) => MineData(model)));
WidgetFactory.regist('profile_functions', DefaultWidgetCreater((model) => MineQuickEntry(model)));
WidgetFactory.regist('profile_my_functions', DefaultWidgetCreater((model) => MineQuickEntry(model)));
WidgetFactory.regist('profile_carousel', DefaultWidgetCreater((model) => HomeBannerWidget(model)));

// ==================== 钱包
WidgetFactory.regist(
'wallet_data', DefaultWidgetCreater((model) => WalletData()));
WidgetFactory.regist('wallet_data', DefaultWidgetCreater((model) => WalletData()));
// WidgetFactory.regist(
// 'wallet_detail', DefaultWidgetCreater((model) => WalletDetail()));
// WidgetFactory.regist('wallet_detail', HomeAuthCreater());
WidgetFactory.regist(
'wallet_data', DefaultWidgetCreater((model) => WalletData()));
WidgetFactory.regist(
'wallet_detail', DefaultWidgetCreater((model) => WalletDetail()));
WidgetFactory.regist('wallet_data', DefaultWidgetCreater((model) => WalletData()));
WidgetFactory.regist('wallet_detail', DefaultWidgetCreater((model) => WalletDetail()));

WidgetFactory.regist(
'wallet_income', DefaultWidgetCreater((model) => WalletIncome()));
WidgetFactory.regist('wallet_income', DefaultWidgetCreater((model) => WalletIncome()));
}
}

+ 2
- 2
lib/widgets/home/home_banner/home_banner_widget.dart Vedi File

@@ -61,8 +61,8 @@ class _HomeBannerContainerState extends State<HomeBannerContainer> {
builder: (context, state) {
print(state);
if (state is HomeBannerLoadedState) {
int lenght = state?.model?.list?.length ?? 0;
if (lenght > 0)
int length = state?.model?.list?.length ?? 0;
if (length > 0)
return _getMainWidget(data: state?.model?.list);
else
return HomeBannerSkeleton(widget?.model);


+ 26
- 0
lib/widgets/search/appbar/model/search_appbar_model.dart Vedi File

@@ -0,0 +1,26 @@
class SearchAppbarModel {
String app_bar_bg_color;
String app_bar_title;
String app_bar_title_color;
String back_icon;

SearchAppbarModel({this.app_bar_bg_color, this.app_bar_title, this.app_bar_title_color, this.back_icon});

factory SearchAppbarModel.fromJson(Map<String, dynamic> json) {
return SearchAppbarModel(
app_bar_bg_color: json['app_bar_bg_color'],
app_bar_title: json['app_bar_title'],
app_bar_title_color: json['app_bar_title_color'],
back_icon: json['back_icon'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['app_bar_bg_color'] = this.app_bar_bg_color;
data['app_bar_title'] = this.app_bar_title;
data['app_bar_title_color'] = this.app_bar_title_color;
data['back_icon'] = this.back_icon;
return data;
}
}

+ 28
- 0
lib/widgets/search/appbar/search_appbar_creater.dart Vedi File

@@ -0,0 +1,28 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:zhiying_base_widget/widgets/search/appbar/search_appbar_widget.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'dart:ui';
import 'package:zhiying_comm/util/custom_sliver_persistent_header_delegate.dart';

class SearchAppbarCreater extends WidgetCreater {
@override
List<Widget> createWidgets(Map<String, dynamic> model) {
return [
SliverPersistentHeader(
delegate: CustomSliverPersistentHeaderDelegate(
child: SearchAppbarWidget(model),
max: MediaQueryData.fromWindow(window).padding.top + 44,
min: MediaQueryData.fromWindow(window).padding.top + 44,
),
pinned: true,
floating: false,
),
];
}

@override
bool isSliverChild() {
return true;
}
}

+ 55
- 0
lib/widgets/search/appbar/search_appbar_widget.dart Vedi File

@@ -0,0 +1,55 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/search/appbar/model/search_appbar_model.dart';
import 'dart:ui';
import 'package:zhiying_comm/zhiying_comm.dart';

class SearchAppbarWidget extends StatelessWidget {
final Map<String, dynamic> data;
SearchAppbarModel model;

SearchAppbarWidget(this.data, {Key key}) : super(key: key) {
try {
model = SearchAppbarModel.fromJson(jsonDecode(data['data']));
} catch (e) {
Logger.error(e);
}
}

/// 返回键
void _openPop(BuildContext context) {
Navigator.maybePop(context);
}

@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
color: HexColor.fromHex(model?.app_bar_bg_color ?? '#FFFFFF'),
padding: EdgeInsets.only(top: MediaQueryData.fromWindow(window).padding.top),
child: _getMainWidget(context),
);
}

/// 样式1
Widget _getMainWidget(BuildContext context) {
return AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios,
size: 22,
color: HexColor.fromHex('#333333'),
),
onPressed: () => _openPop(context),
),
title: Text(
model?.app_bar_title ?? '搜索',
style: TextStyle(fontWeight: FontWeight.bold, color: HexColor.fromHex(model?.app_bar_title_color ?? '#333333')),
),
centerTitle: true,
);
}
}

+ 129
- 0
lib/widgets/search/history_tag/history_tag.dart Vedi File

@@ -0,0 +1,129 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:zhiying_base_widget/widgets/search/widget/text_tag_widget.dart';
import 'package:zhiying_base_widget/widgets/search/widget/title_widget.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
/// 历史搜索标签
///
class HistoryTagWidget extends StatefulWidget {
final Map<String, dynamic> data;

const HistoryTagWidget(this.data);

@override
_HistoryTagWidgetState createState() => _HistoryTagWidgetState();
}

class _HistoryTagWidgetState extends State<HistoryTagWidget> {
///文本标签集合
List<String> _tagList = [];
static final String SP_HOISTROY_KEY = 'hoistroyTag';
static final int MAX_COUNT = 6;

/// 点击历史标签
void _historyTagClick(String tag) {}

/// 初始化历史搜索标签
_initHistoryTag() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String jsonStr = prefs.getString(SP_HOISTROY_KEY);
if (null != jsonStr && jsonStr.length > 0) {
final Map jsonMap = jsonDecode(jsonStr);
if (jsonMap != null && jsonMap.length > 0) {
jsonMap.forEach((key, value) => _tagList.insert(0, value));
}
}
}

/// 添加搜索
void _addTag(String tag) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String jsonStr = prefs.getString(SP_HOISTROY_KEY);
if (null != jsonStr && jsonStr.length > 0) {
final Map jsonMap = jsonDecode(jsonStr);
jsonMap[tag.toString()] = tag.toString();

_tagList.insert(0, tag); // 第一位
if (_tagList.length > MAX_COUNT) {
jsonMap.remove(_tagList[_tagList.length - 1]);
_tagList.removeAt(_tagList.length - 1);
}

prefs.setString(SP_HOISTROY_KEY, jsonEncode(jsonMap));
} else {
prefs.setString(SP_HOISTROY_KEY, jsonEncode({'${tag.toString()}': '${tag.toString()}'}));
_tagList.add(tag);
}
setState(() {});
}

/// 点击清除所有历史记录
void _clearTag() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString(SP_HOISTROY_KEY, '');
}

@override
void initState() {
_initHistoryTag();
super.initState();
}

@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: const EdgeInsets.only(left: 12.5, right: 12.5),
child: Column(
children: <Widget>[
/// 标题
SearchTitleWidget(titleText: '历史搜索', titleTextColor: '#333333', iconUrl: '', callback: () => _clearTag()),
const SizedBox(
height: 10,
),

/// 历史标签
_getHistoryWarp(),
],
),
);
}

/// 历史搜索的标签
Widget _getHistoryWarp() {
List<Widget> itemWidgetList = [];
final int tagListLength = _tagList?.length ?? 0;
if (tagListLength > 0) {
for (var i = 0; i < _tagList.length; i++) {
var str = _tagList[i];
itemWidgetList.add(GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => _historyTagClick(_tagList[i]),
child: TextTagWidget(
"$str",
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 10),
margin: const EdgeInsets.only(right: 5, bottom: 0, top: 0),
borderColor: HexColor.fromHex('#EDEDED'),
backgroundColor: Colors.white,
textStyle: TextStyle(
color: HexColor.fromHex('#383838'),
fontSize: 12.5,
),
),
));
}

return Wrap(
spacing: 8.0,
runSpacing: 8.0,

///子标签
children: itemWidgetList);
}
return Container();
}
}

+ 32
- 0
lib/widgets/search/input/model/search_input_model.dart Vedi File

@@ -0,0 +1,32 @@
class SearchInputModel {
String search_button;
String search_button_color;
String search_button_t;
String search_icon;
String search_inpu_hint_text;
String skip_identifier;

SearchInputModel({this.search_button, this.search_button_color, this.search_button_t, this.search_icon, this.search_inpu_hint_text, this.skip_identifier});

factory SearchInputModel.fromJson(Map<String, dynamic> json) {
return SearchInputModel(
search_button: json['search_button'],
search_button_color: json['search_button_color'],
search_button_t: json['search_button_t'],
search_icon: json['search_icon'],
search_inpu_hint_text: json['search_inpu_hint_text'],
skip_identifier: json['skip_identifier'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['search_button'] = this.search_button;
data['search_button_color'] = this.search_button_color;
data['search_button_t'] = this.search_button_t;
data['search_icon'] = this.search_icon;
data['search_inpu_hint_text'] = this.search_inpu_hint_text;
data['skip_identifier'] = this.skip_identifier;
return data;
}
}

+ 27
- 0
lib/widgets/search/input/search_input_creater.dart Vedi File

@@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:zhiying_base_widget/widgets/search/input/search_input_widget.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:zhiying_comm/util/custom_sliver_persistent_header_delegate.dart';

class SearchInputCreater extends WidgetCreater {
@override
List<Widget> createWidgets(Map<String, dynamic> model) {
return [
SliverPersistentHeader(
delegate: CustomSliverPersistentHeaderDelegate(
child: SearchInputWidget(model),
min: 35,
max: 35,
),
pinned: true,
floating: false,
)
];
}

@override
bool isSliverChild() {
return true;
}
}

+ 36
- 0
lib/widgets/search/input/search_input_sk.dart Vedi File

@@ -0,0 +1,36 @@


import 'package:shimmer/shimmer.dart';
import 'package:flutter/material.dart';


///
/// 搜索输入框的骨架图
///
class SearchInputSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: const EdgeInsets.only(right: 12.5, left: 12.5, top: 13),
child: _shimmerWidget(
width: double.infinity,
height: 32,
),
);
}



Widget _shimmerWidget({double width, double height, double radius = 0}) {
return Shimmer.fromColors(
baseColor: Colors.grey[300],
highlightColor: Colors.grey[100],
child: Container(
width: width,
height: height,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(radius)),
),
);
}
}

+ 172
- 0
lib/widgets/search/input/search_input_widget.dart Vedi File

@@ -0,0 +1,172 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/home/home_quick_entry/cached_network_image_util.dart';
import 'package:zhiying_base_widget/widgets/search/input/model/search_input_model.dart';
import 'package:zhiying_base_widget/widgets/search/input/search_input_sk.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:cached_network_image/cached_network_image.dart';

///
/// 搜索页的搜索框
///
class SearchInputWidget extends StatefulWidget {
final Map<String, dynamic> data;
SearchInputModel model;

SearchInputWidget(this.data, {Key key}) : super(key: key) {
try {
model = SearchInputModel.fromJson(jsonDecode(data['data']));
} catch (e) {
Logger.error(e);
}
}

@override
_SearchInputWidgetState createState() => _SearchInputWidgetState();
}

class _SearchInputWidgetState extends State<SearchInputWidget> {
/// 点击搜索按钮
void _onSearchButtomClick() {}

FocusNode _focusNode;
TextEditingController _editingController;

@override
void didChangeDependencies() {
super.didChangeDependencies();
}

@override
void initState() {
_focusNode = FocusNode();
_editingController = TextEditingController();
super.initState();
}

@override
void dispose() {
_focusNode?.unfocus();
_focusNode?.dispose();
_editingController?.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Visibility(
visible: !EmptyUtil.isEmpty(widget?.model),
replacement: SearchInputSkeleton(),
child: _getMainWidget(widget?.model),
);
}

/// 获取主视图
Widget _getMainWidget(SearchInputModel model) {
return Container(
width: double.infinity,
height: 32,
margin: const EdgeInsets.only(
left: 12.5,
right: 12.5,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: HexColor.fromHex('#F9F9F9'),
),
child: Row(
children: <Widget>[
/// 搜索icon
_getSearchIconWidget(model),
const SizedBox(width: 7.5),

/// 搜索输入框
Expanded(child: _getSearchInputWidget(model)),

/// 搜索按钮
_getSearchButtomWidget(model),
],
),
);
}

/// 搜索icon
Widget _getSearchIconWidget(SearchInputModel model) {
return Container(
height: double.infinity,
width: 20,
margin: const EdgeInsets.only(left: 12.5),
padding: const EdgeInsets.symmetric(vertical: 6),
child: CachedNetworkImage(
imageUrl: model?.search_icon ?? '',
),
);
}

/// 搜索输入框
Widget _getSearchInputWidget(SearchInputModel model) {
return Container(
height: double.infinity,
alignment: Alignment.centerLeft,
// padding: const EdgeInsets.symmetric(vertical: 6),
child: TextField(
showCursor: true,
cursorWidth: 1,
style: TextStyle(fontSize: 14, color: HexColor.fromHex('#333333')),
decoration: InputDecoration(
filled: false,
// focusColor: Colors.transparent,
// fillColor: Colors.transparent,
border: InputBorder.none,
focusedBorder: InputBorder.none,
focusedErrorBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
enabledBorder: InputBorder.none,
hintText: '搜索更多优惠商品',
hintStyle: TextStyle(color: HexColor.fromHex('#999999'), fontSize: 14),
),
),
);
}

/// 搜索按钮
Widget _getSearchButtomWidget(SearchInputModel model) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => _onSearchButtomClick(),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 17.5, vertical: 6),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [HexColor.fromHex('#FD5E5E'), HexColor.fromHex('#FF0100')], begin: Alignment.centerLeft, end: Alignment.centerRight),
borderRadius: BorderRadius.circular(30),
),
child: Text(
'搜索',
style: TextStyle(color: HexColor.fromHex('#FFFFFF'), fontSize: 14),
),
),
);
}

/// 【弃用】搜索按钮
// Widget _getSearchButtomWidget() {
// return Material(
// child: Container(
// decoration: BoxDecoration(
// borderRadius: BorderRadius.only(topRight: Radius.circular(25), bottomRight: Radius.circular(25))
// ),
// height: double.infinity,
// width: 63,
// child: RaisedButton(
// padding: const EdgeInsets.only(bottom: 6, top: 6, left: 17.5, right: 17.5),
// shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( 25)),
// child: Text('搜索', style: TextStyle( fontSize: 14, color: HexColor.fromHex('#FFFFFF')),),
// onPressed: ()=> _onSearchButtomClick(),
// color: HexColor.fromHex('#FF0100'),
// ),
// ),
// );
// }
}

+ 55
- 0
lib/widgets/search/tabbar/model/search_tab_model.dart Vedi File

@@ -0,0 +1,55 @@
class SearchTabModel {
List<SearchTabItemModel> search_icon_list;

SearchTabModel({this.search_icon_list});

factory SearchTabModel.fromJson(Map<String, dynamic> json) {
return SearchTabModel(
search_icon_list: json['search_icon_list'] != null ? (json['search_icon_list'] as List).map((i) => SearchTabItemModel.fromJson(i)).toList() : null,
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.search_icon_list != null) {
data['search_icon_list'] = this.search_icon_list.map((v) => v.toJson()).toList();
}
return data;
}
}

class SearchTabItemModel {
String icon;
String line_select_color;
String name;
String name_color;
String name_select_color;
String type;
String with_icon_color;

SearchTabItemModel({this.icon, this.line_select_color, this.name, this.name_color, this.name_select_color, this.type, this.with_icon_color});

factory SearchTabItemModel.fromJson(Map<String, dynamic> json) {
return SearchTabItemModel(
icon: json['icon'],
line_select_color: json['line_select_color'],
name: json['name'],
name_color: json['name_color'],
name_select_color: json['name_select_color'],
type: json['type'],
with_icon_color: json['with_icon_color'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['icon'] = this.icon;
data['line_select_color'] = this.line_select_color;
data['name'] = this.name;
data['name_color'] = this.name_color;
data['name_select_color'] = this.name_select_color;
data['type'] = this.type;
data['with_icon_color'] = this.with_icon_color;
return data;
}
}

+ 24
- 0
lib/widgets/search/tabbar/search_tab_creater.dart Vedi File

@@ -0,0 +1,24 @@
import 'package:flutter/cupertino.dart';
import 'package:zhiying_base_widget/widgets/search/tabbar/search_tab_widget.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:zhiying_comm/util/sliver_tab_bar_delegate.dart';

class SearcchTabCreater extends WidgetCreater{

@override
List<Widget> createWidgets(Map<String, dynamic> model) {
return [
// SliverPersistentHeader(
// delegate: SliverTabBarDelegate(
// SearchTabWidget(model),
// ),
// ),
SearchTabWidget(model),
];
}

@override
bool isSliverChild() {
return true;
}
}

+ 22
- 0
lib/widgets/search/tabbar/search_tab_sk.dart Vedi File

@@ -0,0 +1,22 @@
import 'package:flutter/material.dart';
import 'package:zhiying_comm/util/shimmer_util.dart';

class SearchTabSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: const EdgeInsets.only(left: 12.5, right: 12.5, top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
ShimmerUtil.getShimmerWidget(width: 45, height: 15),
ShimmerUtil.getShimmerWidget(width: 45, height: 15),
ShimmerUtil.getShimmerWidget(width: 45, height: 15),
ShimmerUtil.getShimmerWidget(width: 45, height: 15),
ShimmerUtil.getShimmerWidget(width: 45, height: 15),
],
),
);
}
}

+ 105
- 0
lib/widgets/search/tabbar/search_tab_widget.dart Vedi File

@@ -0,0 +1,105 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:tab_indicator_styler/tab_indicator_styler.dart';
import 'package:zhiying_base_widget/widgets/home/home_quick_entry/cached_network_image_util.dart';
import 'package:zhiying_base_widget/widgets/search/tabbar/search_tab_sk.dart';
import 'package:zhiying_base_widget/widgets/search/widget/my_tab.dart';

import 'package:zhiying_comm/zhiying_comm.dart';

import 'model/search_tab_model.dart';

class SearchTabWidget extends StatefulWidget {
final Map<String, dynamic> data;
SearchTabModel model;

SearchTabWidget(this.data, {Key key}) : super(key: key) {
try {
model = SearchTabModel.fromJson(jsonDecode(data['data']));
} catch (e) {
Logger.error(e.toString());
}
}

@override
_SearchTabWidgetState createState() => _SearchTabWidgetState();
}

class _SearchTabWidgetState extends State<SearchTabWidget> {
TabController _tabController;
int _currentIndex = 0;

@override
void initState() {
_tabController = TabController(length: widget?.model?.search_icon_list?.length ?? 0, vsync: ScrollableState())..addListener((){
setState(()=> _currentIndex = _tabController.index);
});
super.initState();
}

@override
void dispose() {
_tabController?.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return _getMainWidget(widget?.model);
}

/// 获取主视图
Widget _getMainWidget(SearchTabModel model) {
return Visibility(
replacement: SearchTabSkeleton(),
visible: !EmptyUtil.isEmpty(model),
child: _getTabar(model),
);
}

/// 获取TabBar
Widget _getTabar(SearchTabModel model) {
return Container(
margin: const EdgeInsets.only(left: 12.5, right: 12.5, top: 20),
child: TabBar(
controller: _tabController,
isScrollable: true,
labelStyle: TextStyle( fontSize: 14),
unselectedLabelColor: HexColor.fromHex('#999999'),
labelColor: HexColor.fromHex('#FF4242'),
// indicatorSize: TabBarIndicatorSize.label,
indicator: MaterialIndicator(
height: 2.5,
topLeftRadius: 8,
topRightRadius: 8,
bottomLeftRadius: 8,
bottomRightRadius: 8,
color: HexColor.fromHex('#FF4242'),
horizontalPadding: 25,
),
tabs: model.search_icon_list.map((item) {
return MyTab(
icon: CachedNetworkImage(imageUrl: item?.with_icon_color ?? '', width: 14,),
text: item.name,
);
}).toList(),
),
);
}
}


class SearchTabItemWidget extends StatelessWidget {
final bool isSelect;
final SearchTabItemModel model;

const SearchTabItemWidget(this.isSelect, this.model);

@override
Widget build(BuildContext context) {
return Container();
}
}


+ 19
- 0
lib/widgets/search/widget/color_utils.dart Vedi File

@@ -0,0 +1,19 @@
import 'dart:math';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

/**
* 创建人: Created by zhaolong
* 创建时间:Created by on 2020/6/26.
*
* 可关注公众号:我的大前端生涯 获取最新技术分享
* 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm
* 可关注博客:https://blog.csdn.net/zl18603543572
*/


Color getRandomColor() {
return Color.fromARGB(255, Random.secure().nextInt(200),
Random.secure().nextInt(200), Random.secure().nextInt(200));
}

+ 83
- 0
lib/widgets/search/widget/my_tab.dart Vedi File

@@ -0,0 +1,83 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

const double _kTabHeight = 46.0;
const double _kTextAndIconTabHeight = 40.0;

/// A material design [TabBar] tab.
///
/// If both [icon] and [text] are provided, the text is displayed below
/// the icon.
///
/// See also:
///
/// * [TabBar], which displays a row of tabs.
/// * [TabBarView], which displays a widget for the currently selected tab.
/// * [TabController], which coordinates tab selection between a [TabBar] and a [TabBarView].
/// * <https://material.io/design/components/tabs.html>
class MyTab extends StatelessWidget {
/// Creates a material design [TabBar] tab.
///
/// At least one of [text], [icon], and [child] must be non-null. The [text]
/// and [child] arguments must not be used at the same time.
const MyTab({
Key key,
this.text,
this.icon,
this.child,
}) : assert(text != null || child != null || icon != null),
assert(!(text != null && null != child)),
// TODO(goderbauer): https://github.com/dart-lang/sdk/issues/34180
super(key: key);

/// The text to display as the tab's label.
///
/// Must not be used in combination with [child].
final String text;

/// The widget to be used as the tab's label.
///
/// Usually a [Text] widget, possibly wrapped in a [Semantics] widget.
///
/// Must not be used in combination with [text].
final Widget child;

/// An icon to display as the tab's label.
final Widget icon;

Widget _buildLabelText() {
return child ?? Text(text, softWrap: false, overflow: TextOverflow.fade);
}

@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context));

double height;
Widget label;
if (icon == null) {
height = _kTabHeight;
label = _buildLabelText();
} else if (text == null && child == null) {
height = _kTabHeight;
label = icon;
} else {
height = _kTextAndIconTabHeight;
label = Row(
children: <Widget>[
Container(child: icon, margin: const EdgeInsets.only(right: 5),),
_buildLabelText(),
],
);
}

return SizedBox(
height: height,
child: Center(
child: label,
widthFactor: 1.0,
),
);
}

}

+ 81
- 0
lib/widgets/search/widget/text_tag_widget.dart Vedi File

@@ -0,0 +1,81 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'color_utils.dart';

/**
* 创建人: Created by zhaolong
* 创建时间:Created by on 2020/6/26.
*
* 可关注公众号:我的大前端生涯 获取最新技术分享
* 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm
* 可关注博客:https://blog.csdn.net/zl18603543572
*/
class TextTagWidget extends StatefulWidget {
///显示的文本
String text;
EdgeInsets margin;
EdgeInsets padding;

TextStyle textStyle;

Color backgroundColor;
Color borderColor;

double borderRadius;

TextTagWidget(
this.text, {
this.margin = const EdgeInsets.all(4),
this.padding = const EdgeInsets.only(left: 6, right: 6, top: 3, bottom: 3),
this.textStyle,
this.backgroundColor,
this.borderColor,
this.borderRadius = 20.0,
}) {
if (this.borderColor == null) {
if (this.backgroundColor != null) {
this.borderColor = this.backgroundColor;
} else {
this.borderColor = getRandomColor();
}
}

if (this.textStyle == null) {
Color textColor = this.borderColor;
if (backgroundColor != null) {
textColor = Colors.white;
}
this.textStyle = TextStyle(fontSize: 12, color: textColor);
}

if (this.backgroundColor == null) {
this.backgroundColor = Colors.transparent;
}
}

@override
_TestPageState createState() => _TestPageState();
}

//lib/code/main_data.dart
class _TestPageState extends State<TextTagWidget> {
@override
Widget build(BuildContext context) {
return Container(
margin: widget.margin,
padding: widget.padding,
decoration: BoxDecoration(color: widget.backgroundColor, borderRadius: BorderRadius.all(Radius.circular(widget.borderRadius)), border: Border.all(color: widget.borderColor)),
child: buildTextWidget(),
);
}

///构建文本
Text buildTextWidget() {
return Text(
widget.text,
style: widget.textStyle,
textAlign: TextAlign.center,
);
}
}

+ 56
- 0
lib/widgets/search/widget/title_widget.dart Vedi File

@@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

class SearchTitleWidget extends StatelessWidget {
final String titleText;
final String titleTextColor;
final String iconUrl;
final VoidCallback callback;

const SearchTitleWidget({
this.titleText,
this.titleTextColor,
this.iconUrl,
this.callback,
});

@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
/// 标题
_title(),

/// icon
Visibility(visible: !EmptyUtil.isEmpty(iconUrl), child: _icon()),
],
),
);
}

Widget _title() {
return Text(
titleText,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: HexColor.fromHex(titleTextColor),
),
);
}

Widget _icon() {
return GestureDetector(
onTap: callback,
child: CachedNetworkImage(
imageUrl: iconUrl ?? '',
width: 15,
fit: BoxFit.fill,
),
);
}
}

+ 1
- 0
pubspec.yaml Vedi File

@@ -17,6 +17,7 @@ dependencies:
pull_to_refresh: ^1.6.1
flutter_cupertino_date_picker: ^1.0.26+2
image_picker: ^0.6.7+3
tab_indicator_styler: 1.0.0
image_cropper:
git:
url: 'http://192.168.0.138:3000/FnuoOS_Flutter_Components/Image_Cropper.git'


Caricamento…
Annulla
Salva