信息流 ListView 的实现

93 阅读3分钟

发布技术文章,文章内首/尾句带关键词“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情

信息流 ListView 的实现

实现这个信息流。

正在热映的信息流页面

将信息流页面在单独的类里实现

因为信息流页面的实现比较复杂,所以为了使代码结构清晰,又需要对原来的代码进行重构,这次将信息流页面的代码提取出来,在单独的类里实现。

新建一个文件 HotMoviesListWidget.dart,代码为:

import 'package:flutter/material.dart';

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

class HotMoviesListWidgetState extends State<HotMoviesListWidget> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child: Text('正在热映'),
    );
  }
}

然后将 HotWidget.dart 里正在热映的代码从:

children: <Widget>[
  Center(
        child: Text('正在热映'),
      ),
  Center(
        child: Text('即将上映'),
      )
]

改为:

children: <Widget>[
  HotMoviesListWidget(),
  Center(
    child: Text('即将上映'),
  )
]

使用 ListView 实现信息流

很明显,要实现信息流,需要用到 ListView。

HotMovieData:上映电影的信息

新建一个文件 HotMovieData.dart,在这个文件里创建存储上映电影信息的类 HotMovieData:

class HotMovieData{
  String title;
  double rating;
  String directors;
  String casts;
  int watchedPeople;
  String images;

  HotMovieData(this.title,this.rating,this.directors,this.casts,this.watchedPeople,this.images);
}

HotMovieItemWidget:ListView 里 item 的布局

新建一个文件 HotMovieItemWidget.dart 用来实现信息流 ListView 里 item 的布局。

item 的布局解析之后如下:

而且 item 里要显示数据,所以要在 item 里传入 HotMovieData 的数据,加到 HotMovieItemWidget 的构造函数里:

class HotMovieItemWidget extends StatefulWidget {
  HotMovieData hotMovieData;

  HotMovieItemWidget(this.hotMovieData);

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return HotMovieItemWidgetState();
  }
}

最后实现的代码为:

import 'package:flutter/material.dart';
import 'package:flutter_doubanmovie/HotMovieData.dart';

class HotMovieItemWidget extends StatefulWidget {
  HotMovieData hotMovieData;

  HotMovieItemWidget(this.hotMovieData);

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return HotMovieItemWidgetState();
  }
}

class HotMovieItemWidgetState extends State<HotMovieItemWidget> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      height: 160,
      padding: EdgeInsets.all(20),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Image.network(
            widget.hotMovieData.images,
            width: 80,
            height: 120,
            fit: BoxFit.cover,
          ),
          Expanded(
            flex: 1,
            child: Padding(
              padding: EdgeInsets.only(left: 20),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text(
                    widget.hotMovieData.title,
                    style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
                  ),
                  Text(
                    widget.hotMovieData.rating.toString(),
                    style: TextStyle(fontSize: 14, color: Colors.black54),
                  ),
                  Text('导演: ' + widget.hotMovieData.directors,
                      style: TextStyle(fontSize: 14, color: Colors.black54)),
                  Text('主演: ' + widget.hotMovieData.casts,
                      style: TextStyle(fontSize: 14, color: Colors.black54)),
                ],
              ),
            ),
          ),
          Container(
            width: 100,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(widget.hotMovieData.watchedPeople.toString()+'人看过',style: TextStyle(color: Colors.red,fontSize: 14),),
                OutlineButton(
                  child: Text('购票',style: TextStyle(fontSize: 16),),
                  color: Colors.red,
                  textColor: Colors.red,
                  highlightedBorderColor: Colors.red,
                  borderSide: BorderSide(
                    color: Colors.red
                  ),
                  onPressed: () {},
                )
              ],
            ),
          )
        ],
      ),
    );
  }
}

ListView:信息流实现

在 HotMoviesListWidget.dart 文件里加入 ListView 了。

  • 首先加入数据
    在 HotMoviesListWidgetState 里,增加一个变量 hotMovies:
List<HotMovieData> hotMovies = new List<HotMovieData>();

在 HotMoviesListWidgetState 的 initState() 生命周期里为 hotMovies 赋值:

  • ListView
    然后使用 ListView:
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return ListView.separated(
        itemCount: hotMovies.length,
        itemBuilder: (context, index) {
          return HotMovieItemWidget(hotMovies[index]);
        },
        separatorBuilder: (context, index) {
          return Divider(
            height: 1,
            color: Colors.black26,
          );
        },
      );
  }

运行后的效果为:

然后会发现 ListView 的头部有一段空白区域,是因为当 ListView 没有和 AppBar 一起使用的时候,头部就会有一个 padding,为了去掉 padding ,可以使用 MediaQuery.removePadding:
然后,运行的效果就会正常:

最后 HotMoviesListWidget.dart 里的代码会改成:

import 'package:flutter/material.dart';
import 'package:flutter_doubanmovie/HotMovieData.dart';
import 'package:flutter_doubanmovie/HotMovieItemWidget.dart';

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

class HotMoviesListWidgetState extends State<HotMoviesListWidget> {
  List<HotMovieData> hotMovies = new List<HotMovieData>();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    var data = HotMovieData('反贪风暴4', 6.3, '林德禄', '古天乐/郑嘉颖/林峯', 29013,
        'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2551353482.webp');
    setState(() {
      hotMovies.add(data);
      hotMovies.add(data);
      hotMovies.add(data);
      hotMovies.add(data);
      hotMovies.add(data);
      hotMovies.add(data);
    });
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MediaQuery.removePadding(
      removeTop: true,
      context: context,
      child: ListView.separated(
        itemCount: hotMovies.length,
        itemBuilder: (context, index) {
          return HotMovieItemWidget(hotMovies[index]);
        },
        separatorBuilder: (context, index) {
          return Divider(
            height: 1,
            color: Colors.black26,
          );
        },
      ),
    );
  }
}

发布技术文章,文章内首/尾句带关键词“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情