2021-第一个手写Flutter 页面

本文介绍了一个使用Flutter实现的设置页面案例,该页面包括三个栏目,并实现了动态版本检查、更新提示弹窗等功能。文章详细展示了如何构建异步网络请求、加载列表、创建列表组件及更新对话框。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求:写一个设置页面 包含三个栏目,栏目1,栏目2,栏目三更新提示

关键词:FutureBuilder  showDialog AlertDialog  SharedPreferences 

一、技术细节:

001 网络请求版本号

002 动态显示更新标识

003 点击版本栏目弹窗显示更新内容

004 点击其他栏目跳转到其他页面

二、技术实现点:

001 构建异步网络请求

var _futureBuilderFuter;

void initState() {

var context = this.context;

_futureBuilderFuter = _getUpdate();

}

002 网络请求结束后加载列表

FutureBuilder(

future: _futureBuilderFuter,

builder: (BuildContext context, AsyncSnapshot snapshot) {

if (snapshot.connectionState == ConnectionState.done) {

UpdateModel resultModel = snapshot.data;

}

003 列表组件展示

ListView.builder(

padding: EdgeInsets.all(0),

itemCount: _titles.length,

itemBuilder: (BuildContext context, int index) {

return _listTitleNormal(

context,

index,

_icons[index],

_titles[index],

version,

resultModel.data.lastBuild.toString(),

showSubTitle: index == 2 ? true : false);

}),

004 更新会话弹窗

Future<bool> _onWillPop() {
    return showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: Text('有新版本'),
            content: Text(updateModel.data.content.toString()),
            actions: <Widget>[
              FlatButton(
                  onPressed: () {
                    Navigator.of(context).pop(true);
                  },
                  child: Text(
                    '残忍拒绝',
                    style: TextStyle(color: Theme.of(context).disabledColor),
                  )),
              FlatButton(
                  onPressed: () {
                    Navigator.of(context).pop(false);
                    String url = updateModel.data.iosUrl;
                    // _navigateTo(context, url, '');
                    launch(url);
                  },
                  child: Text('去更新'))
            ],
          ),
        ) ??
        false;
  }

 三、完整代码和显示场景

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:qianduoduo/models/update_model.dart';
import 'package:qianduoduo/service/http_manager.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:qianduoduo/config/service_url.dart';
import 'package:package_info/package_info.dart';
import 'package:qianduoduo/utils/platform_utils.dart';
import 'package:qianduoduo/router/fluro_convert_utils.dart';
import 'package:qianduoduo/router/application.dart';
import 'package:qianduoduo/router/routers.dart';
import 'package:fluro/fluro.dart';
import 'package:qianduoduo/provider/login_page_provider.dart';
import 'package:qianduoduo/provider/store.dart';
import 'package:umeng_analytics_push/umeng_analytics_push.dart';
import 'package:url_launcher/url_launcher.dart';

class MySettingPage extends StatefulWidget {
  MySettingPage({Key key}) : super(key: key);

  @override
  _MySettingPageState createState() => _MySettingPageState();
}

