Flutter使用小技巧三(持续更新)
Flutter使用小技巧三(持续更新...)
- Row 直接包裹 TextField 异常:BoxConstraints forces an infinite width
- Expanded、Flexible区别
- Android无法访问http
- IOS无法访问http
- 获取当前系统Locale
- ClipRRect 圆角无效
- 箭头函数不要写多行,否则报错
- StatefulWidget 构造传参数
- No MediaQuery ancestor could be found?
- 打开一个下载的Flutter module没有android或者.Android文件运行报AndroidManifest.xml could not be found.
- Flutter Android应用启动白屏的解决方案
- Flutter 输入框导致Column溢出
- Column溢出
- Cannot use this MethodChannel before the binary messenger has been initialized
- 解决flutter在iOS14+真机上的运行问题
- 设置BottomNavigationBar超过3个后,不显示颜色
- 多个main函数选择性打包
- Mac 打包 flutter项目 ipa 打包步骤
- 输入框搜索请求限制
- InWell、RaisedButton去除点击效果
- 去除ListView、SingleChildScrollView、CustomScrollView边界水波纹效果
- 空间适配FittedBox
- GridView item设置高度
- 条件导入
Row 直接包裹 TextField 异常:BoxConstraints forces an infinite width
//使用Flexible包裹
Row(
children: <Widget>[
Flexible(
child: new TextField(),
),
],
),
Expanded、Flexible区别
Flexible是一个控制Row、Column、Flex等子组件如何布局的组件。
Flexible组件可以使Row、Column、Flex等子组件在主轴方向有填充可用空间的能力(例如,Row在水平方向,Column在垂直方向),但是它与Expanded组件不同,它不强制子组件填充可用空间
Row、Column、Flex会被Expanded撑开,充满主轴可用空间。
Expanded
代码
body: new Row(
children: <Widget>[
new RaisedButton(
onPressed: () {
print('点击红色按钮事件');
},
color: const Color(0xffcc0000),
child: new Text('红色按钮'),
),
new Expanded(
flex: 1,
child: new RaisedButton(
onPressed: () {
print('点击黄色按钮事件');
},
color: const Color(0xfff1c232),
child: new Text('黄色按钮'),
),
),
new RaisedButton(
onPressed: () {
print('点击粉色按钮事件');
},
color: const Color(0xffea9999),
child: new Text('粉色按钮'),
),
]
),
Flexible
代码
body: new Row(
children: <Widget>[
new RaisedButton(
onPressed: () {
print('点击红色按钮事件');
},
color: const Color(0xffcc0000),
child: new Text('红色按钮'),
),
new Flexible(
flex: 1,
child: new RaisedButton(
onPressed: () {
print('点击黄色按钮事件');
},
color: const Color(0xfff1c232),
child: new Text('黄色按钮'),
),
),
new RaisedButton(
onPressed: () {
print('点击粉色按钮事件');
},
color: const Color(0xffea9999),
child: new Text('粉色按钮'),
),
]
),
Android无法访问http
android11以及以后为了安全Android系统禁用了http的网络请求
需进行如下配置
- 创建
network_security_config.xml. (res/xml) - 配置
<application android:networkSecurityConfig="@xml/network_security_config">...
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
IOS无法访问http
在./ios/Runner/Info.plist文件中添加如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
...
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>
获取当前系统Locale
import 'dart:ui';
window.locale
ClipRRect 圆角无效
问题代码:
_item(index) {
return ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Container(
margin: const EdgeInsets.all(8.0),
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
height: 120,
child: Center(
child: Text(
index.toString(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18),
),
),
),
);
分析:由于ClipRRect内部被Container设置了margin导致的,我们将margin去除就会看到圆角,如果非要加个margin则需要外层再包裹个Container,并且color只能有最外层提供。
_item(index) {
return Container(
margin: const EdgeInsets.all(8.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Container(
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
height: 120,
child: Center(
child: Text(
index.toString(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18),
),
),
),
),
);
}
箭头函数不要写多行,否则报错
StatefulWidget 构造传参数
class UserTextField extends StatefulWidget {
final TextEditingController? controller;
final Widget? icon;
final String? hintText;
final bool obscureText;
const UserTextField(
{Key? key,
this.controller,
this.icon,
this.hintText,
this.obscureText = false})
: super(key: key);
@override
//如果State构造加入参数会提示警告信息:Don't put any logic in createState
_UserTextFieldState createState() => _UserTextFieldState();
}
解决办法:_UserTextFieldState无需在构造中添加参数
- 只需要使用
widget.xx调用即可
class _UserTextFieldState extends State<UserTextField> {
@override
Widget build(BuildContext context) {
return Container(
height: 56.0,
margin: const EdgeInsets.only(top: 20.0),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(7.0), color: Colors.white),
padding: const EdgeInsets.only(left: 20.0),
child: TextField(
controller: widget.controller,
maxLines: 1,
//是否是密码
obscureText: widget.obscureText,
style: const TextStyle(
fontSize: 17.0,
fontFamily: 'QuicksandMedium',
color: Color(0xFF4b4b4b)),
decoration: InputDecoration(
border: InputBorder.none,
icon: widget.icon,
hintText: widget.hintText,
),
),
);
}
}
No MediaQuery ancestor could be found?
No MediaQuery ancestor could be found?
void main() => runApp(const MaterialApp(home: HomePage()));
打开一个下载的Flutter module没有android或者.Android文件运行报AndroidManifest.xml could not be found.
- 切换到当前目录
执行flutter create ..表示输出到当前目录
Flutter Android应用启动白屏的解决方案
打开Android主项目 android工程AndroidManifest.xml
在.Mainactivity下新增
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@mipmap/gradient_bg"/>
Flutter 输入框导致Column溢出
return Scaffold(
resizeToAvoidBottomInset: false,
Column溢出
嵌套SingleChildScrollView
body: SingleChildScrollView(
child: Column(
Cannot use this MethodChannel before the binary messenger has been initialized
channel还未初始化就使用了相应功能,比如SharedPreferences
void main() async {
WidgetsFlutterBinding.ensureInitialized();//添加
await ApplicationRouter.setupRouter();
AppManager.getInstance().isLogin =
await SpUtils.getBool(AppConstants.spKeyLogin);
runApp(const MyApp());
}
解决flutter在iOS14+真机上的运行问题
flutter run --release
设置BottomNavigationBar超过3个后,不显示颜色
BottomNavigationBar设置如下属性,这是因为超过3个后type被设置为了BottomNavigationBarType.shifting
type: BottomNavigationBarType.fixed
源码解析:
// Computes the default value for the [type] parameter.
//
// If type is provided, it is returned. Next, if the bottom navigation bar
// theme provides a type, it is used. Finally, the default behavior will be
// [BottomNavigationBarType.fixed] for 3 or fewer items, and
// [BottomNavigationBarType.shifting] is used for 4+ items.
BottomNavigationBarType get _effectiveType {
return widget.type
?? BottomNavigationBarTheme.of(context).type
?? (widget.items.length <= 3 ? BottomNavigationBarType.fixed : BottomNavigationBarType.shifting);
}
多个main函数选择性打包
flutter build apk -t lib/main_dev.dart
flutter build ipa --release -t lib/main_sit.dart
Mac 打包 flutter项目 ipa 打包步骤
1)首先要确认flutter的环境变量已经配置完好
2)在android studio里面更新代码
3)使用 flutter build ios进行打包
4)打包完成以后使用命令直接进入iphoneos文件夹,由于本身android studio 终端就是在项目下面了
,所以就直接 先 cd build 再 cd iphoneos
当看见终端的前面变成 iphoneos git(master):
5)使用命令 rm -rf Payload
6)最后使用命令
mkdir Payload && mv Runner.app Payload && zip -r Payload.zip Payload && mv Payload.zip Payload.ipa
输入框搜索请求限制
Timer? timer;
void search(Function function, {duration = 500}) {
timer?.cancel();
timer = Timer(Duration(milliseconds: duration), () {
function.call();
timer = null;
});
}
InWell、RaisedButton去除点击效果
InkWell(
onTap: () {},
child: Text('InkWell 组件'),
highlightColor: Colors.transparent, // 透明色
splashColor: Colors.transparent, // 透明色
),
RaisedButton(
onPressed: () {},
child: Text('按钮'),
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
highlightElevation: 0,
elevation: 0,
),
去除ListView、SingleChildScrollView、CustomScrollView边界水波纹效果
- 自定义ScrollBehavior
class AppScrollBehavior extends ScrollBehavior {
@override
Widget buildOverscrollIndicator(
BuildContext context, Widget child, ScrollableDetails details) {
switch (getPlatform(context)) {
case TargetPlatform.linux:
case TargetPlatform.macOS:
case TargetPlatform.windows:
case TargetPlatform.iOS:
return child;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
return GlowingOverscrollIndicator(
showLeading: false,
showTrailing: false,
child: child,
axisDirection: details.direction,
color: Theme.of(context).colorScheme.secondary);
}
}
}
- 使用:ScrollConfiguration控件包裹
body: ScrollConfiguration(
behavior: AppScrollBehavior(),
child: CustomScrollView(
controller: _controller,
slivers: [
_title(),
_searchStickBar(context),
_exploreList(context),
],
),
)
空间适配FittedBox
源码
const FittedBox({
Key? key,
this.fit = BoxFit.contain, // 适配方式
this.alignment = Alignment.center, //对齐方式
this.clipBehavior = Clip.none, //是否剪裁
Widget? child,
})
使用Text仅显示一行,超出后自动适配大小
Padding(
padding: const EdgeInsets.all(10),
child: FittedBox(
child: Row(children: [
Text('wuxinxi' * 13,style:const TextStyle(fontSize: 18),)
]),
)),
GridView item设置高度
import 'package:flutter/rendering.dart';
///
/// @date: 2022/5/22 11:58
/// @author: Tangren
/// @remark:
///
class SliverGridDelegateWithFixedCrossAxisCountAndFixedHeight
extends SliverGridDelegate {
/// Creates a delegate that makes grid layouts with a fixed number of tiles in
/// the cross axis.
///
/// All of the arguments must not be null. The `mainAxisSpacing` and
/// `crossAxisSpacing` arguments must not be negative. The `crossAxisCount`
/// and `childAspectRatio` arguments must be greater than zero.
const SliverGridDelegateWithFixedCrossAxisCountAndFixedHeight({
required this.crossAxisCount,
this.mainAxisSpacing = 0.0,
this.crossAxisSpacing = 0.0,
this.height = 56.0,
}) : assert(crossAxisCount > 0),
assert(mainAxisSpacing >= 0),
assert(crossAxisSpacing >= 0),
assert(height > 0);
/// The number of children in the cross axis.
final int crossAxisCount;
/// The number of logical pixels between each child along the main axis.
final double mainAxisSpacing;
/// The number of logical pixels between each child along the cross axis.
final double crossAxisSpacing;
/// The height of the crossAxis.
final double height;
bool _debugAssertIsValid() {
assert(crossAxisCount > 0);
assert(mainAxisSpacing >= 0.0);
assert(crossAxisSpacing >= 0.0);
assert(height > 0.0);
return true;
}
@override
SliverGridLayout getLayout(SliverConstraints constraints) {
assert(_debugAssertIsValid());
final double usableCrossAxisExtent =
constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1);
final double childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount;
final double childMainAxisExtent = height;
return SliverGridRegularTileLayout(
crossAxisCount: crossAxisCount,
mainAxisStride: childMainAxisExtent + mainAxisSpacing,
crossAxisStride: childCrossAxisExtent + crossAxisSpacing,
childMainAxisExtent: childMainAxisExtent,
childCrossAxisExtent: childCrossAxisExtent,
reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection),
);
}
@override
bool shouldRelayout(
SliverGridDelegateWithFixedCrossAxisCountAndFixedHeight oldDelegate) {
return oldDelegate.crossAxisCount != crossAxisCount ||
oldDelegate.mainAxisSpacing != mainAxisSpacing ||
oldDelegate.crossAxisSpacing != crossAxisSpacing ||
oldDelegate.height != height;
}
}
条件导入
场景:当某个包只支持某个平台时(在不支持的平台下编译会不通过)
示例:
//默认导入:iframe_placeholder.dart。如果后面的条件符合则导入iframe_web
export 'iframe_placeholder.dart' if (dart.library.html) 'iframe_web';
更多推荐



所有评论(0)