一、provider状态管理设置主题颜色
第一步:
安装依赖库
provider: ^4.3.2+3
第二步:
创建共享数据模型
import 'package:flutter/material.dart';
import 'package:privider_test/base/baseThemes.dart';
class ThemesViewmodel extends ChangeNotifier {
int _index = 0;
int get getColor {
return _index;
}
void SetColor(int value) {
if (value > themes.length - 1) return;
_index = value;
notifyListeners();
}
}
在main函数中引入共享模型
第三步:
创建base颜色数组
import 'package:flutter/material.dart';
List themes = [
Colors.green,
Colors.yellow,
Colors.purple,
Colors.orange,
Colors.cyan,
Colors.blue,
];
在主题中使用provider状态管理,由于想让颜色的值发生改变这里我们使用statefulWidget
mian.dart
import 'package:flutter/material.dart';
import 'package:privider_test/page/UserLoginpage.dart';
import 'package:provider/provider.dart';
import 'ViewModel/ThemesViewmodel.dart';
import 'base/baseThemes.dart';
void main() {
runApp(MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => ThemesViewmodel(),
)
],
child: MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({Key key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: UserLoginpage(),
theme: ThemeData(
primarySwatch:
themes[Provider.of<ThemesViewmodel>(context).getColor]), //变换主题颜色
);
}
}
第四步:
画出ui,并添加点击事件
import 'package:flutter/material.dart';
import 'package:privider_test/ViewModel/ThemesViewmodel.dart';
import 'package:privider_test/base/baseThemes.dart';
import 'package:provider/provider.dart';
class UserLoginpage extends StatefulWidget {
const UserLoginpage({ Key key }) : super(key: key);
@override
_UserLoginpageState createState() => _UserLoginpageState();
}
class _UserLoginpageState extends State<UserLoginpage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("登录界面"),
),
body: Padding(
padding: EdgeInsets.all(10),
child: Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: themes.length,
itemBuilder: _itemBuilder,//如果加()就是执行这个方法,不加就是将这个返回
),
),
)
);
}
Widget _itemBuilder(BuildContext context,int index){
return GestureDetector(
onTap: ()async{
(context).read<ThemesViewmodel>().SetColor(index);
},
child: Container(
margin: EdgeInsets.symmetric(vertical: 8),
height: 50,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: themes[index]
),
),
);
}
}
二、flutter登录功能的实现
第一步:创建目录文件夹
第二步:
配置yaml文件依赖
provider: ^4.3.2+3
dio: ^4.0.0
tdui: 0.0.3
encrypt: ^5.0.1
# 提示框
flutter_easyloading: ^3.0.0
编写global.dart
import 'package:dio/dio.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
class Global {
static Global _instance;
Dio dio;
String token;
Map user;
static Global getInstance() {
if (_instance == null) _instance = new Global();
return _instance;
}
Global() {
dio = new Dio();
dio.options = BaseOptions(
baseUrl: "https://zxw.td0f7.cn/",
// baseUrl: "http://localhost:8080/",
connectTimeout: 5000,
sendTimeout: 5000,
receiveTimeout: 5000,
contentType: Headers.formUrlEncodedContentType,
responseType: ResponseType.json,
);
dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
EasyLoading.show(status: "Loading...");
return handler.next(options); //continue
},
onResponse: (response, handler) {
EasyLoading.dismiss();
return handler.next(response); // continue
},
onError: (DioError e, handler) {
print(e.toString());
EasyLoading.dismiss();
String msg = "";
if (e.type == DioErrorType.connectTimeout) {
msg = "连接超时错误";
} else {
msg = "接口错误!";
}
EasyLoading.showError(msg);
},
));
}
}
main.dart
import 'package:flutter/material.dart';
import 'package:myitem/router/route_handler.dart';
import 'package:myitem/view/UserLogin.dart';
import 'package:myitem/viewmodel/login_viewmodel.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => LoginViewmodel(),
)
],
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const UserLogin(),
onGenerateRoute: AppRouteManager.getInstance().onGenerateRoute,
debugShowCheckedModeBanner: false, //去掉默认标签
);
}
}
loginmodel.dart
//登录数据模型
import 'package:myitem/global/Global.dart';
import 'package:myitem/util/rsa_utils.dart';
Future loginModel(String user, String pass) async {//将登录的账号和密码传入
String pwd = await encodeString(pass);//使用rsa进行加密
return await Global.getInstance().dio.post("/zxw/user",queryParameters: {
"username":user,"password":pwd
});//调用实例对象后的dio接口dio接口采用接口文档中对应的接口方式get/post提交数据,文档中
//有固定传入参数两个主键请求的结果异步返回给viewmodel
}
/* view层调用viewmodel,viewmodel通知model层,model再
发送请求返回给viewmodel,viewmodel处理返回结果并刷新view*/
登录界面
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:myitem/base/view.dart';
import 'package:myitem/util/rsa_utils.dart';
import 'package:myitem/viewmodel/login_viewmodel.dart';
import 'package:tdui/tdui.dart';
import 'package:provider/provider.dart';
class UserLogin extends StatefulWidget {
const UserLogin({Key key}) : super(key: key);
@override
_UserLoginState createState() => _UserLoginState();
}
class _UserLoginState extends State<UserLogin> {
@override
void initState() {
super.initState();
}
// void loadData()async{
// var result = await encodeString("1");
// print(result);
// }
@override
void dispose() {
super.dispose();//节省资源
context.read<LoginViewmodel>().getPwd.dispose();
context.read<LoginViewmodel>().getUser.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: getAppBar("登录"),
body: Padding(
padding: EdgeInsets.all(20),
child: Column(
children: [
// Image.asset(
// "images/login.jpg",
// width: double.infinity,
// fit: BoxFit.fill,
// ),
SizedBox(
height: 16,
),
TextField(
decoration: InputDecoration(
labelText: "账号",
hintText: "请输入账号",
prefix: Icon(Icons.person),
),
autofocus: true,
textInputAction: TextInputAction.next,
controller: Provider.of<LoginViewmodel>(context).getUser,
),
TextField(
controller: Provider.of<LoginViewmodel>(context).getPwd,
decoration: InputDecoration(
labelText: "密码", hintText: "请输入密码", prefix: Icon(Icons.lock)),
obscureText: true,
textInputAction: TextInputAction.send,
),
SizedBox(
height: 16,
),
GestureDetector(
child: Container(
width: double.infinity,
child: Text(
"找回密码",
style: TextStyle(color: Colors.blue),
textAlign: TextAlign.right,
),
),
onTap: () {
print("找回密码");
},
),
SizedBox(
height: 16,
),
TdButton(
'登录',
theme: TdButtonType.primary,
loading: Provider.of<LoginViewmodel>(context).getIsLogin,
onClick: () {
_login();
// loadData();
},
),
SizedBox(
height: 16,
),
TdButton(
'注册',
theme: TdButtonType.primary,
onClick: () {
_register();
},
)
],
),
),
);
}
void _login() {
// context.read().setIsLogin(true);
// new Timer(Duration(seconds: 3), () {
// context.read().setIsLogin(false);
// Navigator.of(context).pushNamed("/MenuPage");
// });
context.read<LoginViewmodel>().login(context);
}
void _register() {
// context.read().setIsLogin(false);
Navigator.of(context).pushNamed("/RegisterPage");
}
}
/* view层调用viewmodel,viewmodel通知model层,model再
发送请求返回给viewmodel,viewmodel处理返回结果并刷新view*/
login_viewmodel
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:myitem/model/login_model.dart';
import 'package:tdui/tdui.dart';
//创建登录状态管理
class LoginViewmodel extends ChangeNotifier {
bool _isLogin = false;
TextEditingController _userName; //创建controller进行全局状态管理
TextEditingController _password;
bool get getIsLogin {
//返回
return _isLogin;
}
TextEditingController get getUser {
_userName ??= TextEditingController();
//返回
return _userName;
}
TextEditingController get getPwd {
_password ??= TextEditingController(); //如果没有创建那么进行实例化
//返回
return _password;
}
// ignore: avoid_return_types_on_setters
void setIsLogin(bool value) {
_isLogin = value;
notifyListeners();
}
void login(BuildContext context) async {
setIsLogin(true); //先设置为true
if (getUser.text.isEmpty) {
//判断账号是否为空
TdToast.fail(context)(message: "账号不能为空");
setIsLogin(false); //如果为空那么就返回false
return;
} else if (getPwd.text.isEmpty) {
//如果密码为空,那么返回false
TdToast.fail(context)(message: "密码不能为空");
setIsLogin(false);
return;
}
//如果账号密码都不是空那么,用response接收账号和密码从viewmodel传值到数据模型
Response result = await loginModel(getUser.text, getPwd.text);
if (result.data["success"]) {
Navigator.of(context).popAndPushNamed("/MenuPage");
} else {
TdDialog.alert(context)(result.data["msg"],
theme: TdDialogTheme.android);
}
setIsLogin(false);
}
}
theme: ThemeData(primarySwatch: Colors.yellow),//变换主题颜色
实现开关功能
TdCell(
label: "出生日期",
align: Alignment.center,
content: Provider.of<RegisterViewModel>(context).getDateTime,
footer: Row(
children: [
TdSwitch(
checked:
Provider.of<RegisterViewModel>(context).getSolar == 0
? false
: true,
onChange: (v) {
setState(() {
(context).read<RegisterViewModel>().SetSolar(v ? 1 : 0);
});
},
),
SizedBox(
width: 8,
),
Text(Provider.of