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

2020-11-13 16:04:13 浏览数 (1)

一、老套路,先看样式

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

二、讲解

1.结构拆分

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

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

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

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

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

body里面的列表内容

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

代码语言:javascript复制
  @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个

代码语言:javascript复制
crossAxisCount: 4

左右间距

代码语言:javascript复制
crossAxisSpacing: 10

上下间距

代码语言:javascript复制
mainAxisSpacing: 10

宽高比

代码语言:javascript复制
childAspectRatio: 0.6
代码语言:javascript复制
    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,通过两个组件的堆叠实现,外层要设一个颜色透明度

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

代码语言:javascript复制
fit: StackFit.expand

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

代码语言:javascript复制
decoration: BoxDecoration(color: Color(0x72000000)),

以下是flutter的所有颜色透明

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

代码语言:javascript复制
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(全透明)

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

代码语言:javascript复制
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 人点赞