前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用flutter给图片加个好看的遮罩层【flutter20个实例之六】

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

作者头像
sinnoo
发布2020-11-13 16:04:13
4.2K0
发布2020-11-13 16:04:13
举报
文章被收录于专栏:技术人生

一、老套路,先看样式

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

二、讲解

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;
          });
        },
      ),
    );
  }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、老套路,先看样式
  • 二、讲解
  • 三、源码(可直接运行调试)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档