class _MySettingPageState extends State<MySettingPage> {
  var _futureBuilderFuter;
  List<String> _titles = ['1', '2', '版本信息'];
  var version;
  UpdateModel updateModelTmp;
  @override
  void initState() {
    var context = this.context;
    _futureBuilderFuter = _getUpdate();
    _getUpdate().then((value) {
      updateModel = value;
    });
    //  PackageInfo _packageInfo;
    PlatformUtils.getAppPackageInfo().then((value) {
      // _packageInfo = value;
      version = value.version;
    });
    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    List<Image> _icons = [
      Image.asset(
        'images/my/fuwuxieyi.png',
        width: 24,
        height: 24,
        color: Theme.of(context).primaryColor,
      ),
      Image.asset(
        'images/my/gongyue.png',
        width: 24,
        height: 24,
        color: Theme.of(context).primaryColor,
      ),
      Image.asset(
        'images/my/version.png',
        width: 24,
        height: 24,
        color: Theme.of(context).primaryColor,
      ),
    ];
    return Container(
      child: Scaffold(
        appBar: PreferredSize(
          preferredSize: Size(ScreenUtil().setWidth(750), 44),
          child: Container(
            child: AppBar(
              backgroundColor: Colors.transparent,
              elevation: 0.0,
              title: Text(
                '设置',
                style: TextStyle(color: Colors.white),
              ),
              automaticallyImplyLeading: false,
              leading: IconButton(
                color: Colors.white,
                icon: Icon(Icons.arrow_back),
                onPressed: () {
                  Navigator.pop(context);
                },
              ),
            ),
            decoration: BoxDecoration(
              gradient: LinearGradient(
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
                colors: [
                  Theme.of(context).primaryColor,
                  Theme.of(context).accentColor
                ],
              ),
            ),
          ),
        ),
        body: FutureBuilder(
          future: _futureBuilderFuter,
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              UpdateModel resultModel = snapshot.data;
                 updateModelTmp =  resultModel;
              return Container(
                  width: ScreenUtil().setWidth(750),
                  height: ScreenUtil().setHeight(1330),
                  color: Theme.of(context).scaffoldBackgroundColor,
                  child: Stack(
                    children: <Widget>[
                      ListView.builder(
                          padding: EdgeInsets.all(0),
                          itemCount: _titles.length,
                          itemBuilder: (BuildContext context, int index) {
                            return _listTitleNormal(
                                context,
                                index,
                                _icons[index],
                                _titles[index],
                                version,
                                resultModel.data.lastBuild.toString(),
                                showSubTitle: index == 2 ? true : false);
                          }),
                      Container(
                        height: ScreenUtil().setHeight(70),
                        margin: EdgeInsets.only(
                            left: 30,
                            right: 30,
                            top: ScreenUtil().setHeight(700)),
                        decoration: BoxDecoration(
                          gradient: LinearGradient(
                            begin: Alignment.topLeft,
                            end: Alignment.bottomRight,
                            colors: [
                              Theme.of(context).primaryColor,
                              Theme.of(context).accentColor
                            ],
                          ),
                          borderRadius: BorderRadius.circular(35),
                        ),
                        child: FlatButton(
                            minWidth: ScreenUtil().setWidth(600),
                            height: ScreenUtil().setHeight(100),
                            onPressed: () {
                              showDialog(
                                  context: context,
                                  barrierDismissible: false,
                                  builder: (BuildContext context) {
                                    return CupertinoAlertDialog(
                                      title: new Text(''),
                                      content: new Text(
                                        '确定退出?',
                                        style: Theme.of(context)
                                            .textTheme
                                            .bodyText2,
                                      ),
                                      actions: <Widget>[
                                        CupertinoDialogAction(
                                          child: Text(
                                            '取消',
                                            style: Theme.of(context)
                                                .textTheme
                                                .bodyText2,
                                          ),
                                          onPressed: () {
                                            Navigator.of(context).pop();
                                          },
                                        ),
                                        CupertinoDialogAction(
                                          child: Text(
                                            '退出',
                                            style: TextStyle(
                                                color: Theme.of(context)
                                                    .primaryColor),
                                          ),
                                          onPressed: () {
                                           
                                          },
                                        ),
                                      ],
                                    );
                                  });
                            },
                            child: Text('退出登录',
                                style: TextStyle(color: Colors.white))),
                      )
                    ],
                  ));
            } else {
              return Container();
            }
          },
        ),
      ),
    );
  }

  //

  Widget _listTitleNormal(BuildContext context, int index, Image image,
      String title, String version, String lastBuild,
      {bool showSubTitle}) {
    return Container(
      padding: EdgeInsets.only(left: 8, right: 8),
      height: ScreenUtil().setHeight(110),
      alignment: Alignment.center,
      child: Container(
        color: Theme.of(context).cardColor,
        child: Column(
          children: <Widget>[
            Expanded(
                flex: 1,
                child: ListTile(
                  title: Container(
                    child: Row(
                      children: <Widget>[
                        Container(
                          width: ScreenUtil().setWidth(50),
                          child: image,
                        ),
                        Container(
                          padding: EdgeInsets.only(left: 12),
                          child: Text(
                            title,
                            style: TextStyle(
                                color: Theme.of(context)
                                    .textTheme
                                    .bodyText2
                                    .color),
                            textAlign: TextAlign.left,
                          ),
                        ),
                      ],
                    ),
                  ),
                  trailing: Container(
                    alignment: Alignment.centerRight,
                    width: index == 2 ? 150 : 80,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.end,
                      children: <Widget>[
                        !showSubTitle ? Container() : buildNewContainer(lastBuild),
                        !showSubTitle
                            ? Container()
                            : Container(
                                child: Text(
                                  '  v' + version,
                                  style: TextStyle(
                                      color: Colors.grey, fontSize: 13),
                                ),
                              ),
                        Icon(
                          CupertinoIcons.right_chevron,
                          size: 20,
                          color: Theme.of(context).textTheme.caption.color,
                        ),
                      ],
                    ),
                  ),
                  onTap: () async {
                    print('点击了 $index 行,名称:$title');
                    switch (index) {
                      case 0:
                        String url =
                            "";
                        _navigateTo(context, url, _titles[index - 0]);
                        break;
                      case 1:
                        String url =
                            "";
                        _navigateTo(context, url, _titles[index - 1]);
                        break;
                      case 2:
                        _onWillPop();
                        break;
                    }
                  },
                )),
          ],
        ),
      ),
    );
  }

  Future<bool> _onWillPop() {
    return showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: Text('有新版本'),
            content: Text(updateModelTmp.data.content.toString()),
            actions: <Widget>[
              FlatButton(
                  onPressed: () {
                    Navigator.of(context).pop(true);
                  },
                  child: Text(
                    '残忍拒绝',
                    style: TextStyle(color: Theme.of(context).disabledColor),
                  )),
              FlatButton(
                  onPressed: () {
                    Navigator.of(context).pop(false);
                    String url = updateModelTmp.data.iosUrl;
                    // _navigateTo(context, url, '');
                    launch(url);
                  },
                  child: Text('去更新'))
            ],
          ),
        ) ??
        false;
  }

