Flutter(三):Stack、Positioned、屏幕相关尺寸、Navigator路由跳转

页面尺寸

在这里插入图片描述

  • 通知栏高度:MediaQuery.of(context).padding.top
  • 顶部导航高度:kToolbarHeight
  • 底部导航高度:kBottomNavigationBarHeight
  • 屏幕宽:MediaQuery.of(context).size.width
  • 屏幕高:MediaQuery.of(context).size.height
import 'package:flutter/material.dart';

// 描述文本
class DescText extends StatelessWidget {
  final String title;
  final double size;

  const DescText(this.title, {super.key, this.size = 10});

  
  Widget build(BuildContext context) {
    return Center(
      child: Text(title, style: TextStyle(fontSize: size, decoration: TextDecoration.none)),
    );
  }
}

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

  
  State<ScreenSizePage> createState() => _ScreenSizePage();
}

class _ScreenSizePage extends State<ScreenSizePage> {
  
  Widget build(BuildContext context) {
    // 屏幕宽度
    double screenWidth = MediaQuery
        .of(context)
        .size
        .width;
    // 屏幕高度
    double screenHeight = MediaQuery
        .of(context)
        .size
        .height;
    // 通知栏高度
    double noticeHeight = MediaQuery
        .of(context)
        .padding
        .top;
    // 屏幕中心
    double centerX = screenWidth / 2;
    double centerY = screenHeight / 2;

    return Container(
      width: double.infinity,
      height: double.infinity,
      color: Colors.grey,
      child: Stack(
        children: [
          Positioned(
            top: 0,
            left: 0,
            child: Container(
              width: screenWidth,
              height: noticeHeight,
              color: Colors.yellow,
              child: DescText('通知栏高度($noticeHeight):MediaQuery.of(context).padding.top'),
            ),
          ),
          Positioned(
            top: noticeHeight,
            left: 0,
            child: Container(
              width: screenWidth,
              height: kToolbarHeight,
              color: Colors.blue,
              child: const DescText('顶部导航高度($kToolbarHeight):kToolbarHeight', size: 16),
            ),
          ),
          Positioned(
            bottom: 0,
            left: 0,
            child: Container(
              width: screenWidth,
              height: kBottomNavigationBarHeight,
              color: Colors.green,
              child: const DescText(
                  '底部导航高度($kBottomNavigationBarHeight):kBottomNavigationBarHeight', size: 14),
            ),
          ),
          Positioned(
            bottom: 80,
            left: 0,
            child: Container(
              width: screenWidth,
              height: 30,
              color: const Color.fromRGBO(255, 255, 0, .3),
              child: DescText('屏幕宽($screenWidth):MediaQuery.of(context).size.width'),
            ),
          ),
          Positioned(
            top: 0,
            right: 80,
            child: Container(
              width: 30,
              height: screenHeight,
              color: const Color.fromRGBO(0, 255, 255, .3),
              child: RotatedBox(
                quarterTurns: 45,
                child: DescText(
                    '屏幕高($screenHeight):MediaQuery.of(context).size.height', size: 12),
              ),
            ),
          ),
          Positioned(
            top: centerY - 18,
            left: centerX - 50,
            child: MaterialButton(
              onPressed: () => Navigator.pop(context, true),
              // 返回上一页
              color: Colors.white,
              textColor: Colors.blue,
              minWidth: 100,
              height: 36,
              child: const Text('返 回'),
            ),
          ),
        ],
      ),
    );
  }
}

Stack布局

SelectWidget组件参考 https://blog.csdn.net/weixin_43526371/article/details/136256386

在这里插入图片描述

import 'package:flutter/material.dart';
import 'package:flutter_app/components/select_widget.dart';

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

  
  State<StackPage> createState() => _StackPage();
}

class _StackPage extends State<StackPage> {
  AlignmentDirectional alignmentValue = AlignmentDirectional.topStart;
  List<SelectOption> alignmentList = [
    SelectOption(label: 'topStart', value: AlignmentDirectional.topStart),
    SelectOption(label: 'topCenter', value: AlignmentDirectional.topCenter),
    SelectOption(label: 'topEnd', value: AlignmentDirectional.topEnd),
    SelectOption(label: 'centerStart', value: AlignmentDirectional.centerStart),
    SelectOption(label: 'center', value: AlignmentDirectional.center),
    SelectOption(label: 'centerEnd', value: AlignmentDirectional.centerEnd),
    SelectOption(label: 'bottomStart', value: AlignmentDirectional.bottomStart),
    SelectOption(label: 'bottomCenter', value: AlignmentDirectional.bottomCenter),
    SelectOption(label: 'bottomEnd', value: AlignmentDirectional.bottomEnd),
  ];

