## 布局
#### 層次布局中使用定位元素Postiied
```plain
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
? @override
? Widget build(BuildContext context) {
? ? // 聲明層疊布局變量
? ? var stack = new Stack(
? ? ? // 子元素的對(duì)齊方式,最小是0 ,最大是1,中間就是0.5
? ? ? alignment: const FractionalOffset(0.5,0.8),
? ? ? children: <Widget>[
? ? ? ? new CircleAvatar(
? ? ? ? ? backgroundImage: new NetworkImage('https://public-cdn-oss.mosoteach.cn/mssvc/cover/2020/07/ac0d8db18d681dacaa6471ecb6f677cd.png?x-oss-process=style/s100x100'),
? ? ? ? ? radius: 100.0,
? ? ? ? ),
? ? ? //當(dāng)子元素的個(gè)數(shù)多于兩個(gè)的時(shí)候使用絕對(duì)定位
? ? ? ? new Positioned(
? ? ? ? ? ? top: 10.0,
? ? ? ? ? ? left: 10.0,
? ? ? ? ? ? child: new Text('定位使用')
? ? ? ? ),
? ? ? ? new Positioned(
? ? ? ? ? ? top: 70.0,
? ? ? ? ? ? left: 40.0,
? ? ? ? ? ? child: new Text('定位2'))
? ? ? ],
? ? );
? ? return MaterialApp(
? ? ? title: 'Row Widget Demo',
? ? ? home: Scaffold(
? ? ? ? appBar: new AppBar(title: new Text('垂直方向布局')),
? ? ? ? body: Center(
? ? ? ? ? // 引入變量
? ? ? ? ? child: stack,
? ? ? ? ),
? ? ? ),
? ? );
? }
}
```
#### 卡片布局組件
```plain
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
? @override
? Widget build(BuildContext context) {
? // 聲明一個(gè)卡片布局
? ? var card =? new Card(
? ? ? child: Column(
? ? ? ? children: <Widget>[
? ? ? ? ? ListTile(
? ? ? ? ? ? title: Text('吉林省吉林市'),
? ? ? ? ? ? subtitle: Text('喲呵:134559504'),
? ? ? ? ? ? leading: new Icon(Icons.account_box),
? ? ? ? ? ),
? ? ? ? ? // 加上分割線
? ? ? ? ? new Divider(),
? ? ? ? ? ListTile(
? ? ? ? ? ? title: Text('娜娜姐分餓哦服務(wù)'),
? ? ? ? ? ? subtitle: Text('fegregrefew'),
? ? ? ? ? ? leading: new Icon(Icons.account_box),
? ? ? ? ? ),
? ? ? ? ? new Divider(),
? ? ? ? ? ListTile(
? ? ? ? ? ? title: Text('defief referF'),
? ? ? ? ? ? subtitle: Text('defewfe'),
? ? ? ? ? ? leading: new Icon(Icons.account_box),
? ? ? ? ? )
? ? ? ? ],
? ? ? ),
? ? );
? ? return MaterialApp(
? ? ? title: 'Row Widget Demo',
? ? ? home: Scaffold(
? ? ? ? appBar: new AppBar(title: new Text('垂直方向布局')),
? ? ? ? body: Center(
? ? ? ? ? // 引入變量
? ? ? ? ? child: card,
? ? ? ? ),
? ? ? ),
? ? );
? }
}
```
#### 導(dǎo)航父子頁(yè)面的跳轉(zhuǎn)返回
```plain
import 'package:flutter/material.dart';
void main() => (runApp(MyApp()));
class MyApp extends StatelessWidget {
? @override
? Widget build(BuildContext context) {
? ? return MaterialApp(
? ? ? home: FirstScrreen(),
? ? );
? }
}
class FirstScrreen extends StatelessWidget {
? @override
? Widget build(BuildContext context) {
? ? return Scaffold(
? ? ? appBar: AppBar(
? ? ? ? title: Text('導(dǎo)航頁(yè)面'),
? ? ? ),
? ? ? ? body:Center(
? ? ? ? child: RaisedButton(
? ? ? ? ? child: Text('查看詳情頁(yè)'),
? ? ? ? ? onPressed: () {
? ? ? ? ? ? Navigator.push(context, MaterialPageRoute(
? ? ? ? ? ? ? ? builder: (context) => new SecondScreen()));
? ? ? ? ? },
? ? ? ? ),
? ? ? ? )
? ? );
? }
}
class SecondScreen extends StatelessWidget{
? @override
? Widget build(BuildContext context) {
? ? // TODO: implement build
? ? return Scaffold(
? ? ? appBar: AppBar(
? ? ? ? title: Text('商品詳情頁(yè)'),
? ? ? ),
? ? ? body: RaisedButton(
? ? ? ? child:Text ('返回'),
? ? ? ? onPressed: () {
? ? ? ? ? Navigator.pop(context);
? ? ? ? },
? ? ? ),
? ? );
? }
}
```
#### 瀑布流布局
```plain
///@description?貼子列表頁(yè)
import?'package:flutter/material.dart';
import?'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
class?Choiceness?extends?StatelessWidget?{
??@override
??Widget?build(BuildContext?context)?{
????return?Container(
??????height:?800,
??????padding:?EdgeInsets.only(top:?0,?left:?8,?right:?8),
??????child:?new?StaggeredGridView.countBuilder(
????????///?設(shè)置子元素的寬度
????????crossAxisCount:?4,
????????///?設(shè)置子元素的個(gè)數(shù)
????????itemCount:?8,
????????itemBuilder:?(BuildContext?context,?int?index)?=>?new?Container(
????????????///?設(shè)置子元素的背景色
????????????color:?Colors.green,
????????????child:?new?Center(
??????????????child:?new?CircleAvatar(
????????????????backgroundColor:?Colors.white,
????????????????child:?new?Text('$index'),
??????????????),
????????????)),
????????staggeredTileBuilder:?(int?index)?=>
????????????new?StaggeredTile.count(2,?index.isEven???3?:?2),
????????///?設(shè)置上下間距
????????mainAxisSpacing:?4.0,
????????///?設(shè)置左右間距
????????crossAxisSpacing:?4.0,
??????),
????);
??}
}
```
## 小emo
#### 給圖片加上圓角
```plain
//?設(shè)置圖片圓角
ClipRRect(
borderRadius:?BorderRadius.circular(8),
child:?Image.network(
item.cover,
///?圖片自適應(yīng)設(shè)備的寬度
width:?MediaQuery.of(context).size.width?/?1.06,
height:?165,
fit:?BoxFit.cover,
///?給圖片設(shè)置圓角
),
),
```
#### 給圖片加上圓角2
```plain
???????//?給標(biāo)簽設(shè)置圓角
????????????????????decoration:?BoxDecoration(
????????????????????????shape:?BoxShape.rectangle,
????????????????????????borderRadius:?BorderRadius.all(Radius.circular(10)),
??????????????????????color:?Colors.pink),
```
#### 控制不換行顯示文本
```plain
??child:?RichText(
??????????///??控制不換行
???????????softWrap:?false,
????????????text:?TextSpan(
??????????? Xtext:?'報(bào)名?${item.signUp}',
????????????style:?TextStyle(
?????????????color:?Colors.blue[700],
?????????????fontSize:?Constant.font_sp16)),
??????????????????????????????),
```
#### 過(guò)度顏色的文字
```plain
?body:?Builder(
??????????builder:?(BuildContext?context)?{
????????????RenderBox?box?=?context.findRenderObject();
????????????final?Shader?linearGradient?=?LinearGradient(
??????????????colors:?<Color>[Colors.purple[300],?Colors.blue],
????????????).createShader(
????????????????Rect.fromLTWH(2.0,?1.0,?box?.size?.width,?box?.size?.height));
????????????return?Text(
??????????????'專注分享Flutter技術(shù)和應(yīng)用實(shí)戰(zhàn)',
??????????????style:?new?TextStyle(
??????????????????fontSize:?18.0,
??????????????????fontWeight:?FontWeight.bold,
??????????????????foreground:?Paint()..shader?=?linearGradient),
????????????);
??????????},
????????)
```
#### 帶前后置標(biāo)簽的文本
```plain
??//?帶前后置標(biāo)簽的文本
???????body:?RichText(
??????????text:?TextSpan(
??????????????style:?DefaultTextStyle.of(context).style,
??????????????children:?<InlineSpan>[
????????????????WidgetSpan(
??????????????????child:?Container(
????????????????????margin:?EdgeInsets.only(right:?10),
????????????????????//?標(biāo)簽中的內(nèi)邊距
????????????????????padding:?EdgeInsets.symmetric(horizontal:?30),
????????????????????//?給標(biāo)簽設(shè)置圓角
????????????????????decoration:?BoxDecoration(
????????????????????????shape:?BoxShape.rectangle,
????????????????????????borderRadius:?BorderRadius.all(Radius.circular(10)),
????????????????????????color:?Colors.pink),
????????????????????child:?Text(
??????????????????????'判斷題',
??????????????????????//?標(biāo)簽中字體的顏色
??????????????????????style:?TextStyle(color:?Colors.white),
????????????????????),
??????????????????),
????????????????),
????????????????TextSpan(text:?'泡沫滅火器可用于帶點(diǎn)滅火')
??????????????]),
????????));
```

