前言:
各位同学大家好,很长一段时间没有给大家更新文章了,之前发了一个Android 仿QQ登录下拉历史列表 (因为工作需要就发一篇安卓的 算是基础的常用功能实现吧)现在想着做一个
flutter的效果出来,今天才把代码撸好,就分享给大家 如果有什么错误或者纰漏 希望大家指正,那么废话不说 我们正式开始
效果图:



准备工作:
需要安装flutter的开发环境:大家可以去看看之前的教程:
1 win系统flutter开发环境安装教程: https://www.jianshu.com/p/152447bc8718
2 mac系统flutter开发环境安装教程:https://www.jianshu.com/p/bad2c35b41e3
需要用到三方库:
shared_preferences: "^0.4.2"
请大家在yaml 文件中添加依赖并且执行flutter pub  get 下载依赖
如图:

我们的需求和明确,就是要把登录成功的账号密码缓存保存好,然后并且显示到历史信息列表里面让用户可以自由切换已经登录过的账号。
具体实现:

登录页面实现
Container(
        margin: EdgeInsets.fromLTRB(20, 100, 20, 0),
        child: Column(
          children: <Widget>[
          TextField(
            controller: controller1,
          obscureText: false,
          decoration: InputDecoration(
            hintText: "请输入账号",
            border: InputBorder.none,
          ),
          onChanged: (value){
            setState(() {
              this._username=value;
            });
          },
          ),
            new Divider(
              height: 2.0,
              color: Colors.black54,
            ),
            TextField(
              controller: controller2,
              obscureText: false,
              decoration: InputDecoration(
                hintText: "请输入密码",
                border: InputBorder.none,
              ),
              onChanged: (value){
                setState(() {
                  this._password=value;
                });
              },
            ),
            new Divider(
              height: 2.0,
              color: Colors.black54,
            ),
            new Padding(padding: EdgeInsets.only(top: 20),
                child: Container(
                  width: double.infinity,
                  height: 40,
                  child: RaisedButton(
                    color: Colors.green,
                    textColor: Colors.white,
                    child: Text("登录"),
                    onPressed: ()async{
                    User user=new User();
                    user.username=_username;
                    user.password=_password;
                    datalsit.add(user);
                    String jsonStringA = jsonEncode(datalsit);
                    print("jsonStringA   --------- >"+ jsonStringA);
                    SharedPreferences prefs = await SharedPreferences.getInstance();
                    prefs.setString("data",jsonStringA);
                    },
                  ),
                )
            ),
            new Padding(padding: EdgeInsets.only(top: 20),
                child: Container(
                  width: double.infinity,
                  height: 40,
                  child: RaisedButton(
                    color: Colors.green,
                    textColor: Colors.white,
                    child: Text("查看登录历史账号信息"),
                    onPressed: ()async{
                      SharedPreferences prefs = await SharedPreferences.getInstance();
                      getdata = await prefs.getString("data");
                      print("getdata  ---  >"+getdata.toString());
                      showCustomDialog(context,getdata).then((value){
                        List  list= json.decode(getdata);
                        setState(() {
                          getusername=list[value]["username"];
                          getpassword=list[value]["password"];
                          controller1.text=getusername;
                          controller2.text=getpassword;
                        });
                        print(list[value]["username"]);
                        print(list[value]["password"]);
                      });
                    },
                  ),
                )
            )
          ],
        ),
      ),
登录页面我们写了两个TextField和输入框和两个 RaisedButton 按钮的简单的布局当我们点击登录按钮的时候我们拿到账号和密码 通过SharedPreferences  存起来。
我们查阅了SharedPreferences 官方文档使用  SharedPreferences 只能支持基本数据类型和 string的集合所以不能满足我们的需求,我这边改变思路写了一个数据模型类:
class  User{
   String  username;
   String  password;
   User ({this.username,this.password});
   factory User .fromJson(Map<String,dynamic> json) {
     return User (
       username: json['username'],
       password: json['password'],
     );
   }
   Map toJson() {
     Map map = new Map();
     map["username"] = this.username;
     map["password"] = this.password;
     return map;
   }
}
在每次点击登录的时候我们 实例化User对象传 设置值username password 属性为我们输入框拿到的值
  User user=new User();
  user.username=_username;
  user.password=_password;
  datalsit.add(user);
因为SharedPreferences 是不支持存储 List<User>datalsit=new List();这种数据格式 所以我们需要把datalist 转换成json字符串再存储 这里我们需要用到dart里面自带的 jsonEncode 需要引入dart:convert
import 'dart:convert';
数据存储逻辑:
 String jsonStringA = jsonEncode(datalsit);
 print("jsonStringA   --------- >"+ jsonStringA);
 SharedPreferences prefs = await SharedPreferences.getInstance();
 prefs.setString("data",jsonStringA);
