专栏首页技术人生用flutter给图片加个好看的遮罩层【flutter20个实例之六】

用flutter给图片加个好看的遮罩层【flutter20个实例之六】

一、老套路,先看样式

左起图一是我业务中的样式,左起图二、三是下方源码展示样式(复制可直接运行,无额外组件引入)

二、讲解

1.结构拆分

我们先看下页面布局结构,首先肯定是有个GridView滚动组件来容纳内容

其次顶部有个日期的选择,点击后底部弹出下拉选择,可以选择不同年份

年份选择后,进行内容刷新,数据重新加载

每个图片底部有个一定高度的遮罩层,用来放一些文字

2.看看这个布局的主内容

body里面的列表内容

右上角点击后调用了bottomModal组件

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('备忘录' + _dropValue),
          centerTitle: true,
          elevation: 0.0,
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.date_range),
              tooltip: "编辑",
              onPressed: () {
                return bottomModal();
              },
            ),
          ],
        ), //这个是顶部tab样式,如果不需要可以去掉
        body: monthList());
  }

3.底部弹框其实就是个showModalBottomSheet组件

isDismissible:false //点击空白区域不可关闭

row:底部的三个样式进行mainAxisAlignment: MainAxisAlignment.spaceBetween的布局排列

InkWell:为每个图标增加个点击事件

由于底部弹框也相当于一个页面,所以想要里面的select选择后内容跟着变动,就需要重定义setState()

4.核心内容列表就是一个GridView

一行显示4个

crossAxisCount: 4

左右间距

crossAxisSpacing: 10

上下间距

mainAxisSpacing: 10

宽高比

childAspectRatio: 0.6
    return Padding(
      padding: const EdgeInsets.all(10.0),
      child: SafeArea(
        child: GridView.builder(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 4,
              crossAxisSpacing: 10,
              mainAxisSpacing: 10,
              childAspectRatio: 0.6),
          itemBuilder: (context, index) {
            return _itemGrid(index);
          },
          itemCount: _list.length,
        ),
      ),
    );

5.主要是遮罩层的讲解

这里是一个stack,通过两个组件的堆叠实现,外层要设一个颜色透明度

属性要设置自动撑满,这样组件的遮罩层才会自动撑满父组件宽度

fit: StackFit.expand

然后要设置一个颜色透明度

decoration: BoxDecoration(color: Color(0x72000000)),

以下是flutter的所有颜色透明

比如完全不透明:0xFF000000 需要将第3第4两个字母,替换为下方列表的右侧两个字符即可

00%=FF(不透明) 
5%=F2 
10%=E5 
15%=D8 
20%=CC 
25%=BF 
30%=B2 
35%=A5 
40%=99 
45%=8c 
50%=7F 
55%=72 
60%=66 
65%=59 
70%=4c 
75%=3F 
80%=33 
85%=21 
90%=19 
95%=0c 
100%=00(全透明)

三、源码(可直接运行调试)

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class Mytest extends StatefulWidget {
  @override
  _MytestState createState() => _MytestState();
}