#### 圖片自適應(yīng)設(shè)備的寬度
```plain
? ? ? ? ? /// 圖片自適應(yīng)設(shè)備的寬度
? ? ? ? ? ? ? width: MediaQuery.of(context).size.width / 1.0
```
#### 設(shè)置狀態(tài)欄白底黑字
```plain
// 設(shè)置狀態(tài)欄,白底黑字
? brightness: Brightness.light,
```
#### 自定義懸浮按鈕


#### 設(shè)置Container的圓角

#### 解析html文檔
```plain
添加依賴
#?富文本解析
??flutter_html:?^1.0.0-pre.1
導(dǎo)入包
import?'package:flutter_html/flutter_html.dart';
引用
Container(
padding:?EdgeInsets.only(top:?4),
width:?MediaQuery.of(context).size.width,
alignment:?Alignment.center,
child:?Expanded(
//?children:?<Widget>[Text(choicenessList['sourceContent'])],
child:?Html(
data:?choicenessList['sourceContent']
//?data:?htmlStr1,
),
),
),
```
#### 設(shè)置水平和垂直方向間距
```plain
?margin:?EdgeInsets.symmetric(horizontal:?4,?vertical:?3),
```
## 遇到的問(wèn)題
#### 1flutter打包之后無(wú)法訪問(wèn)接口數(shù)據(jù)
1.添加網(wǎng)絡(luò)權(quán)限
AndroidManifest文件里 加了一行 use開(kāi)頭的


