Flutter

Flutter小记

2021-01-21  本文已影响0人  91阿生
0.关于AppBar中leading
如果没有leading,automaticallyImplyLeading为true,就会默认返回箭头
如果 没有leading 且为false,空间留给title
如果有leading,automaticallyImplyLeading 这个参数就无效了
1.关于ElevatedButton
image.png
ElevatedButton(
   child: Text("立即体验"),
   style: ButtonStyle(
       foregroundColor: MaterialStateProperty.all(Color(0xFF535149)),
      backgroundColor: MaterialStateProperty.all(ColorFit.mainColor),
      textStyle: MaterialStateProperty.all(TextStyle(
           fontSize: 16,
           fontWeight: FontWeight.bold
      )),
   shape: MaterialStateProperty.all(RoundedRectangleBorder(
         borderRadius: BorderRadius.circular(8)
   )),
   side: MaterialStateProperty.all(BorderSide(color: Colors.red, width: 2))),
   onPressed: () {  },
)
2.关于initState中拿不到context

解决:

Future.delayed(Duration.zero, () {
   // 延迟0秒,异步执行
   Navigator.of(context).pushReplacementNamed(MainPage.routeName);
});
3.关于PageView使用切换图片时,图片之间会有短暂的背景显示

解决:

// Implicit:含蓄的
设置属性 allowImplicitScrolling: true
4.关于取消scroller边缘弹簧效果

解决:

设置属性 physics: ClampingScrollPhysics()
5.关于设置命名路由问题

描述:设置命名路由时,主路由设置成 '/' 路由A,其他所注册的路由命名为 '/xxx'(非'/'),则系统会默认初始路由设置成由 '/'命名的路由A,这样在使用push替换路由(pushReplacementNamed)时,导航栏上会显示出返回按钮(如果此路由有导航栏),或左侧边缘可以拉回到主路由A页面。

【明明在MaterialApp中设置的initialRoute:为引导页/Launch页,但系统还是会默认初始路由为 '/'的主路由。】

解决:

可能原因注册其他路由时,其他路由的命名都为 / 开头;
例如像 引导页/Launch页 路由命名时,前面不用加 /  这样就正常了。

建议:不是经常使用到的页面,则路由命名可以不添加 /
6.关于全局消除水波纹效果,长按水波纹效果

解决:

theme: ThemeData(
   splashColor: Colors.transparent, // 全局设置点击水波纹颜色, 去除长按不放, 水波效果
   highlightColor: Colors.transparent // 全局去除点击的水波纹效果
)
7. TabBar() + TabBarView() + TabController配合
TabBar:设置标题,设置指示器样式等
TabBarView:存放标题对应的页面
TabController:使得 TabBar 与 TabBarView进行关联
选择栏.png
7. NestedScrollView 与 CustomScrollView

NestedScrollView:用来处理复杂情况下的滑动应用场景,如向上滑动视图时,要折叠隐藏一部分内容,这时候就需要使用到 NestedScrollView 与 SliverAppBar 的结合使用。

CustomScrollView:用来处理更为复杂的布局,可以将SliverAppBar,SliverList和SliverGrid SliverPadding SliverToBoxAdapter SliverPersistentHeader, SliverFillRemaining,SliverFillViewport组合等来使用。

8. 关于TextField 获取焦点 + 取消焦点
 ①、创建FocusNode实例aNode,并设置对应TextField的属性focusNode: aNode
 ②、获取焦点:FocusScope.of(context).requestFocus(aNode);
 ③、失去焦点:aNode.unfocus();
9. 回收键盘操作
SystemChannels.textInput.invokeMethod("textInput.hide");
10. 关于键盘监听操作

1、使用 with WidgetsBindingObserver 绑定监听
2、由于键盘开启后,应用视图尺寸会改变,则会被 WidgetsBindingObserver 监听到, 就会回调走此函数
@override
void didChangeMetrics() {}

@override
  void didChangeMetrics() {
    super.didChangeMetrics();

    // 当键盘开启后, 界面会往上, 这里绑定监听界面缩小
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
       // 获取底部被遮挡的高度
        double keybordHeight = MediaQuery.of(context).viewInsets.bottom;
        print("键盘高度: $keybordHeight");

        // 判断
        if (keybordHeight == 0) { // 键盘收起状态
          
        } else {
          
        }
    });
  }
11. 关于去处导航栏左侧自带返回按钮
appBar: AppBar(
   automaticallyImplyLeading: false,
),
12. 关于dart中math函数
int i = -1; //定义一个整型变量i
double j = 2.1; //定义一个小数j
  print(i.abs());//求i的绝对值,打印 ‘1’
  print(j.ceil());//求j的向上最大整数,打印'3'
  print(j.floor());//求j的向下的最大整数,打印'2'
  print(j.round());//求离j最近的整数,四舍五入,打印'2'
  print(j.truncate());//截取掉小数点取整,打印'2'
  
