我的第一个flutter demo 顶部导航栏加网络请求的基本使用

上图是要实现的效果得意,废话不多说上代码。。由于涉及到公司的接口,所以代码里涉及这块就不贴出来了。

1 首先创建一个类 继承 StatelessWidget 由于是我的模块 就命名为MineLayout

class ReadLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Widget tabBarContainer = new TabBar(//创建TabBar实例
      isScrollable: true, //这个属性是导航栏是否支持滚动,false则会挤在一起了
      unselectedLabelColor: Colors.grey, //未选标签标签的颜色(这里定义为灰色)
      labelColor: Colors.black,//选中的颜色(黑色)
      indicatorColor: Colors.black,//指示器颜色
      indicatorWeight: 2.0,//指示器厚度
      tabs: choices.map((Choice choice) {//选项卡
        return new Tab(
          text: choice.title,
        );
      }).toList(),
    );

    Widget tabContainer = new DefaultTabController(
      length: choices.length,
      initialIndex: 0, //初始索引
      child: new Column(
        children: <Widget>[
          new Container(
            constraints: new BoxConstraints.expand(
              height:
                  Theme.of(context).textTheme.display1.fontSize * 1.1 + 50.0,
            ),
            padding: const EdgeInsets.all(8.0),
            color: Colors.teal.shade700,
            alignment: Alignment.center,
            child: tabBarContainer,
          ),
          new Expanded(
            child: new TabBarView(
              children: choices.map((Choice choice) {
                return new BookListView(categoryId: choice.categoryId);//一个属于展示内容的listview
              }).toList(),
            ),
          ),
        ],
      ),
    );

    return tabContainer;
  }
}

注意:上面我不是没有Appbar 的,所以默认会侵入到系统栏,所以我定义了高度

height: Theme.of(context).textTheme.display1.fontSize * 1.1 + 50.0,

接着定义一个类去封装顶部标签
class Choice {
  const Choice({this.title,  this.categoryId});

  final String title;//这个参数是分类名称
  final int categoryId;//这个适用于网络请求的参数,获取不同分类列表
}

const List<Choice> choices = const <Choice>[

  const Choice(
    title: '通话故事',
    categoryId: 1,
  ),
  const Choice(
    title: '科幻灵异',
    categoryId: 2,
  ),
  const Choice(
    title: '经典名著',
    categoryId: 3,
  ),
  const Choice(
    title: '科普百科',
    categoryId: 4,
  ),
  const Choice(
    title: '历史传记',
    categoryId: 5,
  ),
  const Choice(
    title: '诗歌散文',
    categoryId: 6,
  ),
  const Choice(
    title: '幽默成长',
    categoryId: 7,
  ),
  const Choice(
    title: '寓言传说',
  ),
];

接着我们来看listview 的具体实现吧。

原理很简单,就是在初始化时加载用过异步的方式加载网络数据将请求到的数据放到定义好的集合里面,然后调用setState方法重新构建widget。这时listview的itemcount就有数了。得意

class _BookListViewState extends State<BookListView> {
  List widgets = [];
  int bookId;
  String bookName;
  String coverKey;
  int picture;
  int media;
  int lang;
  int isQuestion;
  String author;
  String introduction;
  int downloadNum;
  String coverUrl;

//  final List<RowsBean> books;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    loadData(widget.categoryId);
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: new ListView.builder(
            itemCount: widgets.length,
            itemBuilder: (BuildContext context, int position) {
              return getRow(position);
            }));
  }

  loadData(int categoryId) async {
    String dataURL =
        "你的API?categoryId=$categoryId";
    http.Response response = await http.get(dataURL);
    print(response.body);
    Map data = JSON.decode(response.body);

    var retobj = data['retobj'];
    List rows = retobj['rows'];
    widgets = rows;
    setState(() {
//      JsonDecoder decoder = new JsonDecoder();
//
//      // 将给定的JSON字符串输入转换为其对应的对象
//      List<List<RowsBean>> json = decoder.convert(response.body);
//      // 输出给定的JSON数据
//      print(json[0][1]);
//      widgets = JSON.decode(response.body);
    });
  }

  Widget getRow(int i) {
    return new BookListItem(
      bookId: widgets[i]['bookId'],
      bookName: widgets[i]['bookName'],
      coverKey: widgets[i]['coverKey'],
      picture: widgets[i]['picture'],
      media: widgets[i]['media'],
      lang: widgets[i]['lang'],
      isQuestion: widgets[i]['isQuestion'],
      introduction: widgets[i]['introduction'],
      downloadNum: widgets[i]['downloadNum'],
      author: widgets[i]['author'],
      coverUrl: widgets[i]['coverUrl'],
    );
  }
}



上面涉及到网络请求和json解析,楼主该开始也不知道怎么解析,官方的都是返回的一个list类型的json,看看我们返回的json类型吧


 
 

接着就需要写item的布局了,布局就是左边一张图,右边一个模块,右边模块采用线性布局。

import 'package:flutter/material.dart';

import 'package:flutter/rendering.dart';

class BookListItem extends StatelessWidget {
  BookListItem(
      {this.bookId,
      this.bookName,
      this.coverKey,
      this.picture,
      this.media,
      this.lang,
      this.isQuestion,
      this.author,
      this.introduction,
      this.downloadNum,
      this.coverUrl})
      : super(key: new ObjectKey(bookId));
  int bookId;
  String bookName;
  String coverKey;
  int picture;
  int media;
  int lang;
  int isQuestion;
  String author;
  String introduction;
  int downloadNum;
  String coverUrl;

  @override
  Widget build(BuildContext context) {
    print('bookId:$bookId');
    Widget titleSection = new Container(
      padding: const EdgeInsets.fromLTRB(12.0, 8.0, 0.0, 0.0),
      child: new Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          new Image.network(
            coverUrl,
            width: 107.0,
            height: 130.0,
          ),
          new Expanded(
            child: new Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                new Container(
                  padding: const EdgeInsets.fromLTRB(6.0, 15.0, 24.0, 0.0),
                  child: new Text(
                    bookName,
                    style: new TextStyle(
                        fontWeight: FontWeight.bold, fontSize: 17.0),
                  ),
                ),
                new Container(
                  padding: const EdgeInsets.fromLTRB(6.0, 16.0, 24.0, 0.0),
                  child: new Text(
                    author,
                    style: new TextStyle(
                        fontWeight: FontWeight.bold, fontSize: 13.0),
                  ),
                ),
                new Container(
                  padding: const EdgeInsets.fromLTRB(6.0, 18.0, 24.0, 2.0),
                  child: new Text(
                    introduction,
                    overflow: TextOverflow.ellipsis,
                    textAlign: TextAlign.start,
                    maxLines: 3,
                    style: new TextStyle(
                        fontSize: 12.0, fontStyle: FontStyle.normal),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );

    return titleSection;
  }
}

ok, 本节就说道这里,文笔简陋,见谅,欢迎私信,互相学习。。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值