/*
 判断是否有更新标志
*/
   _getUpdateFlag(String lastBuild) {

    var lastBuildInt = int.parse(lastBuild);
    var versionValue = version.replaceAll('.', '');
    var versionInt = int.parse(versionValue);

    if (lastBuildInt > versionInt) {
      return true;
    }

    return false;
  }

/*
  构建更新标记控件
*/
  buildNewContainer(String lastBuild) {
    bool updateFlag =  _getUpdateFlag(lastBuild);

    return !updateFlag
        ? Container()
        : Container(
            decoration: new BoxDecoration(
              border: new Border.all(color: Colors.redAccent, width: 1.0),
              borderRadius: new BorderRadius.circular((4.0)),
            ),
            width: 40.0,
            height: 20.0,
            alignment: Alignment.center,
            child: Text(
              'New',
              style: TextStyle(color: Colors.redAccent, fontSize: 13),
            ),
          );
  }

  Future _getUpdate() async {
    ResultModel resultModel = await HTTPManager.requestBase(
        ServiceUrl.checkversion, {"build": '0'}, null, null);
    UpdateModel updateModel = UpdateModel.fromJson(resultModel.data);
    return updateModel;
  }

  setPreferences(String key, String value) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(key, value);
  }

  Future<String> _getPreferences(String key) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String value = prefs.getString(key);
    return value;
  }

  removePreferences(String key) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.remove(key);
  }

  void _navigateTo(BuildContext context, String url, String title) {
    url = FluroConvertUtils.fluroCnParamsEncode(url);
    title = FluroConvertUtils.fluroCnParamsEncode(title); //fluro 不支持中文需要转换下
    Application.router.navigateTo(
        context, '${QDDRouters.webviewPage}?url=$url&title=$title',
        transition: TransitionType.cupertino);
  }
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值