用flutter給圖片加個好看的遮罩層【flutter20個例項之六】

蔥頭來過發表於2021-08-13

一、老套路,先看樣式

圖一是我業務中的樣式,圖二、三是下方原始碼展示樣式(複製可直接執行,無額外元件引入)

二、講解

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;
          });
        },
      ),
    );
  }
}
複製程式碼

相關文章