  TextDirection textDirectionValue = TextDirection.ltr;
  List<SelectOption> textDirectionList = [
    SelectOption(label: 'ltr', value: TextDirection.ltr),
    SelectOption(label: 'rtl', value: TextDirection.rtl),
  ];

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Stack 布局')),
      body: Scaffold(
        appBar: PreferredSize(
          preferredSize: const Size.fromHeight(50),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Expanded(
                flex: 1,
                child: SelectWidget(
                  title: 'AlignmentDirectional',
                  options: alignmentList,
                  onChange: (SelectOption selectOption) {
                    setState(() {
                      alignmentValue = selectOption.value as AlignmentDirectional;
                    });
                  },
                ),
              ),
              Expanded(
                flex: 1,
                child: SelectWidget(
                  title: 'TextDirection',
                  options: textDirectionList,
                  onChange: (SelectOption selectOption) {
                    setState(() {
                      textDirectionValue = selectOption.value as TextDirection;
                    });
                  },
                ),
              ),
            ],
          ),
        ),
        body: Container(
          width: double.infinity,
          height: double.infinity,
          color: Colors.grey,
          child: Stack(
            alignment: alignmentValue,
            textDirection: textDirectionValue,
            children: [
              Container(width: 250, height: 250, color: Colors.red),
              Container(width: 200, height: 200, color: Colors.green),
              Container(width: 150, height: 150, color: Colors.blue),
              Container(width: 100, height: 100, color: Colors.black),
            ],
          ),
        ),
      ),
    );
  }
}

Positioned布局

在这里插入图片描述

import 'package:flutter/material.dart';

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

  
  State<PositionedPage> createState() => _PositionedPage();
}

class _PositionedPage extends State<PositionedPage> {
  
  Widget build(BuildContext context) {
    // 屏幕宽度
    double screenWidth = MediaQuery
        .of(context)
        .size
        .width;
    // 屏幕高度
    double screenHeight = MediaQuery
        .of(context)
        .size
        .height;
    // 通知栏高度
    double noticeHeight = MediaQuery
        .of(context)
        .padding
        .top;
    // 屏幕中心
    double centerX = screenWidth / 2;
    double centerY = (screenHeight - noticeHeight - kToolbarHeight - kBottomNavigationBarHeight) /
        2;

    return Scaffold(
      appBar: AppBar(title: const Text('Positioned 布局')),
      body: Container(
        width: double.infinity,
        height: double.infinity,
        color: Colors.grey,
        child: Stack(
          children: [
            // 中
            Positioned(
              top: centerY - 50,
              left: centerX - 50,
              child: Container(width: 100, height: 100, color: Colors.orange),
            ),
            // 左上
            Positioned(
              top: 10,
              left: 10,
              child: Container(
                width: 120,
                height: 120,
                color: Colors.red,
                child: Stack(
                  children: [
                    Positioned(top: 20,
                        left: 20,
                        child: Container(width: 50, height: 50, color: Colors.black)),
                  ],
                ),
              ),
            ),
            // 右上
            Positioned(
              top: 10,
              right: 10,
              child: Container(
                width: 120,
                height: 120,
                color: Colors.green,
                child: Stack(
                  children: [
                    Positioned(top: 20,
                        right: 20,
                        child: Container(width: 50, height: 50, color: Colors.blue)),
                  ],
                ),
              ),
            ),
            // 左下
            Positioned(
              bottom: 10,
              left: 10,
              child: Container(
                width: 120,
                height: 120,
                color: Colors.blue,
                child: Stack(
                  children: [
                    Positioned(bottom: 20,
                        left: 20,
                        child: Container(width: 50, height: 50, color: Colors.green)),
                  ],
                ),
              ),
            ),
            // 右下
            Positioned(
              bottom: 10,
              right: 10,
              child: Container(
                width: 120,
                height: 120,
                color: Colors.black,
                child: Stack(
                  children: [
                    Positioned(bottom: 20,
                        right: 20,
                        child: Container(width: 50, height: 50, color: Colors.red)),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: 'HOME'),
          BottomNavigationBarItem(icon: Icon(Icons.book), label: 'BOOK'),
        ],
      ),
    );
  }
}

路由组件

在这里插入图片描述

路由组件

import 'package:flutter/material.dart';
import 'package:flutter_app/views/RowColumnPage.dart';
import 'package:flutter_app/views/StackPage.dart';
import 'package:flutter_app/views/ScreenSizePage.dart';
import 'package:flutter_app/views/PositionedPage.dart';

class MenuItem {
  final String title;
  final Widget widget;

  MenuItem({required this.title, required this.widget});
}

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

  static List<MenuItem> list = <MenuItem>[
    MenuItem(title: "Row、Column 布局", widget: const RowColumnPage()),
    MenuItem(title: "Stack 布局", widget: const StackPage()),
    MenuItem(title: "界面尺寸", widget: const ScreenSizePage()),
    MenuItem(title: "Positioned 布局", widget: const PositionedPage()),
  ];

  
  Widget build(BuildContext context) {
    return ListView.separated(
      itemCount: list.length,
      separatorBuilder: (BuildContext context, int index) => const Divider(height: 1),
      itemBuilder: (BuildContext context, int index) {
        return ListTile(
          title: Text(list[index].title),
          onTap: () {
            Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => list[index].widget));
          },
        );
      },
    );
  }
}

入口组件

import 'package:flutter/material.dart';
import 'package:flutter_app/components/router_widget.dart';

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

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

  
  State<App> createState() => _AppState();
}

