## 布局
#### 层次布局中使用定位元素Postiied
```plain
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 声明层叠布局变量
var stack = new Stack(
// 子元素的对齐方式,最小是0 ,最大是1,中间就是0.5
alignment: const FractionalOffset(0.5,0.8),
children:
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,
),
//当子元素的个数多于两个的时候使用绝对定位
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) {
// 声明一个卡片布局
var card = new Card(
child: Column(
children:
ListTile(
title: Text('吉林省吉林市'),
subtitle: Text('哟呵:134559504'),
leading: new Icon(Icons.account_box),
),
// 加上分割线
new Divider(),
ListTile(
title: Text('娜娜姐分饿哦服务'),
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,
),
),
);
}
}
```
#### 导航父子页面的跳转返回
```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('导航页面'),
),
body:Center(
child: RaisedButton(
child: Text('查看详情页'),
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('商品详情页'),
),
body: RaisedButton(
child:Text ('返回'),
onPressed: () {
Navigator.pop(context);
},
),
);
}
}
```
#### 瀑布流布局
```plain
///@description 贴子列表页
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(
/// 设置子元素的宽度
crossAxisCount: 4,
/// 设置子元素的个数
itemCount: 8,
itemBuilder: (BuildContext context, int index) => new Container(
/// 设置子元素的背景色
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),
/// 设置上下间距
mainAxisSpacing: 4.0,
/// 设置左右间距
crossAxisSpacing: 4.0,
),
);
}
}
```
## 小emo
#### 给图片加上圆角
```plain
// 设置图片圆角
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
item.cover,
/// 图片自适应设备的宽度
width: MediaQuery.of(context).size.width / 1.06,
height: 165,
fit: BoxFit.cover,
/// 给图片设置圆角
),
),
```
#### 给图片加上圆角2
```plain
// 给标签设置圆角
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(10)),
color: Colors.pink),
```
#### 控制不换行显示文本
```plain
child: RichText(
/// 控制不换行
softWrap: false,
text: TextSpan(
Xtext: '报名 ${item.signUp}',
style: TextStyle(
color: Colors.blue[700],
fontSize: Constant.font_sp16)),
),
```
#### 过度颜色的文字
```plain
body: Builder(
builder: (BuildContext context) {
RenderBox box = context.findRenderObject();
final Shader linearGradient = LinearGradient(
colors:
).createShader(
Rect.fromLTWH(2.0, 1.0, box?.size?.width, box?.size?.height));
return Text(
'专注分享Flutter技术和应用实战',
style: new TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
foreground: Paint()..shader = linearGradient),
);
},
)
```
#### 带前后置标签的文本
```plain
// 带前后置标签的文本
body: RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children:
WidgetSpan(
child: Container(
margin: EdgeInsets.only(right: 10),
// 标签中的内边距
padding: EdgeInsets.symmetric(horizontal: 30),
// 给标签设置圆角
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(10)),
color: Colors.pink),
child: Text(
'判断题',
// 标签中字体的颜色
style: TextStyle(color: Colors.white),
),
),
),
TextSpan(text: '泡沫灭火器可用于带点灭火')
]),
));
```
![图片](https://uploader.shimo.im/f/l7m1xqmXbm4qGLO4.png!thumbnail)
#### 图片自适应设备的宽度
```plain
/// 图片自适应设备的宽度
width: MediaQuery.of(context).size.width / 1.0
```
#### 设置状态栏白底黑字
```plain
// 设置状态栏,白底黑字
brightness: Brightness.light,
```
#### 自定义悬浮按钮
![图片](https://uploader.shimo.im/f/ZQX5dzDwGBjyJgxi.png!thumbnail)
![图片](https://uploader.shimo.im/f/ChCSY4bWtcE11nxB.png!thumbnail)
#### 设置Container的圆角
![图片](https://uploader.shimo.im/f/xlg9TbGoRCZ1VDmW.png!thumbnail)
#### 解析html文档
```plain
添加依赖
# 富文本解析
flutter_html: ^1.0.0-pre.1
导入包
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:
child: Html(
data: choicenessList['sourceContent']
// data: htmlStr1,
),
),
),
```
#### 设置水平和垂直方向间距
```plain
margin: EdgeInsets.symmetric(horizontal: 4, vertical: 3),
```
## 遇到的问题
#### 1flutter打包之后无法访问接口数据
1.添加网络权限
AndroidManifest文件里 加了一行 use开头的
![图片](https://uploader.shimo.im/f/0wzKwpTtYmwtIUub.png!thumbnail)
![图片](https://uploader.shimo.im/f/oo1MvX2UThoUXR3c.png!thumbnail)
2添加ndk支持库
![图片](https://uploader.shimo.im/f/J0w4TsHYU4szXuOp.png!thumbnail)
#### 3.项目中无法访问Dio网络请求包,加了依赖的情况下也找不到Dio(),
解决的办法,找到本地flutter文件夹删掉其中的.pub-cache再项目中重新跑一下flutter pub get
#### Flutter中setState导致的内存泄漏——setState() called after dispose()
解决的额办法
我们的错误原因是异步消息未返回,所以在`setState`方法之前调用`mouted`属性进行判断即可。
```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
WebViewController _controller;
String _title = "webview";
double _height = 500.0;
double _width = 100;
String htmlStr1 = """""";
String htmlStr = """
.a{
text-align: center;
}
""";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("$_title"),
backgroundColor: Colors.black,
),
body: ListView(
children:
SizedBox(
width: _width,
height: _height,
child: Card(
child: WebView(
//JS执行模式 是否允许JS执行
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (controller) {
_controller = controller;
controller.loadUrl(Uri.dataFromString(htmlStr,
mimeType: 'text/html',
encoding: Encoding.getByName('utf-8'))
.toString());
},
onPageFinished: (url) {
//调用JS得到实际高度
_controller
.evaluateJavascript(
"document.documentElement.clientHeight;")
.then((result) {
setState(() {
_height = double.parse(result);
print("高度$_height");
});
});
},
navigationDelegate: (NavigationRequest request) {
if (request.url.startsWith("myapp://")) {
print("即将打开 ${request.url}");
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
javascriptChannels:
JavascriptChannel(
name: "share",
onMessageReceived: (JavascriptMessage message) {
print("参数: ${message.message}");
}),
].toSet(),
)),
)
],
));
}
}
```
## test
#### 判断当前用户是否登录状态如果没有登录跳转到登录页面
需要判断的页面中
![图片](https://uploader.shimo.im/f/o0Q0QlcX7la8X3uV.png!thumbnail)
![图片](https://uploader.shimo.im/f/83g9ObZ9ONYyOUX4.png!thumbnail)
![图片](https://uploader.shimo.im/f/wGDhlIqj0yOIjTid.png!thumbnail)
![图片](https://uploader.shimo.im/f/45QvPxK3ujTCHhlv.png!thumbnail)
统一封装的判断是否登录
![图片](https://uploader.shimo.im/f/kLpZxXsKDUmfnTMU.png!thumbnail)
路由管理
![图片](https://uploader.shimo.im/f/8cdD7ijIgzFs65O1.png!thumbnail)
//对应的页面
body: pages[currentIndex]);
## android模拟器启动快捷方式脚本
D:\tools\android-sdk-windows\emulator\emulator.exe -netdelay none -netspeed full -avdPixel_XL_API_30
注:Pixel_XL_API_30是模拟器的名字,之前的是路径