Flutter项目之table页面实现
目录:
- 1、首页页面
- index.dart(首页table页面)
- searchbar.dart (搜索页面)
- common_swiper.dart (轮播图)
- index_navigation.dart (导航区域)
- index_navigatorItem_list.dart (数组构造)
- 2、房屋推荐
- index_recommond.dart (房屋推荐区域)
- IndexRecommendItem.dart (构造数据)
- IndexRecommondWidget.dart (点击图片的处理逻辑)
1、首页页面
效果图:
index.dart(首页table页面)
import 'package:flutter/material.dart';
import 'package:flutter_haoke/pages/home/info/index.dart';
import 'package:flutter_haoke/pages/home/tab_index/index_navigation.dart';
import 'package:flutter_haoke/pages/home/tab_index/index_recommond.dart';
import 'package:flutter_haoke/widget/common_swiper.dart';
import 'package:flutter_haoke/widget/search_bar/index.dart';
class TabIndex extends StatelessWidget {
const TabIndex({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: SearchBar(
showLocation: true,
showMap: true,
onSearch: () {
Navigator.of(context).pushNamed("search");
},
),
backgroundColor: Colors.white,
),
body: ListView(
children: [
CommonSwiper(),
IndexNavigation(),
IndexRecommond(),
Info(
showTitle: true,
),
],
),
);
}
}
searchbar.dart (搜索页面)
import 'dart:convert';
import 'package:city_pickers/city_pickers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_haoke/config.dart';
import 'package:flutter_haoke/pages/home/tab_index/index_recommond_item.dart';
import 'package:flutter_haoke/scopoed_model/city.dart';
import 'package:flutter_haoke/utils/common_toast.dart';
import 'package:flutter_haoke/utils/model/general_type.dart';
import 'package:flutter_haoke/utils/scopoed_mode_helper.dart';
import 'package:flutter_haoke/utils/store.dart';
class SearchBar extends StatefulWidget {
final bool? showLocation; //是否显示位置
final void Function()? goBackCallback; //回退
final String? inputValue; //搜索框值
final String? defaultInputValue; //默认显示值
final void Function()? onCancel; //取消按钮
final bool? showMap; //是否显示地图按钮
final void Function()? onSearch; //点击搜索框触发
// final Function? onSearch;
final ValueChanged<String>? onSearchSubmit; //点击按键回车触发
const SearchBar(
{Key? key,
this.showLocation,
this.goBackCallback,
this.inputValue = '',
this.defaultInputValue = '请输入搜索词',
this.onCancel,
this.showMap,
this.onSearch,
this.onSearchSubmit})
: super(key: key);
_SearchBarState createState() => _SearchBarState();
}
class _SearchBarState extends State<SearchBar> {
String _searchWord = '';
late TextEditingController _controller;
late FocusNode _focus;
_onClean() {
_controller.clear();
setState(() {
_searchWord = '';
});
}
_onChangeLocation() async {
//打开第三方的选择页面
var resultCity = await CityPickers.showCitiesSelector(
context: context, theme: ThemeData(primarySwatch: Colors.green));
//选择之后返回选择的数据
String? cityName = resultCity!.cityName;
if (cityName == null) return;
//检测选中的城市是否在 四个城市中
//查找数组中是否有这个名字 有就返回这个城市model 没有就返回空的类
var city = Config.availableCitys
.firstWhere((city) => cityName.startsWith(city.name), orElse: () {
CommontToast.showToast("该城市暂未开通!");
return GeneralType('', "");
});
//保存选中的城市
_saveCity(city);
}
_saveCity(GeneralType city) async {
if (city.name == null ||city.name =="") return;
//保存到全局
ScopoedModelHelper.getModel<CityModel>(context).city = city;
//保存到本地
var store = await Store.getInstance();
//转化成json字符串格式
var cityString = json.encode(city.toJson());
store.setString(StoreKeys.city, cityString);
}
void initState() {
_focus = FocusNode();
_controller = TextEditingController(text: widget.inputValue);
super.initState();
}
Widget build(BuildContext context) {
//从全局里拿到city
var city = ScopoedModelHelper.getModel<CityModel>(context).city;
if (city.name == null || city.name == "") {
city = Config.availableCitys.first;
//存储下此时的city
_saveCity(city);
}
return Container(
child: Row(
children: [
if (widget.showLocation != null)
Padding(
padding: EdgeInsets.only(right: 10),
child: GestureDetector(
onTap: () {
_onChangeLocation();
},
child: Row(
children: [
Icon(
Icons.room,
color: Colors.green,
size: 15,
),
Text(
city.name,
style: TextStyle(color: Colors.black, fontSize: 14),
)
],
),
),
),
if (widget.goBackCallback != null)
Padding(
padding: EdgeInsets.only(right: 10),
child: GestureDetector(
onTap: widget.goBackCallback,
child: Icon(
Icons.chevron_left,
color: Colors.black,
)),
),
Expanded(
child: Container(
height: 34,
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(17)),
margin: EdgeInsets.only(right: 10),
child: TextField(
focusNode: _focus,
controller: _controller,
style: TextStyle(fontSize: 14),
onChanged: (value) {
setState(() {
_searchWord = value;
});
},
onTap: () {
//判断没有使用搜索功能则失去焦点
if (null == widget.onSearchSubmit) {
_focus.unfocus();
}
if(widget.onSearch !=null)widget.onSearch!();
},
onSubmitted: widget.onSearchSubmit,
textInputAction: TextInputAction.search,
decoration: InputDecoration(
hintText: widget.defaultInputValue,
hintStyle: TextStyle(color: Colors.black, fontSize: 14),
contentPadding: EdgeInsets.only(top: 2, left: -10),
border: InputBorder.none,
icon: Padding(
padding: EdgeInsets.only(top: 4, left: 8),
child: Icon(
Icons.search,
size: 18,
color: Colors.grey,
),
),
suffixIcon: GestureDetector(
onTap: _onClean,
child: Icon(
Icons.clear,
size: 18,
color:
_searchWord == '' ? Colors.grey.shade100 : Colors.grey,
),
)),
),
)),
if (widget.onCancel != null)
Padding(
padding: EdgeInsets.only(right: 10),
child: GestureDetector(
onTap: widget.onCancel,
child: Text(
"取消",
style: TextStyle(color: Colors.black, fontSize: 14),
),
),
),
if (widget.showMap != null)
Image.asset("static/icons/widget_search_bar_map.png")
],
));
}
}
common_swiper.dart (轮播图)
import 'package:flutter/material.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
const List<String> defaultImages = [
'http://ww3.sinaimg.cn/large/006y8mN6ly1g6e2tdgve1j30ku0bsn75.jpg',
'http://ww3.sinaimg.cn/large/006y8mN6ly1g6e2whp87sj30ku0bstec.jpg',
'http://ww3.sinaimg.cn/large/006y8mN6ly1g6e2tl1v3bj30ku0bs77z.jpg',
];
// 图片宽高 1200 800
const imageWidth = 1200.0;
const imageHeight = 800;
class CommonSwiper extends StatelessWidget {
final List<String> images;
const CommonSwiper({Key? key, this.images = defaultImages}) : super(key: key);
Widget build(BuildContext context) {
var heigth = MediaQuery.of(context).size.width / imageWidth * imageHeight;
return Container(
height: heigth,
child: Swiper(
itemBuilder: (context, index) {
//Image.network网络图片,前提需开启网络权限
return Image.network(images[index], fit: BoxFit.fill);
},
itemCount: images.length,
autoplay: true,
),
);
}
}
index_navigation.dart (导航区域)
import 'package:flutter/material.dart';
import 'index_navigation_item.dart';
class IndexNavigation extends StatelessWidget {
const IndexNavigation({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Container(
child: Padding(
//EdgeInsets是Flutter中用于定义组件的填充和边距的一个类。它提供了几种便捷的方法来设置组件的填充值,包括:
//EdgeInsets.fromLTRB(double left, double top, double right, double bottom):分别指定四个方向的填充值。
//EdgeInsets.all(double value):所有方向使用相同数值的填充。
//EdgeInsets.only({left, top, right, bottom}):可以设置具体某个方向的填充(可以同时指定多个方向)。
//EdgeInsets.symmetric({vertical, horizontal}):用于设置对称方向的填充,vertical指top和bottom,horizontal指left和right
padding: const EdgeInsets.only(top: 10, bottom: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: indexNavigatorItemList
.map((item) => InkWell(
child: Column(
children: [
Image.asset(item.imageUrl, width: 40),
Text(
item.title,
style: TextStyle(
fontWeight: FontWeight.w500, fontSize: 14.0),
)
],
),
onTap: () {
item.onTap(context);
},
))
.toList(),
),
),
);
}
}
index_navigatorItem_list.dart (数组构造)
import 'package:flutter/material.dart';
//准备数据:title,image
class IndexNavigatorItem {
final String title;
final String imageUrl;
final Function (BuildContext contenxt) onTap;
IndexNavigatorItem(this.title,this.imageUrl,this.onTap);
}
List<IndexNavigatorItem> indexNavigatorItemList=[
IndexNavigatorItem('整租','static/images/home_index_navigator_total.png',(BuildContext context){
Navigator.of(context).pushNamed('login');
}),
IndexNavigatorItem('合租','static/images/home_index_navigator_share.png',(BuildContext context){
Navigator.of(context).pushNamed('login');
}),
IndexNavigatorItem('地图找房','static/images/home_index_navigator_map.png',(BuildContext context){
Navigator.of(context).pushNamed('login');
}),
IndexNavigatorItem('去出租','static/images/home_index_navigator_rent.png',(BuildContext context){
Navigator.of(context).pushNamed('login');
}),
];
2、房屋推荐
index_recommond.dart (房屋推荐区域)
import 'package:flutter/material.dart';
import 'package:flutter_haoke/pages/home/tab_index/index_recommond_data.dart';
import 'package:flutter_haoke/pages/home/tab_index/index_recommond_item.dart';
class IndexRecommond extends StatelessWidget {
final List<IndexRecommendItem> dataList;
const IndexRecommond({Key? key, this.dataList = indexRecommendData})
: super(key: key);
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(color: Color(0x08000000)),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"房屋推荐",
style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500),
),
Text("更多")
],
),
Padding(padding: EdgeInsets.all(10)),
Wrap(
spacing: 10,
runSpacing: 10,
children: dataList.map((item) {
return IndexRecommondWidget(item);
}).toList(),
)
],
),
);
}
}
IndexRecommendItem.dart (构造数据)
class IndexRecommendItem{
final String title;
final String subTitle;
final String imageUrl;
final String navigateUrl;
const IndexRecommendItem(this.title,this.subTitle,this.imageUrl,this.navigateUrl);
}
const List<IndexRecommendItem> indexRecommendData=[
const IndexRecommendItem(
'家住回龙观','归属的感觉', 'static/images/home_index_recommend_1.png', 'login'),
const IndexRecommendItem(
'宜居四五环', '大都市生活','static/images/home_index_recommend_2.png', 'login'),
const IndexRecommendItem(
'喧嚣三里屯', '繁华的背后','static/images/home_index_recommend_3.png', 'login'),
const IndexRecommendItem(
'比邻十号线','地铁心连心', 'static/images/home_index_recommend_4.png', 'login'),
];
IndexRecommondWidget.dart (点击图片的处理逻辑)
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_haoke/pages/home/tab_index/index_recommond_data.dart';
var textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.w600);
class IndexRecommondWidget extends StatelessWidget {
final IndexRecommendItem data;
const IndexRecommondWidget(
this.data, {
Key? key,
}) : super(key: key);
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).pushNamed(data.navigateUrl);
},
child: Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(color: Colors.white),
width: (MediaQuery.of(context).size.width - 10 * 3) / 2,
height: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Text(
data.title,
style: textStyle,
),
Text(
data.subTitle,
style: textStyle,
)
]),
// Image.asset展示的本地图片
Image.asset(
data.imageUrl,
width: 40,
)
],
),
),
);
}
}