APP 导航框架与常用功能实现
APP 首页框架搭建
首先,先新建这些文件:
tab_navigator.dart 文件代码如下:
import 'package:flutter/material.dart';
import 'package:xiecheng/pages/home_page.dart';
import 'package:xiecheng/pages/my_page.dart';
import 'package:xiecheng/pages/search_page.dart';
import 'package:xiecheng/pages/travel_page.dart';
class TabNavigator extends StatefulWidget {
@override
_TabNavigatorState createState() => _TabNavigatorState();
}
class _TabNavigatorState extends State<TabNavigator> {
final _defaultColor = Colors.grey;
final _activeColor = Colors.blue;
int _currentIndex = 0;
final PageController _controller = PageController(
initialPage: 0,
);
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
controller: _controller,
children: [
HomePage(),
MyPage(),
SearchPage(),
TravelPage(),
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
_controller.jumpToPage(index);
setState(() {
_currentIndex = index;
});
},
type: BottomNavigationBarType.fixed, //把lable进行固定
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
color: _defaultColor,
),
activeIcon: Icon(
Icons.home,
color: _activeColor,
),
title: Text(
'首页',
style: TextStyle(
color: _currentIndex != 0 ? _defaultColor : _activeColor,
),
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.search,
color: _defaultColor,
),
activeIcon: Icon(
Icons.search,
color: _activeColor,
),
title: Text(
'搜索',
style: TextStyle(
color: _currentIndex != 1 ? _defaultColor : _activeColor,
),
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.camera_alt,
color: _defaultColor,
),
activeIcon: Icon(
Icons.camera_alt,
color: _activeColor,
),
title: Text(
'旅拍',
style: TextStyle(
color: _currentIndex != 2 ? _defaultColor : _activeColor,
),
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.account_circle,
color: _defaultColor,
),
activeIcon: Icon(
Icons.account_circle,
color: _activeColor,
),
title: Text(
'我的',
style: TextStyle(
color: _currentIndex != 3 ? _defaultColor : _activeColor,
),
),
),
],
),
);
}
}
home_page.dart 文件代码如下:
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('首页'),
),
);
}
}
my_page.dart 文件代码如下:
import 'package:flutter/material.dart';
class MyPage extends StatefulWidget {
@override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('我的'),
),
);
}
}
search_page.dart 文件代码如下:
import 'package:flutter/material.dart';
class SearchPage extends StatefulWidget {
@override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('搜索'),
),
);
}
}
travel_page.dart 文件代码如下:
import 'package:flutter/material.dart';
class TravelPage extends StatefulWidget {
@override
TravelPageState createState() => TravelPageState();
}
class TravelPageState extends State<TravelPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('旅拍'),
),
);
}
}
最后将 main.dart 的代码进行微小的修改:
就可以运行啦:
轮播图 Banner 功能开发
轮播图需要用到的 swiper 插件,我们可以去 pub 网站上去找:
打开 pub 网站,搜索 swiper 即可:
这时候我们查看该插件的 Installing,里面会告诉你如何引入该插件:
这时候我们按照它说的步骤做就好啦:
引入后 VSCode 的右上角会出现一个下载的标志,点击下载即可;
然后编辑 home_page.dart 里的代码:
import 'package:flutter/material.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List _imageUrls = [
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1976529436,2778459069&fm=26&gp=0.jpg',
'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3597917999,2966077325&fm=26&gp=0.jpg',
'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3352739916,685169444&fm=26&gp=0.jpg',
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Container(
height: 160,
child: Swiper(
itemCount: _imageUrls.length,
autoplay: true,
itemBuilder: (BuildContext context, int index) {
return Image.network(
_imageUrls[index],
fit: BoxFit.fill,
);
},
pagination: SwiperPagination(),
),
),
],
),
),
);
}
}
运行界面如下:
自定义 AppBar 实现滚动渐变
修改 home_page.dart 的代码,如下:
import 'package:flutter/material.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
const APPBAR_SCROLL_OFFSET = 100; //设置滚动最大距离
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List _imageUrls = [
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1976529436,2778459069&fm=26&gp=0.jpg',
'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3597917999,2966077325&fm=26&gp=0.jpg',
'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3352739916,685169444&fm=26&gp=0.jpg',
];
double appBarAlpha = 0.0;
_onScroll(offset) {
double alpha = offset / APPBAR_SCROLL_OFFSET;
if (alpha < 0.0) {
alpha = 0.0;
} else if (alpha > 1.0) {
alpha = 1.0;
}
setState(() {
appBarAlpha = alpha;
});
// print(appBarAlpha);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
MediaQuery.removePadding(
//把顶部预留的安全区域去掉
removeTop: true,
context: context,
child: NotificationListener(
//监听列表的滚动
onNotification: (scrollNotification) {
if (scrollNotification is ScrollUpdateNotification &&
scrollNotification.depth == 0) {
//滚动且是列表滚动的时候
_onScroll(scrollNotification.metrics.pixels);
}
},
child: ListView(
children: [
Container(
height: 160,
child: Swiper(
itemCount: _imageUrls.length,
autoplay: true,
itemBuilder: (BuildContext context, int index) {
return Image.network(
_imageUrls[index],
fit: BoxFit.fill,
);
},
pagination: SwiperPagination(),
),
),
Container(
height: 800,
child: ListTile(
title: Text('阿巴阿巴阿巴'),
),
),
],
),
),
),
Opacity(
//自定义AppBar
opacity: appBarAlpha,
child: Container(
height: 80,
decoration: BoxDecoration(color: Colors.white),
child: Center(
child: Padding(
padding: EdgeInsets.only(top: 20),
child: Text('首页'),
),
),
),
)
],
),
);
}
}
运行界面:
网络编程与数据存储技术相关经验和技巧
基于Http实现网络操作
如何用 http 库做 get 请求?
- 在
pubspec.yaml
中引入http
插件; - 调用 http.get 发送请求;
Future<http.Response> fetchPost() {
return http.get('https://jsonplaceholder.typicode.com/posts/1');
}
http.get()
返回一个包含 http.Response
的 Future
:
- Future:是与异步操作一起工作的核心 Dart 类。它用于表示未来某个时间可能会出现的可用值或错误;
http.Response
:类包括一个成功的 HTTP 请求接收到的数据;
如何用 http 库做 post 请求?
- 在
pubspec.yaml
中引入 http 插件; - 调用
http.post
发送请求;
Future<http.Response> fetchPost() {
return http.post('https://jsonplaceholder.typicode.com/posts/1');
}
http.post()
返回一个包含 http.Response
的 Future
:
- Future:是与异步操作一起工作的核心 Dart 类。它用于表示未来某个时间可能会出现的可用值或错误;
http.Response
:类包括一个成功的 HTTP 请求接收到的数据;
如何将 Response 转换成 Dart object?
虽然发出网络请求很简单,但如果要使用原始的 Future<http. Response>
并不简单。为了让我们可以开开心心的写代码,我们可以将 http.Response
转换成我们自己的 Dart 对象。
创建一个 CommonModel 类
首先,我们需要创建一个 CommonModel 类,它包含我们网络请求的数据。它还将包括一个工厂构造函数,它允许我们可以通过 json 创建个 CommonModel 对象。
将 http.Response 转换成一个 CommonModel 对象
如何将请求结果展示在界面上?
异步:Future 与 FutureBuilder 实用技巧
什么是 Future?
Future 的常见用法?
使用 future.then 获取 future 的值与捕获 future 的异常
结合 async await
future.whenComplete
future.timeout
什么是 FutureBuilder?
FutureBuilder
是一个将异步操作和异步 UI 更新结合在一起的类,通过它我们可以将网络请求,数据库读取等的结果更新的页面上。
FutureBuilder 的构造方法
FutureBuilder({Key key, Future<T> future, T initialData, @required AsyncWidgetBuilder<T> builder})
FutureBuilder 的使用?
JSON 解析与复杂模型转换实用技巧
应该是有哪种 JSON 序列化方式?
如何序列化?
复杂 JSON 解析?
如何解析对象中的数组?
解析:
提示效率:在线转换 JSON TO Dart
基于 shared_preferences 本地存储操作
什么是 shared_preferences?
如何使用 shared_preferences?
shared_preferences 有哪些常用的 API?
存储相关
读取相关
基于 shared_preferences 实现计数器 Demo