一、老套路,先看樣式
圖一是我業務中的樣式,圖二、三是下方原始碼展示樣式(複製可直接執行,無額外元件引入)
二、講解
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;
});
},
),
);
}
}
複製程式碼