Flutter 仿QQ登录下拉历史列表案例

前言:

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

效果图:

QQ20200906-141737.png

QQ20200906-141839.png

QQ20200906-141907.png

准备工作:

需要安装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 下载依赖

如图:

QQ20200906-143825.png

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

具体实现:

QQ20200906-141737.png

登录页面实现

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 和转发谢谢

项目地址:

码云:https://gitee.com/qiuyu123/flutter_loginhistory.git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355