double j = 2.6;//验证小数位超过0.5的情形
    print(j.round());//求离j最近的整数,四舍五入,打印'3'
    print(j.truncate());//截取掉小数点取整,打印'2'
    print(j.clamp(1,3));//如果j再1-3之间则返回 j,这里打印j的值 ‘2.6’;否则返回离其最近的边界值。
    print(j.clamp(3,4));//打印‘3’,原理同上
    print(j.clamp(1,2));//打印‘2’,原理同上

//保留n 位小数:  .toStringAsFixed(n)
double j = 2.6;
String rs = j.toStringAsFixed(2) = "2.60"; 

1.toStringAsFixed(3);  // 1.000
(4321.12345678).toStringAsFixed(3);  // 4321.123
(4321.12345678).toStringAsFixed(5);  // 4321.12346
123456789012345.toStringAsFixed(3);  // 123456789012345.000
10000000000000000.toStringAsFixed(4); // 10000000000000000.0000
5.25.toStringAsFixed(0); // 5
13. 关于flutter中List既能获取value,也能获取下角标index
例子:final List<String> _titles = ['2021', '2020', '2019', '2018', '2017', '2016'];

...
tabs: titles.asMap().entries.map((item) {
   return Tab(
     child: Container(
        child: Text('$(item.value) === $item.key'),
     ),
  );
}).toList()  
14. 关于flutter中拦截导航栏返回事件
class SearchPage extends StatelessWidget {
  static const String routeName = '/search';

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        print('true:可点击返回上一个界面;false:点击返回效果被禁用');
        return false;
      },
      child: Scaffold(
        appBar: AppBar(
          title: Text(''),
        ),
        body: Center(
          child: Text(''),
        ),
      ),
    );
  }
}
15. 关于flutter中关于导航栏左侧宽度不够问题

实现如下图:


image.png
AppBar(
  elevation: 1.0,
  automaticallyImplyLeading: false,
  title: Row(
     mainAxisAlignment: MainAxisAlignment.start,
     crossAxisAlignment: CrossAxisAlignment.center,
     children: <Widget>[
            Image.asset(ImageTool.loadOthersImgPath('other_back_dark')),
            Text(widget.navTitle, style: TextStyle(
                fontSize: 14,
                color: Colors.black
              ),
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
            )
          ],
        ),
      ),
16. 关于flutter中使用 shared_preferences 出现 Unhandled Exception: Null check operator used on a null value 问题
解决:
 void main() { 
    WidgetsFlutterBinding.ensureInitialized();
 }
17. 关于flutter中查询 文本中共有多少个换行,并替换换行符为空格
/// 换行符个数:
final numLines = '\n'.allMatches(content).length + 1;

/// \n 替换成 空格" "
String rsContent = model.content.replaceAll(RegExp(r"\n"), " ");
18. 关于监听一个界面的 pop / push (WidgetsBindingObserver)
image.png

代码:

/* 用于监听 每个界面的 push pop 组件出现或者消失的回调,主要是要靠路由的监听 */
import 'package:flutter/material.dart';

class AppRouteObserver {
  //这是实际上的路由监听器
  static final RouteObserver<ModalRoute<void>> _routeObserver = RouteObserver<ModalRoute<void>>();
  //这是个单例
  static AppRouteObserver get shared => AppRouteObserver();

  static AppRouteObserver? _instance;
  factory AppRouteObserver() {
    return _instance ??= AppRouteObserver._internal();
  }

  AppRouteObserver._internal() {}
 
  RouteObserver<ModalRoute<void>> get routeObserver => _routeObserver;
}

使用:

⑴ 
。。。 with WidgetsBindingObserver

⑵  
  @override
    void initState() {
      WidgetsBinding.instance?.addObserver(this);
      super.initState();
    }

⑶ 
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    //路由订阅
    AppRouteObserver.shared.routeObserver
        .subscribe(this, ModalRoute.of(context)!);
  }

⑷ 
  @override
  void didPush() {
    //当前页面显示时
    print("哈哈didPush");
    super.didPush();
  }

  @override
  void didPushNext() {
    //当前页面 push 到另一个页面
    print("哈哈didPushNext");
    super.didPushNext();
  }

  @override
  void didPop() {
    //当前的页面被pop.
    print("哈哈didPop");
    super.didPop();
  }

  @override
  void didPopNext() {
    //另一个页面 pop 到当前页面时.
    print("哈哈didPopNext");
    super.didPopNext();
  }

⑸
  @override
  void dispose() {
    AppRouteObserver.shared.routeObserver.unsubscribe(this);
    WidgetsBinding.instance?.removeObserver(this);
    super.dispose();
  }

上一篇下一篇

猜你喜欢

热点阅读