class _AppState extends State<App> {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, // 移除右上角DEBUG标识
      home: Scaffold(
        appBar: AppBar(title: const Text("目录")),
        body: const RouterWidget(),
      ),
    );
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/428841.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于STM32制作的示波器(可对任意信号进行描点)

基于STM32制作的示波器&#xff08;可对任意信号进行描点&#xff09; 注意&#xff1a;用的屏幕是TFT-LCD&#xff08;MCU 屏&#xff09;正点原子同款屏幕 液晶显示器&#xff0c;即 Liquid Crystal Display&#xff0c;利用了液晶导电后透光性可变的特性&#xff0c;配合显…

2024洗地机选购攻略 | 洗地机好用吗?洗地机如何挑选?

在众多清洁工具中&#xff0c;洗地机以其卓越的清洁能力和便捷的操作方式&#xff0c;获得了广泛关注。2024年&#xff0c;市场上涌现出众多品牌的洗地机&#xff0c;但哪些品牌的洗地机值得推荐呢&#xff1f;在这里&#xff0c;我们将详细探讨几个备受好评的洗地机品牌&#…

Fisher矩阵与自然梯度法

文章目录 Fisher矩阵及自然梯度法Fisher矩阵自然梯度法总结参考链接 Fisher矩阵及自然梯度法 自然梯度法相比传统的梯度下降法具有以下优势&#xff1a; 更好的适应性&#xff1a;自然梯度法通过引入黎曼流形上的梯度概念&#xff0c;能够更好地适应参数空间的几何结构。这使…

向上生长笔记

