學(xué)習(xí)Flutter的第十一天

6.2 屏幕寬高

6.2.1 系統(tǒng)提供的方法

需要在有context容器中才能使用恩伺,也就是build方法中使用

Widget build(BuildContext context){
    final size =MediaQuery.of(context).size;
    final width =size.width;
    final height =size.height; 
}

6.2.2 使用起來最簡單的方法

需要提前定義睬塌,要不然拿不到,方法報錯

import 'dart:ui';

final width = window.physicalSize.width;
final height = window.physicalSize.height;

6.3去掉debug標簽

import 'package:flutter/material.dart';
import './pages/tabs.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
    );
  }
}

6.4 PreferredSize

此控件不對其子控件施加任何約束,并且不以任何方式影響孩子的布局扎阶。

此控件對自定義AppBar.bottom和AppBar非常有用鳍徽。

PreferredSize 可以改變 appBar 的高度

Scaffold(
      // 通過 PreferredSize 來改變 appBar的高度
      appBar: PreferredSize(
        preferredSize: const Size.fromHeight(50),
        child: AppBar(
          
        ),
      ),
    )

6.5 保存頁面狀態(tài)

參考:https://blog.csdn.net/qq_14876133/article/details/125393405

AutomaticKeepAliveClientMixin緩存組件

AutomaticKeepAlive 的組件的主要作用是將列表項的根 RenderObject 的 keepAlive 按需自動標記 為 true 或 false潘拱。為了方便敘述,我們可以認為根 RenderObject 對應(yīng)的組件就是列表項的根 Widget参咙,代表整個列表項組件犀农,同時我們將列表組件的 Viewport區(qū)域 + cacheExtent(預(yù)渲染區(qū)域)稱為加載區(qū)域 :

  1. 當(dāng) keepAlive 標記為 false 時惰赋,如果列表項滑出加載區(qū)域時,列表組件將會被銷毀井赌。
  2. 當(dāng) keepAlive 標記為 true 時谤逼,當(dāng)列表項滑出加載區(qū)域后,Viewport 會將列表組件緩存起來仇穗;當(dāng)列表項進入加載區(qū)域時流部,Viewport 從先從緩存中查找是否已經(jīng)緩存,如果有則直接復(fù)用纹坐,如果沒有則重新創(chuàng)建列表項枝冀。

封裝組件代碼

import 'package:flutter/material.dart';

class KeepAliveWrapper extends StatefulWidget {
  final bool keepAlive;
  final Widget child;

  const KeepAliveWrapper({Key? key, this.keepAlive = true, required this.child})
      : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return _KeepAliveWrapperState();
  }
}

class _KeepAliveWrapperState extends State<KeepAliveWrapper>
    with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    super.build(context);
    return widget.child;
  }

  @override
  void didUpdateWidget(covariant KeepAliveWrapper oldWidget) {
    //狀態(tài)發(fā)生變化時調(diào)用
    if (oldWidget.keepAlive != widget.keepAlive) {
      //更新KeepAlive狀態(tài)
      updateKeepAlive();
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  bool get wantKeepAlive => widget.keepAlive;
}

在使用的時候,只需要把組件耘子,放到 KeepAliveWrapper 的child中即可果漾。

6.6 配置命名路由

routers.dart

import 'package:flutter/material.dart';
import '../pages/Tabs.dart';
import '../pages/search.dart';
import '../pages/first.dart';

Map routes = {
  "/": (context) => const Tabs(),
  "/s": (context, {arguments}) => Search(arguments: arguments),
  "/f": (context) => const FirstPage(),
};

//固定寫法
var onGenerateRoute = (RouteSettings settings) {
  // 統(tǒng)一處理
  final String? name = settings.name;
  final Function? pageContentBuilder = routes[name];
  if (pageContentBuilder != null) {
    if (settings.arguments != null) {
      final Route route = MaterialPageRoute(
          builder: (context) =>
              pageContentBuilder(context, arguments: settings.arguments));
      return route;
    } else {
      final Route route =
          MaterialPageRoute(builder: (context) => pageContentBuilder(context));
      return route;
    }
  }
};

main.dart

import 'package:flutter/material.dart';
import './tools/routers.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      theme: ThemeData(primarySwatch: Colors.blue),
      // home: const Tabs(),
      initialRoute: "/",
      onGenerateRoute: onGenerateRoute,
    );
  }
}

傳值

import 'package:flutter/material.dart';

class Message extends StatefulWidget {
  const Message({super.key});

  @override
  State<Message> createState() => _MessageState();
}

