flutter 项目实战四 列表数据展示

本项目借用 逛丢 网站的部分数据,仅作为 flutter 开发学习之用。 逛丢官方网址:https://guangdiu.com/

flutter windows开发环境设置

flutter 项目实战一 新建 flutter 项目

flutter 项目实战二 网络请求

flutter 项目实战三 json数据解析以及Gson格式化flutter 项目实战二 网络请求

flutter 项目实战四 列表数据展示

flutter 项目实战五 item 点击跳转,webview加载

flutter 项目实战六 drawer侧边栏

flutter 项目实战七 bottomNavigationBar

flutter 项目实战八 下拉刷新 上拉加载

flutter 项目实战九 小时风云榜

先放上 本人 使用 kotlin 开发的逛丢的页面,kotlin开发的源码以及相关说明将在其他部分给出。

我们会按照此列表展示,但是UI会略有修改。

appBar部分为一个 Image 与 title ,不用详细的分解。

列表的Item 分解示意图如下

说名一下,row是横向排列的控件,column是竖向排列的控件。container 可设置边框边距等属性。

开始代码实现步骤。

新建一个 home_index.dart文件

class HomeIndex extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return IndexWidget();
  }
}

class IndexWidget extends State<HomeIndex>{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return null;
  }
  
}

flutter 页面新建的时候可以选择继承  StatefulWidget 以及 StatelessWidget,StatelessWidget是无状态值得,即不可使用setState更新变量,我们需要在获取数据之后来刷新页面加载数据,所以我们使用 StatefulWidget .然后修改 main() 中的代码加载HomeIndex.

此时 IndexWidget 的 build方法返回的还是空值,先完成appBar 部分,修改代码

class IndexWidget extends State<HomeIndex>{

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
        appBar: AppBar(
          title: Text("首页",style: TextStyle(color: Colors.white),),
          leading: Icon(Icons.menu,color: Colors.white,),
          backgroundColor: Colors.green[500],
        ),
        body: Text("列表数据等待设计"),
    );
  }

}

运行代码

flutter中的所有的控件都是基于 Widget 所有可以使用 各widget 组合出各种效果。上面的appBar 中控件排列方式如下图(actions未展示),大概的位置如下图所示(请忽略图的美丑,示意即可)

下面按照之前的 item 分析设计列表数据。flutter中列表数据使用 ListView.builder 创建。

首先item用container包裹,里面是一个横向排列的Row控件,Row有两个子widget ,左边一个 image,右边一个 column ,column又分为两部分,上面一个Text,下面又是一个Row,而此Row又包含一个靠左显示的Text,以及靠右的有两个子Text的Row.分析完了,开始代码。

根据梳理好的结构关系,编写代码如下

class IndexWidget extends State<HomeIndex>{

  List<RstData> _listData;//设置列表数据

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
        appBar: AppBar(
          title: Text("首页",style: TextStyle(color: Colors.white),),
          leading: Icon(Icons.menu,color: Colors.white,),
          backgroundColor: Colors.green[500],
        ),
        body: _listInfos(),
    );
  }

  //list列表
  Widget _listInfos(){
    return ListView.builder(
        itemCount: 3,//此处展示需要写成此形式,实际适用时  _listData==null?0:_listData.length
        itemBuilder: (content,index){
           return _listItem(null);
        }
    );
  }
  //list列表的item
  Widget _listItem(RstData rstdata){
    return Container(
      height: 110,//设置item的高度
      padding: EdgeInsets.all(5),//设置item的边距
      child: Row(
        children: <Widget>[
          Container(
            height: 100,
            margin: EdgeInsets.all(5),//设置图片的边距
            child: Image.network("https://l.guangdiu.com/29ddbc1dc1e151a2311604744f54510b.jpg?imageView2/2/w/224/h/224/format/jpg"),
          ),//涉及到widget的大小或者边框的时候,使用container包裹
          Container(
            width: MediaQuery.of(context).size.width-120,
            child: Column(
              children: <Widget>[
                Text("拼多多 Apple 苹果 新iPad Air 10.5 英寸平板电脑 WLAN版 64GB 3749元包邮(直降250元)"),
                Expanded( //此处使用expanded 填充,然后设置container 的对其方式确保 在底部显示
                  child:  Row(
                    children: <Widget>[
                      Container(
                        alignment: Alignment.bottomLeft,//设置container的对其方式
                        child: Text("天猫",style: TextStyle(color: Colors.green[500]),),
                      ),
                      Expanded(
                        child: Container(
                          alignment: Alignment.bottomRight,//设置container的对其方式
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.end,//设置ROW的对其显示方式
                            children: <Widget>[
                              Text("3分钟前-",style: TextStyle(color: Colors.green[500]),),
                              Text("今日值得买",style: TextStyle(color: Colors.green[500]),),
                            ],
                          ),
                        ),
                      ),
                    ],
                  ),
                ),//expanded类似于Android View的layout_weight属性按照比例填充,flex: 为1 时可以不填写此属性
              ],
            ),
          ),
        ],
      ),
    );
  }

}