这样我们就能把每次登录的数据通过user实例化然后设置属性 添加到datalist集合里面转成json字符串并且通过缓存存储起来了
历史账号弹窗的实现:
import 'package:flutter/material.dart';
import 'dart:convert';
/***
 *
 *创建人:xuqing
 * 类说明:账号历史记录弹窗
 * 创建时间:2020-9-5
 *
 *
 */
class   RecordDialog extends Dialog{
  String jsondata;
  RecordDialog({Key key, @required this.jsondata}) : super(key: key);
  List  list;
     @override
  Widget build(BuildContext context) {
     list= json.decode(jsondata);
    // TODO: implement build
       return new Material(
         //创建透明层
        type: MaterialType.transparency, //透明类型
         child: new Center(
           //保证控件居中效果
           child: new SizedBox(
             width: 300.0,
             height: 200.0,
             child: new Container(
               color: Colors.white,
             child: ListView.builder(
                 itemCount:list.length==0?0:list.length,
                 itemBuilder: (BuildContext context, int  position){
                  return itemWidget(context,position);
                 }),
             ),
           ),
         ),
       );
  }
   Widget itemWidget(BuildContext context,int  index){
       return GestureDetector(
         child: Container(
           height: 40,
           width: double.infinity,
          child: Center(
            child:  Text("账号:"+list[index]["username"]),
          )
         onTap: (){
           Navigator.pop(context,index);
         },
       );
   }
}
在RecordDialog  定义了jsondata  也就换存的数据需要外部调用的时候需要需要外部传入
然后在布局的地方我们通过Material中的     type: MaterialType.transparency, //透明类型 实现了透明的效果
然后在Material  嵌套有个Center  组件来使得我们弹窗居中显示 然后嵌套一个  Container组件设置宽高 200 300 在Container 中嵌套listview 展示我们的缓存的账号的列表
缓存数据的获取
我们调用 SharedPreferences 中的 prefs.getString("data") 方法来获取数据
 SharedPreferences prefs = await SharedPreferences.getInstance();
 getdata = await prefs.getString("data");
 print("getdata  ---  >"+getdata.toString());
我们在控制台中捕捉到打印出的数据是含有了列表的json数据
[{
    "username": "xq9527",
    "password": "xq123456"
}, {
    "username": "wx1991",
    "password": "wx123456"
}, {
    "username": "zb1999",
    "password": "zb9377"
}]
我们在RecordDialog 中拿到缓存的数据 我们需要通过调用 json.decode(需要引入dart:convert包) 来把json还原成list
List  list= json.decode(jsondata);
然后我们在RecordDialog  中listview 里面的item里面调用   list[index]["username"] ;来展示
用户点击listview
 onTap: (){
           Navigator.pop(context,index); //通过调用    Navigator.pop 关闭RecordDialog  并且将点击的下标回调回去 
         },
RecordDialog 具体调用显示
  //  RecordDialog  具体调用
  Future  showCustomDialog(BuildContext context,String getdata )async {
    var  result=await showDialog(
        context: context,
        builder: (BuildContext context) {
          return RecordDialog(jsondata: getdata,);
        });
    return result;
  }
这里我们 return 返回的result 就是用户点击 RecordDialog 列表的item的下标我们可以通过这个下标来获取用户是点击的拿一条数据
  showCustomDialog(context,getdata).then((value){
    List  list= json.decode(getdata);
      setState(() {
           getusername=list[value]["username"];
            getpassword=list[value]["password"];
              controller1.text=getusername;
             controller2.text=getpassword;
               });
         print(list[value]["username"]);
         print(list[value]["password"]);
 });
我们拿到数据后台需要调用 TextField  中的 controller属性来将获取到的getusername  getpassword 赋值给
controller.text
  TextEditingController controller1 = TextEditingController();
  TextEditingController controller2 = TextEditingController();
   getusername=list[value]["username"];
   getpassword=list[value]["password"];
   controller1.text=getusername;
    controller2.text=getpassword;
这样我们就把用户点击  RecordDialog 列表 中的账号密码填充到 账号和密码的   TextField 输入框中
到此 Flutter  仿QQ登录下拉历史列表案例 功能实现我们就讲完了 主要关键点是数据的存储 UI实现相对简单
最后总结:
我是一名Android 游戏SDK开发的人程序员 ,因为最近用到这个仿QQ下拉历史列表的功能(之前很在就实现过)之前写过一个Android 原生的  这个仿QQ下拉历史列表的功能 ,今天就实现一个flutter版本的分享给各位
如果觉得文章还不错麻烦给个star 和转发谢谢