1. 前言
由於在實際的開發過程中會有遇到各式各樣的效果,會把一些常見的介面佈局與部件使用統一放在這個倉庫下,如果有遇到和你需求一致的直接拿走即可,感覺有幫助,star
一下更好,不迷路。
- 倉庫地址:github.com/yayxs/flutt…
- star數:3(截至發稿)
- 特別說明:有些效果是藉助於大佬的開原始碼
- 閱讀預警:有表有圖有程式碼
2. 倉庫資料夾
由於是每個小案例新建的一個flutter
專案,所以克隆下倉庫cd
到資料夾flutter run
即可。部分說明如下
資料夾 | 外掛 / 技術點 /第三方包 | 其他說明 |
---|---|---|
cached_network_image_demo | cached_network_image: ^1.1.3 | 這個主要用來驗證網路圖片批量載入的快取效果 |
color_decoration_test | 佈局的修飾 | 這個主要是驗證修飾的時候color 與decoration: BoxDecoration() 不能夠同時使用 |
custom_scroll_view_demo | flutter內建api | 這個主要是滾動效果小案例 |
dismissible_demo | flutter內建api | 主要是測試滑動刪除的效果 |
fl_chart_scatter_demo | fl_chart | 主要是圖表相關 |
flutter_bar_chart_demo | 圖表 | 這個主要是bar統計圖,我在上幾個專欄也提到過 |
flutter_dio_demo | dio | 網路請求庫簡單試水(沒有參考價值) |
flutter_radar_chart_demo | 圖表 | 這個是雷達圖效果的案例 |
flutter_select_demo | direct_select_flutter: ^1.0.5 | 這個是選取效果 |
flutter_state_demo | 狀態管理 | 我有提到要書寫一篇專欄分享一下我對狀態管理的理解,由於週六加班鴿了 |
json_to_model_demo | json_to_dart | 這個是AD一個json轉模型的測試 |
loading_demo | loading: ^1.0.2 | 這個是loading載入的效果,就是網路請求的時候 |
long_press_delete_demo | 點選 | 這個主要是使用者長按某塊進行刪除 |
new_provider_demo | provider | 這個是provider新版本更新過後廢棄掉builder之後的demo |
ok_toast_demo | ok_toast | 這個主要是toast案例 |
search_demo | flutter 內建api | 這個主要是搜尋框 |
select_demo | 選取 | 這個主要是按住拖動選擇 |
selection_callback_example_bar | 這個主要是圖表可以點選的回撥測試 | |
sliver_demo | flutter sliver | 這個主要是滾動大家族頂樑柱 |
spider_chart_demo | 圖表 | 像個蜘蛛網一樣 |
url_launcher_demo | url_launcher | 更新頻次比較快的一個跳轉其他app的庫 |
3. 演示效果
1.dismissible_demo
這個有必要分享一下,也是參考了一位大佬的封裝,是類似於微信的左滑刪除等其他操作
- 案例演示
- 核心程式碼
Widget _createListView() {
return ListView.builder(
itemCount: _listData.length,
itemBuilder: (context, index) {
return Dismissible(
// Key
key: Key('key${_listData[index]}'),
// Child
child: ListTile(
title: Text('${_listData[index]}'),
),
onDismissed: (direction) {
var _snackStr;
if (direction == DismissDirection.endToStart) {
// 從右向左 也就是刪除
_snackStr = '刪除了${_listData[index]}';
} else if (direction == DismissDirection.startToEnd) {
_snackStr = '收藏了${_listData[index]}';
}
// 展示 SnackBar
Scaffold.of(context).showSnackBar(SnackBar(
content: Text(_snackStr),
duration: Duration(milliseconds: 400),
));
// 刪除後重新整理列表,以達到真正的刪除
setState(() {
_listData.removeAt(index);
});
},
background: Container(
color: Colors.green,
// 這裡使用 ListTile 因為可以快速設定左右兩端的Icon
child: ListTile(
leading: Icon(
Icons.bookmark,
color: Colors.white,
),
),
),
secondaryBackground: Container(
color: Colors.red,
// 這裡使用 ListTile 因為可以快速設定左右兩端的Icon
child: ListTile(
trailing: Icon(
Icons.delete,
color: Colors.white,
),
),
),
confirmDismiss: (direction) async {
var _confirmContent;
var _alertDialog;
if (direction == DismissDirection.endToStart) {
// 從右向左 也就是刪除
_confirmContent = '確認刪除${_listData[index]}?';
_alertDialog = _createDialog(
_confirmContent,
() {
// 展示 SnackBar
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('確認刪除${_listData[index]}'),
duration: Duration(milliseconds: 400),
));
Navigator.of(context).pop(true);
},
() {
// 展示 SnackBar
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('不刪除${_listData[index]}'),
duration: Duration(milliseconds: 400),
));
Navigator.of(context).pop(false);
},
);
} else if (direction == DismissDirection.startToEnd) {
_confirmContent = '確認收藏${_listData[index]}?';
_alertDialog = _createDialog(
_confirmContent,
() {
// 展示 SnackBar
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('確認收藏${_listData[index]}'),
duration: Duration(milliseconds: 400),
));
Navigator.of(context).pop(true);
},
() {
// 展示 SnackBar
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('不收藏${_listData[index]}'),
duration: Duration(milliseconds: 400),
));
Navigator.of(context).pop(false);
},
);
}
var isDismiss = await showDialog(
context: context,
builder: (context) {
return _alertDialog;
});
return isDismiss;
},
);
},
);
}
複製程式碼
2.long_press_delete_demo
這個效果是長按的時候進行刪除,有個小彈窗
-
專案演示
-
核心程式碼
class PlusMinusEntry extends PopupMenuEntry<int> {
@override
final double height = 100;
@override
bool represents(int n) => n == 1 || n == -1;
@override
PlusMinusEntryState createState() => PlusMinusEntryState();
}
class PlusMinusEntryState extends State<PlusMinusEntry> {
void _plus1() {
// 這是關閉彈出選單並返回使用者選擇的方式。 1 刪除 -1 取消
Navigator.pop<int>(context, 1);
}
void _minus1() {
Navigator.pop<int>(context, -1);
}
@override
Widget build(BuildContext context) {
return Opacity(
child: Container(
color: Color.fromRGBO(0, 0, 0, 0.4),
child: Row(
children: <Widget>[
Expanded(child: FlatButton(onPressed: _plus1, child: Text('刪除'))),
Expanded(
child: FlatButton(onPressed: _minus1, child: Text('取消'))),
],
)),
opacity: 0.3,
);
}
}
複製程式碼
3.new_provider_demo
這個是 provider 廢棄掉 builder 之後的用法
- 核心用法
providers: [
ChangeNotifierProvider(create: (_) => Counter()),
],
複製程式碼
4.ok_toast_demo
這個是一個 toast,提醒時候用
- 專案演示
5.scatter_plot_chart
這個主要是畫點(沒什麼內容)
- 效果演示
- 核心程式碼
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
var paint = Paint();
_myDrawCircle(double offsetX, double offsetY, double radius, Paint paint) {
canvas.drawCircle(
Offset(offsetX, offsetY),
radius,
paint,
);
}
for (int i = 0; i <= listData.length; ++i) {
paint
..style = PaintingStyle.fill
..color = Colors.lightBlue;
if (i == 0) {
_myDrawCircle(50.0, 50.0, 10.0, paint);
} else {
_myDrawCircle(50.0 + 50 * i, 50, 10.0, paint);
}
}
}
//在實際場景中正確利用此回撥可以避免重繪開銷
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
複製程式碼
6.search_demo
這個主要是搜尋的效果,並不是在 appBar 上
- 演示效果
- 核心程式碼
Widget buildTextField() => TextField(
cursorColor: Colors.black, // 游標顏色
// 預設設定
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 10.0),
border: InputBorder.none,
icon: Icon(Icons.search),
hintText: "教師姓名",
hintStyle: new TextStyle(
fontSize: 14, color: Color.fromARGB(50, 0, 0, 0))),
style: new TextStyle(fontSize: 14, color: Colors.black),
);
複製程式碼
7.select_demo
這個主要是選擇,滑動進行選擇的效果
- 演示效果
- 核心程式碼
body: DirectSelectContainer(
child: SingleChildScrollView(
child: Container(
width: 150,
child: Column(
mainAxisSize: MainAxisSize.min,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Column(
children: <Widget>[
Row(children: <Widget>[
Expanded(
child: Container(
decoration: _getShadowDecoration(),
child: Card(
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.only(left: 22),
child: DirectSelectList<String>(
values: _dataList,
defaultItemIndex: selectedIndex,
itemBuilder: (String value) =>
getDropDownMenuItem(value),
focusedItemDecoration: _getDslDecoration(),
onUserTappedListener: () {
_showScaffold();
},
// 選中之後的回撥
onItemSelectedListener:
(item, index, context) {
setState(() {
selectedIndex = index;
});
}),
)),
Padding(
padding: EdgeInsets.only(right: 8),
child: _getDropdownIcon(),
)
],
)),
)),
]),
],
),
],
),
),
),
複製程式碼
8.selection_callback_example_bar
這個主要是條形統計圖
- 效果演示
- 核心程式碼
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.blueAccent)),
width: double.infinity,
height: ScreenUtil.getInstance().setHeight(500),
child: charts.BarChart(
//通過下面獲取資料傳入
ChartFlutterBean.createSampleData(),
//配置項,以及設定觸發的函式
selectionModels: [
charts.SelectionModelConfig(
type: charts.SelectionModelType.info,
changedListener: _onSelectionChanged,
)
],
),
),
_showMask(flag, 4.0)
],
複製程式碼
9.sliver_demo
這個主要是滑動效果,Sliver,這個滑動效果,比 ta 其他的兄弟家族要順滑很多
- 沒有使用第三方包
- 演示效果
- 核心程式碼
SliverPadding(
padding: const EdgeInsets.all(8.0),
sliver: new SliverGrid(
//Grid
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, //Grid按兩列顯示
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 4.0,
),
delegate: new SliverChildBuilderDelegate(
(BuildContext context, int index) {
//建立子widget
return Container(
padding: EdgeInsets.all(5),
width: 200,
height: 200,
child: Image.network('https://yayxs.github.io/head.jpg'));
},
childCount: 27,
),
),
),
//List
new SliverFixedExtentList(
itemExtent: 50.0,
delegate:
new SliverChildBuilderDelegate((BuildContext context, int index) {
//建立列表項
return new Container(
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: new Text('list item $index'),
);
}, childCount: 50 //50個列表項
),
),
複製程式碼
10.spider_chart_demo
這個主要是圖表相關的,類似於一個蜘蛛一樣的雷達圖
- 第三方包 spider_chart: ^0.1.4
- 演示效果
- 核心程式碼
child: Container(
width: 300,
height: 300,
child: SpiderChart(
data: [49.98, 24.4, 8.2, 41.47, 15.29],
maxValue: 100,
colors: <Color>[
Colors.red,
Colors.orange,
Colors.green,
Colors.yellow,
Colors.indigo,
],
labels: <String>[
"吃",
"喝",
"玩",
"樂",
"學",
]),
),
複製程式碼
11.url_launcher_demo
這個主要是外部連線到其他 app,也就是說在 Flutter 應用內跳轉到瀏覽器,打電話,發簡訊等
- 第三方包 url_launcher: ^5.2.7
- 演示效果
- 核心程式碼
class _TestState extends State<Test> {
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
RaisedButton(child: Text('我是一個按鈕'), onPressed: _launchURL)
],
));
}
_launchURL() async {
String url = 'https://www.baidu.com/s?wd=';
String keyWords = '中';
String urlParams = '$url$keyWords';
print('${urlParams}');
if (await canLaunch(urlParams)) {
await launch(urlParams);
} else {
throw 'Could not launch $url';
}
}
}
複製程式碼
4. 寫在最後
很高興你能看到這兒,我也是今天看了下,Flutter.dev
官網,其版本更新到1.12了,希望加油,最後也期待都有收穫。我還想對你說
Although it is over, thank you