class _MytestState extends State<Mytest> {
  var _dropValue = '2020';
  List _list = [
    {
      'id': '1',
      'num': '0',
      'cover':
          'https://daybili.oss-cn-beijing.aliyuncs.com/image/202008/1m.jpg',
      'name': '1月'
    }
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('备忘录' + _dropValue),
          centerTitle: true,
          elevation: 0.0,
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.date_range),
              tooltip: "编辑",
              onPressed: () {
                return bottomModal();
              },
            ),
          ],
        ), //这个是顶部tab样式,如果不需要可以去掉
        body: monthList());
  }

  //核心的内容列表数据
  Widget monthList() {
    return Padding(
      padding: const EdgeInsets.all(10.0),
      child: SafeArea(
        child: GridView.builder(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 4,
              crossAxisSpacing: 10,
              mainAxisSpacing: 10,
              childAspectRatio: 0.6),
          itemBuilder: (context, index) {
            return _itemGrid(index);
          },
          itemCount: _list.length,
        ),
      ),
    );
  }

  Widget _itemGrid(index) {
    return InkWell(
      child: Container(
        color: Colors.black,
        height: 120,
        padding: EdgeInsets.all(0),
        child: Stack(
          fit: StackFit.expand,
          children: <Widget>[
            Container(
              height: 150,
              child: Image.network(
                _list[index]['cover'],
                fit: BoxFit.fill,
              ),
            ),
            Align(
              alignment: Alignment.bottomCenter,
              child: Container(
                width: double.infinity,
                child: RichText(
                  text: TextSpan(
                      style: DefaultTextStyle.of(context).style,
                      children: <InlineSpan>[
                        TextSpan(
                          text: _list[index]['name'],
                          style: TextStyle(
                              fontSize: 11,
                              decoration: TextDecoration.none,
                              color: Colors.white),
                        ),
                        TextSpan(
                          text: _list[index]['num'] + '条',
                          style: TextStyle(
                              color: Colors.red,
                              fontSize: 13,
                              decoration: TextDecoration.none),
                        ),
                        TextSpan(
                          text: '提醒',
                          style: TextStyle(
                              fontSize: 11,
                              color: Colors.white,
                              decoration: TextDecoration.none),
                        ),
                      ]),
                ),
                decoration: BoxDecoration(color: Color(0x72000000)),
              ),
            ),
          ],
        ),
      ),
    );
  }

  //底部日期选择框
  Widget bottomModal() {
    showModalBottomSheet(
        isDismissible: false,
        context: context,
        builder: (BuildContext context) {
          return StatefulBuilder(builder: (context1, state) {
            ///这里的state就是setState
            return Container(
              height: 60,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  InkWell(
                      onTap: () {
                        Navigator.of(context).pop();
                      },
                      child: Padding(
                        padding: const EdgeInsets.only(left: 10),
                        child: Icon(Icons.close),
                      )),
                  selectYear(context1, state),
                  InkWell(
                      onTap: () {
                        Navigator.of(context).pop();
                      },
                      child: Padding(
                        padding: const EdgeInsets.only(right: 10),
                        child: Icon(Icons.done),
                      ))
                ],
              ),
            );
          });
        });
  }

  Widget selectYear(context1, state) {
    return DropdownButtonHideUnderline(
      child: DropdownButton(
        iconSize: 20.0, //设置三角标icon的大小
        value: _dropValue,
        items: [
          DropdownMenuItem(
            child: Text('2020年'),
            value: '2020',
          ),
          DropdownMenuItem(child: Text('2021年'), value: '2021'),
          DropdownMenuItem(child: Text('2022年'), value: '2022'),
        ],
        onChanged: (value) {
          state(() {
            _dropValue = value;
          });
          setState(() {
            _dropValue = value;
          });
        },
      ),
    );
  }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 用flutter很简单的实现一个时光轴样式【flutter20个实例之五】

    左边图是我业务中的样式,右边图是下方源码展示样式(复制可直接运行,无额外组件引入)

    sinnoo
  • Not an editor command: Bundle ‘gmarik/Vundle.vim’ 错误的解决方案【工具】

    4,打开,~/.bashrc,在末尾添加export EDITOR=vim,然后执行source ~/.bashrc

    sinnoo
  • 谈谈flutter中Checkbox复选框的全选与删除【flutter20个实例之三】

    左侧三张图片是我的实际开发中业务界面,用作展示而已,具体源码效果是右边侧的三张图片。

    sinnoo
  • 1033 旧键盘打字 (20 分)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    韩旭051
  • Egret3D之初体验

    Ⅰ,Egret3D官方文档 : https://developer.egret.com/cn/docs/3d/docs/guide/getting-starte...

    py3study
  • [设计直播] I Love UX 第9期来袭!

    ? ? ? ? ? ? —— 关于I♥UX —— I♡UX AIR,是由腾讯ISUX用户体验设计部旗下原创馆创办的,面向广大设计师群体的在线直播论坛活动。I♡...

    腾讯ISUX
  • 注入利器之“四人帮”

    “注入”者,名如其义,在与对方数据库的一次次“别有用心”刺探访问中猜解出那些敏感信息的长要、范围,最终精确到点,颇有些让自己战友悄悄地打入敌人内部一样。看危险漫...

    C4rpeDime
  • 记一次大型且细小的域渗透实战

    我是后面接手这个域环境,而前面的dalao已经到域控的部分了,我因为写文章的原因,所以需要从原地出发,学习一下dalao是如何打到域控的

    Gcow安全团队
  • Flutter Drawer 抽屉视图与自定义header

    移动开发中,drawerLayout抽屉视图是比较常用的一种控件。一般将用户的头像,用户名等信息在抽屉视图中呈现。 drawer中也可以提供一些选项,比如跳转去...

    AnRFDev
  • sap.ushell.Container.getService.done的设计思路

    注意,此处执行done function并不意味着F5之后会看到执行一个名为done的function,而是执行done这个attribute指向的functi...

    Jerry Wang

扫码关注云+社区

领取腾讯云代金券