前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter 自定义列表以及本地图片引用

Flutter 自定义列表以及本地图片引用

作者头像
Mr.RisingSun
发布2021-01-27 10:32:42
9370
发布2021-01-27 10:32:42
举报
文章被收录于专栏:移动端开发移动端开发

前言


上篇关于Flutter的文章总结了下标签+导航的项目模式的搭建,具体的有需要的可以去看看Flutter分类的文章,这篇文章我们简单的总结一下关于Flutter本地文件引用以及简单的自定义List的使用,我们先总结本地图片的引用。今天这篇文章的具体的UI效果如下:

引用本地图片


我们没有使用到的我们暂时先不提,等后面慢慢补充进去,比如说网络图片的显示等等,我们现总结一下关于本地图片的使用,具体的我们需要下面几步:

1、创建文件导入资源

Flutter的文件资源需要我们创建一个文件去管理,我们可以定义一个images的文件,当然这个名字不是固定的但需要留意下它的文件等级,它里面还可以装别的其他资源文件,你要叫Resource也可以的。然后不管是做Android的还是iOS的都知道我们的图片资源是分2x和3x的,所以我们在你创建的文件下面再创建一个2.0x和3.0x的文件夹分别存放相应倍数的图片资源。如下图:

2、不是说直接导入就能直接使用的,还需要处理一下 pubspec.yaml文件,具体的改动如下面所示:

代码语言:javascript
复制
# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  # assets:
  #   - images/a_dot_burr.jpeg
  #   - images/a_dot_ham.jpeg

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware.

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages

  #### 图片资源
  assets:
    - images/icon_header.png
    - images/icon_heath.png
    - images/icon_village.png
    - images/mine_train.png

前面我们说的文件夹名字不是固定的,绑定使用的的就是assets,这里其实你理解成图片在项目中的层级位置就可以了。看上面Flutter给的注释信息,我们完全可以在导入别的信息,如 fonts等等。

3、现在可以直接使用了,它的使用还是相对比较简单的,我们直接上代码,需要注意的点是使用的时候需要的是图片全程,记得带上后缀。

代码语言:javascript
复制
Image.asset(
     "images/icon_header.png",
     width: 20,
     height: 20,
 )

实现上面我的页面


上面的实现我们需要简单的了解几个相应的控件,我们一个一个的介绍一下先,最后就可以出来我们前面的我的页面的UI了。

1、InkWell 它是一个效果控件 ,点击有泼墨的水波的效果 ,经常和Material+颜色透明一起使用。

2、Row 水平组件,首先一点是不管是我们现在说的Row还是我们后面说的 Column只能在继承与StatelessWidget或者StatefullWidget的Widget中使用。

代码语言:javascript
复制
Row({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline = TextBaseline.alphabetic,
    List<Widget> children = const <Widget>[],
  }) : super(
    children: children,
    key: key,
    direction: Axis.horizontal,
    mainAxisAlignment: mainAxisAlignment,
    mainAxisSize: mainAxisSize,
    crossAxisAlignment: crossAxisAlignment,
    textDirection: textDirection,
    verticalDirection: verticalDirection,
    textBaseline: textBaseline,
);

它就这么一个构造方法,还是相对比较简单的,首先它是不能滚动的,但是它可以灵活布局,如果要让某个子组件填充满剩余剩余空间,可以在 children 中使用 Expanded 组件,children 这个属性看上面的源码我们知道,它是一个 Widget 数组,这个我们在后面会使用到。具体的它里面的 Expanded 组件我们下面总结,现不在这里细说。

它里面的属性还是相对比较简单的,可以自己了解学习一下。我们接着看下面的组件。

3、Column

上面说的是水平的,那这个肯定就是竖直的了,其实它俩挺像的,也都是最基础的。我们把它初始化方法放出来对比一下,对比一下前面的Row:

代码语言:javascript
复制
Column({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline,
    List<Widget> children = const <Widget>[],
  }) : super(
    children: children,
    key: key,
    direction: Axis.vertical,
    mainAxisAlignment: mainAxisAlignment,
    mainAxisSize: mainAxisSize,
    crossAxisAlignment: crossAxisAlignment,
    textDirection: textDirection,
    verticalDirection: verticalDirection,
    textBaseline: textBaseline,
  );
}

4、Expanded

这个我们也需要说说的,因为我们的Row和Column都需要Expanded,其实它也是比较简单的:

代码语言:javascript
复制
class Expanded extends Flexible {
  /// Creates a widget that expands a child of a [Row], [Column], or [Flex]
  /// so that the child fills the available space along the flex widget's
  /// main axis.
  const Expanded({
    Key key,
    int flex = 1,
    @required Widget child,
  }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
}

我们就需要了解两个参数一个 flex 和一个 child,child我们就不多说了,比较简单,flex 按照一个比例理解,比如两个Expanded , 并排需要控制它们的宽度比例,就可以使用这个属性。这些我们在下面的代码使用中都有体现的。我们代码中细说。

我们看具体的代码,理解了上面大概说的,这个代码就相对比较简单了,我们先看看顶部的头部我们是怎样定义的:

代码语言:javascript
复制
class MineHeader extends StatelessWidget {

  String userHeaderImage;
  String userName;

  /// 这里定义了就可以在外面使用这个方法进行初始化
  MineHeader(this.userHeaderImage, this.userName);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.orange,
      height: 100,

      /// 水平布局
      /// 在Row中使用Expanded的时候,无法指定Expanded中的子组件的宽度width,但可以指定其高度height。
      /// 同理,在Column中使用Expanded的时候,
      /// 无法指定Expanded中的子组件的高度height,可以指定宽度width。
      child: Row(
        children: <Widget>[
          Expanded(
            flex: 1,
            child: Container(
              padding: EdgeInsets.only(left: 15),
              child: Image.asset(
                userHeaderImage,
                width: 50,
                height: 50,
              ),
            ),
          ),
          Expanded(
            flex: 5,
            child: Container(
              padding: EdgeInsets.only(left: 15),
              child: Text(
                userName,
                /// 18号 蓝色 加粗
                style: TextStyle(
                    fontSize: 18,
                    color: Colors.white,
                    fontWeight: FontWeight.bold),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

需要我们注意的点我们都在上面代码注释中基本上都说了,接下来我们我们看看下面列表的代码:

代码语言:javascript
复制
class MineItemWidget extends StatelessWidget {
  String imageName;
  String title;

  @required
  VoidCallback onTap;

  MineItemWidget(this.imageName, this.title, {this.onTap});

  @override
  Widget build(BuildContext context) {
    return Container(
      /// 子视图 颜色容器
      child: Column(
        children: <Widget>[
          ///
          Container(
            height: 53,
            child: _mineItem(imageName, title),
          ),
          Container(
            color: Color(0xffeaeaea),
            constraints: BoxConstraints.expand(height: 1.0),
          ),
        ],
      ),
    );
  }

  Widget _mineItem(String imageName, String title) {
    return InkWell(
      onTap: () {
        this.onTap();
      },
      child: Row(
        ///
        children: <Widget>[
          Expanded(
            flex: 1,
            child: Container(
              padding: EdgeInsets.only(left: 15),
              child: Image.asset(
                imageName,
                width: 20,
                height: 20,
              ),
            ),
          ),
          Expanded(
            flex: 6,
            child: Container(
              padding: EdgeInsets.only(left: 15),
              child: Text(
                title,
                style: TextStyle(fontSize: 16),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

最后就是把它俩写到我们的 MinePage ,MinePage的代码如下:

代码语言:javascript
复制
class MinePage extends StatefulWidget {
  MinePage({Key key}) : super(key: key);
  @override
  _MinePageState createState() => _MinePageState();
}

class _MinePageState extends State<MinePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: Text("我的"),
        backgroundColor: Colors.orange,
        elevation: 0, // 去掉Appbar底部阴影
      ),
      body: ListView(
        children: <Widget>[
          /// 头部的View
          MineHeader("images/icon_header.png", "张旭旭旭旭啊"),
          /// 线
          _listViewLine,
          MineItemWidget("images/icon_heath.png", "我的健康", onTap: () {
            /// 跳转到查看按钮内容界面
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => MineCustomButton()),
            );
          }),
          MineItemWidget("images/icon_village.png", "我的旅行", onTap: () {
            print('我的旅行');
          }),
          _listViewLine,
          MineItemWidget("images/mine_train.png", "我的家乡", onTap: () {
            print('我的家乡');
          }),
        ],
      ),
    );
  }

  /// 分割线
  Widget get _listViewLine {
    return Container(
      color: Color(0xffeaeaea),
      height: 6,
    );
  }
}

这样整个一个基本的效果就出来了,如最开始我们给的那张图效果一样。打算在后面一篇文章中再说说我们常见到一些组件,按钮,输入框,进度条等等的。

参考文章:

1、 Flutter ListView 自定义

2、详解flutter中本地资源图片的使用

3、项目地址

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-01-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档