第一章 成为一个很厉害的人(持续输入&#xff0c;反复练习) 为什么要学习及如何学习 1、自毁趋势(熵增)&#xff0c;故需要能量输入(负熵流) //引申&#xff1a;水往低处流是趋势&#xff0c;学习是逆趋势。 2、持续输入能量&#xff08;物质和信息&#xff09;&#xff0c;…

BUUCTF---[ACTF2020 新生赛]BackupFile1

1.题目描述 2.题目提示backup file &#xff0c;是备份文件的意思。点开链接&#xff0c;页面提示 3.查看源码没有什么有用信息&#xff0c;也没有登录界面&#xff0c;所以也不会用到蚁剑链接来找备份文件&#xff0c;所以大概率就是通过构造playload来查找备份文件。 4.备份…

vue+element ui上传图片到七牛云服务器

本来打算做一个全部都是前端完成的资源上传到七牛云的demo&#xff0c;但是需要获取token&#xff0c;经历了九九八十一难&#xff0c;最终还是选择放弃&#xff0c;token从后端获取&#xff08;springboot&#xff09;。如果你们有前端直接能解决的麻烦记得私我哦&#xff01;…

详解自动化测试框架特点和原理

【软件测试面试突击班】2024吃透软件测试面试最全八股文攻略教程&#xff0c;一周学完让你面试通过率提高90%&#xff01;&#xff08;自动化测试&#xff09; 今天捡一些比较典型的工具型自动化框架来介绍&#xff0c;主要围绕历史、特点和原理来讲解&#xff0c;至于使用教程…

MYSQL07高级_Hash结构、平衡二叉树、B树、B+树介绍

文章目录 ①. 全表遍历②. Hash结构③. 平衡二叉搜索树(AVL)④. B树⑤. B树⑥. 时间复杂度 选择的合理性 磁盘的I/O操作次数对索引的使用效率至关重要查找都是索引操作,一般来说索引非常大,尤其是关系型数据库,当数据量比较大的时候,索引的大小有可能几个G甚至更多,为了减少索引…

BUUCTF---[BJDCTF2020]藏藏藏1

1.题目描述 2.下载附件&#xff0c;解压之后是一张图片和一个文本 3.把图片放在winhex,发现图片里面包含压缩包 4.在kali中使用binwalk查看&#xff0c;然后使用foremost分离&#xff0c;在使用tree查看分离出来的文件&#xff0c;最后将zip文件使用unzip进行解压。步骤如下 5.…

分巧克力 刷题笔记

/* 分巧克力 解题思路 二分 直接检查看答案是否符合题目条件 对于一块边长分别为x 和y的巧克力\\ 假设我们输入检查的数为k 其能分割成的 k*k 的巧克力的块数为 (x/k)*(y/k) 因为c里面的除法是下取整的所以我们不用考虑奇偶数 是否能整除 将每一块巧克力能分成的k*k的巧克力…

镭速:推动工业设备数据高效汇聚的关键力量

在工业4.0时代&#xff0c;智能制造和工业自动化的快速发展使得工业设备数据汇聚、采集、传输变得尤为重要。这些数据&#xff0c;包括设备运行状态、生产效率、能耗等关键信息&#xff0c;对于企业优化生产流程、提升产品质量、降低成本具有至关重要的作用。然而&#xff0c;在…

jsp阿帕奇安装教程

1.将压缩包解压&#xff0c;存放在自己所知道的位置 2.将软件文件夹打开 使用winr &#xff0c;输入cmd运行打开 输入Java或者Javac&#xff0c;出现一大串之后表明成功 接着在所解压的软件中点开bin这个文件夹&#xff0c;找到startup.bat点击 点击之后会出现黑框&#xff0c…

Mint_21.3 drawing-area和goocanvas的FB笔记(三)

一、改变goocanvas线条自动画线时间间隔 通过系统SIGALRM信号触发&#xff0c;每秒画一条线对于慢温湿度等慢变信号可以应付&#xff0c;但对于快速信号1秒的间隔就太慢了。可以改变方式&#xff0c;通过另外的线程&#xff0c;完成要做的任务。 1. 线程的回调函数 myfunc 2…

javaWebssh酒店客房管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh酒店客房管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0…

都2024了,软件测试真的就是简单的点点点吗???

软件测试真的就是用手点点这么简单 你的身边&#xff0c;是否有这样一片景象&#xff1f; A:写了几年代码&#xff0c;写不下去了&#xff0c;听说测试很好上手&#xff0c;先来做几年测试 。 B:小文员一枚&#xff0c;想入行 IT&#xff0c;听说测试入门简单&#xff0c;请…

SpringBoot-首页和图标定制

1.静态资源导入 SpringBoot中的静态资源&#xff0c;默认有以下四个路径可以访问&#xff1a; classpath:/META-INF/resources/ classpath:/resources/ classpath:/static/ classpath:/public/ 其中第一个路径&#xff0c;一般不常用&#xff0c;它是来获取用maven导入webj…

4.5.CVAT——视频标注的详细步骤

文章目录 1. 跟踪模式&#xff08;基础&#xff09;2. 跟踪模式&#xff08;高级&#xff09;3. 带多边形的轨迹模式 追踪模式Track mode &#xff08;视频标注使用&#xff09;——类似pr的动画效果 1. 跟踪模式&#xff08;基础&#xff09; 使用示例&#xff1a; 为一系列…

如何创建MinIO存储服务公网地址实现固定TCP域名异地远程访问——“cpolar内网穿透”

文章目录 前言1. 创建Buckets和Access Keys2. Linux 安装Cpolar3. 创建连接MinIO服务公网地址4. 远程调用MinIO服务小结5. 固定连接TCP公网地址6. 固定地址连接测试 前言 MinIO是一款高性能、分布式的对象存储系统&#xff0c;它可以100%的运行在标准硬件上&#xff0c;即X86等…

Python 全栈系列231 以数据处理为核心的微服务思考

说明 最初我是专注与做数据分析和建模的&#xff0c;通俗点说也就是pandas和sklearn。照理来说&#xff0c;分析和建模作为一种分工&#xff0c;本身是可以独立于架构的设计和使用的。其实也就是从20年之后&#xff0c;我才开始花比较多的时间研究这一块。 回想了一下原因&am…

【计算机考研】408学到什么程度才能考130?

408考130要比考研数学考130难的多 我想大部分考过408的考生都是这么认为的。408的难点在于他涉及的范围太广了&#xff0c;首先如果你要备考408&#xff0c;你要准备四门课程&#xff0c;分别是数据结构&#xff0c;计算机组成原理&#xff0c;操作系统和计算机网络。 这四门…