class _MessageState extends State<Message> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
              onPressed: () {
                Navigator.pushNamed(context, "/s",
                    arguments: {"title": "我是標題", "content": "我是內(nèi)容"});
              },
              child: const Text("跳轉(zhuǎn)搜索頁面"))
        ],
      ),
    );
  }
}

接收值

import 'package:flutter/material.dart';

class Search extends StatefulWidget {
  final Map arguments;
  const Search({super.key, required this.arguments});

  @override
  State<Search> createState() => _SearchState();
}

class _SearchState extends State<Search> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.arguments["title"]),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(widget.arguments["content"]),
          const SizedBox(height: 20),
          ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: const Text("返回上一頁"))
        ],
      ),
    );
  }
}

6.7 fluttertoast

1、打開網(wǎng)站 https://pub.dev/

2谷誓、搜索 fluttertoast

3绒障、在pubspec.yaml中,的 dependencies 中捍歪,配置 fluttertoast: ^8.0.9

4户辱、導(dǎo)入包:import 'package:fluttertoast/fluttertoast.dart';

5、使用
Fluttertoast.showToast(
        msg: "提示信息",
        toastLength: Toast.LENGTH_SHORT,    // 針對android平臺
        gravity: ToastGravity.CENTER,   // 方位
        timeInSecForIosWeb: 1,  // 提示時間
        backgroundColor: Colors.red, // 背景顏色
        textColor: Colors.white,    // 文字顏色
        fontSize: 16.0  // 字號
    );

6.8 定時器

引入包:

import 'dart:async';


var t = Timer.periodic(const Duration(seconds: 3), (timer) {
  print("定時執(zhí)行:" + DateTime.now().toString());
  // 取消定時器
  // timer.cancel;
});

// 組件銷毀的時候糙臼,取消定時器
void dispose() {
  super.dispose();
  t.cancel();
}

6.9 key

key是用來作為Widget庐镐、ElementSemanticsNode的標示,僅僅用來更新widget->key相同的小部件的狀態(tài)变逃。

主要用于組件的排序必逆,例如listview中,拖動組件,橫豎屏切換

當(dāng)你想要跨widget樹保留狀態(tài)時 , 應(yīng)該使用key.

一名眉、LocalKey有三種類型粟矿,用作diff算法的核心所在,用Element和widget進行比較

  • ValueKey 以一個數(shù)據(jù)作為Key璧针。如:數(shù)字嚷炉、字符
  • ObjectKey 以O(shè)bject對象作為Key
  • UniqueKey 可以保證Key的唯一性!(一旦使用Uniquekey那么就不存在Element復(fù)用 了L匠鳌)

二申屹、GlobalKey

  • 1、GlobalKey可以獲取到對應(yīng)的Widget的State對象隧膏!

需求:當(dāng)我們頁面內(nèi)容很多時哗讥,而需要改變的內(nèi)容只有很少的一部分且在樹的底層的時候,我們?nèi)绾稳崿F(xiàn)增量更新胞枕?

通常情況下有兩種方式杆煞,

  • 第一種是通過方法的回調(diào),去實現(xiàn)數(shù)據(jù)更新腐泻,
  • 第二種是通過GlobalKey决乎,在StatelessWidget引用StatefulWidget。
//在statelessWidget中引用statefulWidget更新UI
class GlobalKeyDemo extends StatelessWidget{
  // 1派桩、 定義GlobalKey
  final GlobalKey<_ChildPageState> _globalKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('GlobalDemo'),
      ),
      // 2构诚、給子控件設(shè)置key
      body: ChildPage(
        key: _globalKey,
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: (){
         // 3、可以通過 globalKey.currentState 來獲取子組件的屬性和方法
          _globalKey.currentState.data = 'old' + _globalKey.currentState.count.toString();
          _globalKey.currentState.count++;
          _globalKey.currentState.setState(() { });
        },
      ),
    );
  }

}

class ChildPage extends StatefulWidget{
  ChildPage({Key key}):super(key:key);

  @override
  _ChildPageState createState() => _ChildPageState();
}

class _ChildPageState extends State<ChildPage>{
  int count = 0;
  String data = 'hello Flutter';

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child: Column(
        children: <Widget>[
          Text(count.toString()),
          Text(data),
        ],
      ),
    );
  }
}

6.10 Matrix4