因为边界问题所以当widget需要设置宽高,对其方式等属性是,我们用container进行包裹,当控件需要占用一个不固定的空间时,我们用expanded 包裹,达到类似于 Android View的layout_weight的使用效果。

运行示例,app截图

基本样式已完成,下面的步骤是使用网络数据填充,并且给item添加一个框框

修改后的代码为

class IndexWidget extends State<HomeIndex>{

  List<RstData> _listData;//设置列表数据

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
        appBar: AppBar(
          title: Text("首页",style: TextStyle(color: Colors.white),),
          leading: Icon(Icons.menu,color: Colors.white,),
          backgroundColor: Colors.green[500],
        ),
        body: _listInfos(),
    );
  }

  //list列表
  Widget _listInfos(){
    return ListView.builder(
        itemCount: _listData==null?0:_listData.length,//此处展示需要写成 3,实际适用时  _listData==null?0:_listData.length
        itemBuilder: (content,index){
           return _listItem(_listData[index]);
        }
    );
  }
  //list列表的item
  Widget _listItem(RstData rstdata){
    return Container(
      height: 110,//设置item的高度
      margin: EdgeInsets.only(left: 5,right: 5,top: 5),//设置item的边距
      decoration: BoxDecoration(
        border: Border.all(color: Colors.black54,width: 1),//设置边框的宽度 以及 颜色
        borderRadius: BorderRadius.all(Radius.circular(5)),//设置圆角
      ),
      child: Row(
        children: <Widget>[
          Container(
            height: 100,
            margin: EdgeInsets.all(5),//设置图片的边距
            child: Image.network(rstdata.image),
          ),//涉及到widget的大小或者边框的时候,使用container包裹
          Expanded(
            child: Container(
              margin: EdgeInsets.only(right: 5),
              child: Column(
                children: <Widget>[
                  Text(rstdata.title),
                  Expanded( //此处使用expanded 填充,然后设置container 的对其方式确保 在底部显示
                    child:  Row(
                      children: <Widget>[
                        Container(
                          alignment: Alignment.bottomLeft,//设置container的对其方式
                          child: Text(rstdata.mall,style: TextStyle(color: Colors.green[500]),),
                        ),
                        Expanded(
                          child: Container(
                            alignment: Alignment.bottomRight,//设置container的对其方式
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.end,//设置ROW的对其显示方式
                              children: <Widget>[
                                Text("${rstdata.pubtime}-",style: TextStyle(color: Colors.green[500],fontSize: 10),),
                                Text(rstdata.fromsite,style: TextStyle(color: Colors.green[500],fontSize: 10),),
                              ],
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),//expanded类似于Android View的layout_weight属性按照比例填充,flex: 为1 时可以不填写此属性
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    //项目加载时去获取数据
    _getGuangdiuIndexData();
  }

  void _getGuangdiuIndexData() async{
    String url="getlist.php";
    FormData formData=FormData();
    formData.add("markid", "5685521");
    Response resp=await HttpUtil().post(url,data: formData).then((resp){
      RespResult respResult=RespResult.fromJson(resp.data);
      setState(() {
        _listData=respResult.data;
      });
    });
  }
}

此处在 initState 中获取数据,所有不用热加载更新,否则看不到数据。重新运行项目等到数据列表

此为数据的展示样式

码云 git 下载

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值