2添加ndk支持庫(kù)

#### 3.項(xiàng)目中無(wú)法訪問(wèn)Dio網(wǎng)絡(luò)請(qǐng)求包,加了依賴的情況下也找不到Dio(),
解決的辦法,找到本地flutter文件夾刪掉其中的.pub-cache再項(xiàng)目中重新跑一下flutter pub get
#### Flutter中setState導(dǎo)致的內(nèi)存泄漏——setState() called after dispose()
解決的額辦法
我們的錯(cuò)誤原因是異步消息未返回,所以在`setState`方法之前調(diào)用`mouted`屬性進(jìn)行判斷即可。
```plain
? if(mounted){
? ? ? ? setState(() {
? ? ? ? ? _listData.addAll(list);
? ? ? }
```
## WebView的小demo
```plain
import?'package:flutter/material.dart';
import?'package:flutter_learning/test.dart';
import?'package:webview_flutter/webview_flutter.dart';
///?字符集編碼
import?'dart:convert';
void?main()?{
runApp(MyApp());
}
class?MyApp?extends?StatelessWidget?{
//?This?widget?is?the?root?of?your?application.
@override
Widget?build(BuildContext?context)?{
return?MaterialApp(
title:?'Flutter?Demo',
theme:?ThemeData(
primarySwatch:?Colors.blue,
visualDensity:?VisualDensity.adaptivePlatformDensity,
),
home:?Scaffold(
body:?Center(
child:?WebViewPage(),
),
),
);
}
}
class?WebViewPage?extends?StatefulWidget?{
@override
_WebViewPageState?createState()?=>?_WebViewPageState();
}
class?_WebViewPageState?extends?State<WebViewPage>?{
WebViewController?_controller;
String?_title?=?"webview";
double?_height?=?500.0;
double?_width?=?100;
String?htmlStr1?=?"""""";
String?htmlStr?=?"""<!DOCTYPE?html>
<html>
<head>
<meta?charset="utf-8">
<title>用戶注冊(cè)表單</title>
<style?type="text/css">
.a{
text-align:?center;
}
</style>
</head>
<body>
<center>
<form?class="a">
<h1>用戶注冊(cè)</h1>
<pre>
<br?/>姓????名:<input?type="text"?id="filed1">
<br?/>性????別:<input?type="radio"?name="sex"?value="female">男???????????<input?type="radio"?name="sex"?value="female">女
<br?/>年????齡:<input?type="text"?id="filed2">
<br?/>聯(lián)系電話:<input?type="text"?id="filed3">
<br?/>電子郵件:<input?type="text"?id="filed4">
<br?/>聯(lián)系地址:<input?type="text"?id="filed5">
<br?/>
<input?type="submit"?class="feedback"?value="提交">????????????<input?type="submit"?class="feedback"?value="取消">
</form>
</pre>
</center>
</body>
</html>
""";
@override
Widget?build(BuildContext?context)?{
return?Scaffold(
appBar:?AppBar(
title:?Text("$_title"),
backgroundColor:?Colors.black,
),
body:?ListView(
children:?<Widget>[
SizedBox(
width:?_width,
height:?_height,
child:?Card(
child:?WebView(
//JS執(zhí)行模式?是否允許JS執(zhí)行
javascriptMode:?JavascriptMode.unrestricted,
onWebViewCreated:?(controller)?{
_controller?=?controller;
controller.loadUrl(Uri.dataFromString(htmlStr,
mimeType:?'text/html',
encoding:?Encoding.getByName('utf-8'))
.toString());
},
onPageFinished:?(url)?{
//調(diào)用JS得到實(shí)際高度
_controller
.evaluateJavascript(
"document.documentElement.clientHeight;")
.then((result)?{
setState(()?{
_height?=?double.parse(result);
print("高度$_height");
});
});
},
navigationDelegate:?(NavigationRequest?request)?{
if?(request.url.startsWith("myapp://"))?{
print("即將打開(kāi)?${request.url}");
return?NavigationDecision.prevent;
}
return?NavigationDecision.navigate;
},
javascriptChannels:?<JavascriptChannel>[
JavascriptChannel(
name:?"share",
onMessageReceived:?(JavascriptMessage?message)?{
print("參數(shù):?${message.message}");
}),
].toSet(),
)),
)
],
));
}
}
```
## test
#### 判斷當(dāng)前用戶是否登錄狀態(tài)如果沒(méi)有登錄跳轉(zhuǎn)到登錄頁(yè)面
需要判斷的頁(yè)面中




統(tǒng)一封裝的判斷是否登錄

路由管理

//對(duì)應(yīng)的頁(yè)面
body: pages[currentIndex]);
## android模擬器啟動(dòng)快捷方式腳本
D:\tools\android-sdk-windows\emulator\emulator.exe -netdelay none -netspeed full -avdPixel_XL_API_30
注:Pixel_XL_API_30是模擬器的名字,之前的是路徑