參考:https://blog.csdn.net/liu__520/article/details/83796784

  1. scale:縮放比例 transform: Matrix4.diagonal3Values(2, 10, 1),
  2. transform: 移動
  3. rotationZ:繞Z軸旋轉(zhuǎn)
  4. rotationX:繞X軸旋轉(zhuǎn)
  5. rotationY:繞Y軸旋轉(zhuǎn)
  6. columns:設(shè)置一個新的矩陣
  7. compose:復(fù)合平移铆惑、旋轉(zhuǎn)范嘱、縮放,形成新的狀態(tài)
  8. copy:復(fù)制一個4*4的張量(矩陣)
  9. identity:恢復(fù)初始狀態(tài)员魏,也就是4*4的單位矩陣
  10. inverted:取相反的矩陣丑蛤,就是反著來
  11. outer(合并)、skew(扭曲)撕阎、skewX(x軸扭曲)受裹、skewY(y軸扭曲)、zero(置零矩陣)虏束、fromList(將一個16位的一維數(shù)組轉(zhuǎn)換成4*4的矩陣)

常用的如下:

6.10.1 縮放

Matrix4.diagonal3Values(1, 1, 1)

表示縮放的比例名斟,分別沿x,y,z三個方向,x軸正向向右魄眉,y軸正向向下,z軸正向從屏幕朝上闷袒,正值表示正向坑律,>1表示放大,小于1大于0表示縮小,負值表示反向晃择。

6.10.2 移動

Matrix4.translationValues

表示平移的距離冀值,分別沿x,y,z三個方向,
x軸正向向右宫屠,
y軸正向向下列疗,
z軸正向從屏幕朝上,
正值表示正向移動浪蹂,負值表示負向移動抵栈,
其中z軸移動在平面上無法看出小錯

6.10.3 旋轉(zhuǎn)

Matrix4.rotationZ(pi / 6)

繞著Z軸旋轉(zhuǎn),正向是順時針坤次,負向是逆時針古劲,
正向也就是從x軸正向往y軸正向旋轉(zhuǎn)

Matrix4.rotationX(pi / 6)

繞著X軸旋轉(zhuǎn),正向是順時針缰猴,負向是逆時針产艾,
正向也就是從y軸正向往z軸正向旋轉(zhuǎn)

Matrix4.rotationY(pi / 6)

繞著Y軸旋轉(zhuǎn),正向是順時針滑绒,負向是逆時針闷堡,
正向也就是從x軸正向往z軸正向旋轉(zhuǎn)

6.11 photo_view

圖片預(yù)覽插件

photo_view: ^0.13.0

簡單使用

  Widget _buildPhotoView() {
    _galleryItems = [
      'assets/images/icon_avatar_staff.png',
      'assets/images/icon_avatar_staff.png',
      'assets/images/icon_avatar_staff.png'
    ];
    return PhotoViewGallery.builder(
      scrollPhysics: const BouncingScrollPhysics(),
      builder: (BuildContext context, int index) {
        return PhotoViewGalleryPageOptions(
          imageProvider: AssetImage(_galleryItems[index]),
          initialScale: PhotoViewComputedScale.contained * 0.9,
        );
      },
      itemCount: _galleryItems.length,
      backgroundDecoration: const BoxDecoration(color: Colors.white),
      pageController: PageController(initialPage: _currentPageIndex),
      onPageChanged: (i) {
        _currentPageIndex = i;
        _valueNotifier.notifyListeners();
      },
    );
  }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市疑故,隨后出現(xiàn)的幾起案子杠览,更是在濱河造成了極大的恐慌,老刑警劉巖焰扳,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倦零,死亡現(xiàn)場離奇詭異,居然都是意外死亡吨悍,警方通過查閱死者的電腦和手機扫茅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來育瓜,“玉大人葫隙,你說我怎么就攤上這事□锍穑” “怎么了恋脚?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長焰手。 經(jīng)常有香客問我糟描,道長,這世上最難降的妖魔是什么书妻? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任船响,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘见间。我一直安慰自己聊闯,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布米诉。 她就那樣靜靜地躺著菱蔬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪史侣。 梳的紋絲不亂的頭發(fā)上拴泌,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音抵窒,去河邊找鬼弛针。 笑死,一個胖子當(dāng)著我的面吹牛李皇,可吹牛的內(nèi)容都是我干的削茁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼掉房,長吁一口氣:“原來是場噩夢啊……” “哼茧跋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起卓囚,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤瘾杭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后哪亿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體粥烁,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年蝇棉,在試婚紗的時候發(fā)現(xiàn)自己被綠了讨阻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡篡殷,死狀恐怖钝吮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情板辽,我是刑警寧澤奇瘦,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站劲弦,受9級特大地震影響耳标,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜邑跪,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一麻捻、第九天 我趴在偏房一處隱蔽的房頂上張望纲仍。 院中可真熱鬧,春花似錦贸毕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至寇僧,卻和暖如春摊腋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嘁傀。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工兴蒸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人细办。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓橙凳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親笑撞。 傳聞我的和親對象是個殘疾皇子岛啸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容