Flutter之頁面布局二

目錄:

    • 1、列表布局
      • 1.1、基礎列表
      • 1.2、水平滑動的列表
      • 1.3、網格列表
      • 1.3、不同列表項的列表
      • 1.4、包含間隔的列表
      • 1.6、長列表
    • 2、滾動
      • 2.1、浮動的頂欄
      • 2.2、平衡錯位滾動

1、列表布局

1.1、基礎列表

在這里插入圖片描述

import 'package:flutter/material.dart';void main() => runApp(const MyApp());class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {const title = 'Basic List';return MaterialApp(title: title,home: Scaffold(appBar: AppBar(title: const Text(title)),body: ListView(children: const <Widget>[ListTile(leading: Icon(Icons.map), title: Text('Map')),ListTile(leading: Icon(Icons.photo_album), title: Text('Album')),ListTile(leading: Icon(Icons.phone), title: Text('Phone')),],),),);}
}

1.2、水平滑動的列表

在這里插入圖片描述

import 'package:flutter/material.dart';void main() => runApp(const MyApp());class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {const title = 'Horizontal List';return MaterialApp(title: title,home: Scaffold(appBar: AppBar(title: const Text(title)),body: Container(margin: const EdgeInsets.symmetric(vertical: 20),height: 200,child: ListView(// This next line does the trick.scrollDirection: Axis.horizontal,children: <Widget>[Container(width: 160, color: Colors.red),Container(width: 160, color: Colors.blue),Container(width: 160, color: Colors.green),Container(width: 160, color: Colors.yellow),Container(width: 160, color: Colors.orange),],),),),);}
}

1.3、網格列表

在這里插入圖片描述

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {const title = 'Grid List';return MaterialApp(title: title,home: Scaffold(appBar: AppBar(title: const Text(title)),body: GridView.count(// Create a grid with 2 columns.// If you change the scrollDirection to horizontal,// this produces 2 rows.crossAxisCount: 2,// Generate 100 widgets that display their index in the list.children: List.generate(100, (index) {return Center(child: Text('Item $index',style: TextTheme.of(context).headlineSmall,),);}),),),);}
}

1.3、不同列表項的列表

在這里插入圖片描述

import 'package:flutter/material.dart';void main() {runApp(MyApp(items: List<ListItem>.generate(1000,(i) =>i % 6 == 0? HeadingItem('Heading $i'): MessageItem('Sender $i', 'Message body $i'),),),);
}class MyApp extends StatelessWidget {final List<ListItem> items;const MyApp({super.key, required this.items});Widget build(BuildContext context) {const title = 'Mixed List';return MaterialApp(title: title,home: Scaffold(appBar: AppBar(title: const Text(title)),body: ListView.builder(// Let the ListView know how many items it needs to build.itemCount: items.length,// Provide a builder function. This is where the magic happens.// Convert each item into a widget based on the type of item it is.itemBuilder: (context, index) {final item = items[index];return ListTile(title: item.buildTitle(context),subtitle: item.buildSubtitle(context),);},),),);}
}/// The base class for the different types of items the list can contain.
abstract class ListItem {/// The title line to show in a list item.Widget buildTitle(BuildContext context);/// The subtitle line, if any, to show in a list item.Widget buildSubtitle(BuildContext context);
}/// A ListItem that contains data to display a heading.
class HeadingItem implements ListItem {final String heading;HeadingItem(this.heading);Widget buildTitle(BuildContext context) {return Text(heading, style: Theme.of(context).textTheme.headlineSmall);}Widget buildSubtitle(BuildContext context) => const SizedBox.shrink();
}/// A ListItem that contains data to display a message.
class MessageItem implements ListItem {final String sender;final String body;MessageItem(this.sender, this.body);Widget buildTitle(BuildContext context) => Text(sender);Widget buildSubtitle(BuildContext context) => Text(body);
}

1.4、包含間隔的列表

在這里插入圖片描述

import 'package:flutter/material.dart';void main() => runApp(const SpacedItemsList());class SpacedItemsList extends StatelessWidget {const SpacedItemsList({super.key});Widget build(BuildContext context) {const items = 4;return MaterialApp(title: 'Flutter Demo',debugShowCheckedModeBanner: false,theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),cardTheme: CardTheme(color: Colors.blue.shade50),),home: Scaffold(body: LayoutBuilder(builder: (context, constraints) {return SingleChildScrollView(child: ConstrainedBox(constraints: BoxConstraints(minHeight: constraints.maxHeight),child: Column(mainAxisAlignment: MainAxisAlignment.spaceBetween,crossAxisAlignment: CrossAxisAlignment.stretch,children: List.generate(items,(index) => ItemWidget(text: 'Item $index'),),),),);},),),);}
}class ItemWidget extends StatelessWidget {const ItemWidget({super.key, required this.text});final String text;Widget build(BuildContext context) {return Card(child: SizedBox(height: 100, child: Center(child: Text(text))));}
}

1.6、長列表

在這里插入圖片描述

import 'package:flutter/material.dart';void main() {runApp(MyApp(items: List<String>.generate(10000, (i) => 'Item $i'),),);
}class MyApp extends StatelessWidget {final List<String> items;const MyApp({super.key, required this.items});Widget build(BuildContext context) {const title = 'Long List';return MaterialApp(title: title,home: Scaffold(appBar: AppBar(title: const Text(title)),body: ListView.builder(itemCount: items.length,prototypeItem: ListTile(title: Text(items.first)),itemBuilder: (context, index) {return ListTile(title: Text(items[index]));},),),);}
}

2、滾動

2.1、浮動的頂欄

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

import 'package:flutter/material.dart';void main() => runApp(const MyApp());class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {const title = 'Floating App Bar';return MaterialApp(title: title,home: Scaffold(// No appbar provided to the Scaffold, only a body with a// CustomScrollView.body: CustomScrollView(slivers: [// Add the app bar to the CustomScrollView.const SliverAppBar(// Provide a standard title.title: Text(title),// Allows the user to reveal the app bar if they begin scrolling// back up the list of items.floating: true,// Display a placeholder widget to visualize the shrinking size.flexibleSpace: Placeholder(),// Make the initial height of the SliverAppBar larger than normal.expandedHeight: 200,),// Next, create a SliverListSliverList(// Use a delegate to build items as they're scrolled on screen.delegate: SliverChildBuilderDelegate(// The builder function returns a ListTile with a title that// displays the index of the current item.(context, index) => ListTile(title: Text('Item #$index')),// Builds 1000 ListTileschildCount: 1000,),),],),),);}
}

2.2、平衡錯位滾動

在這里插入圖片描述

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';const Color darkBlue = Color.fromARGB(255, 18, 32, 47);void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return MaterialApp(theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),debugShowCheckedModeBanner: false,home: const Scaffold(body: Center(child: ExampleParallax())),);}
}class ExampleParallax extends StatelessWidget {const ExampleParallax({super.key});Widget build(BuildContext context) {return SingleChildScrollView(child: Column(children: [for (final location in locations)LocationListItem(imageUrl: location.imageUrl,name: location.name,country: location.place,),],),);}
}class LocationListItem extends StatelessWidget {LocationListItem({super.key,required this.imageUrl,required this.name,required this.country,});final String imageUrl;final String name;final String country;final GlobalKey _backgroundImageKey = GlobalKey();Widget build(BuildContext context) {return Padding(padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),child: AspectRatio(aspectRatio: 16 / 9,child: ClipRRect(borderRadius: BorderRadius.circular(16),child: Stack(children: [_buildParallaxBackground(context),_buildGradient(),_buildTitleAndSubtitle(),],),),),);}Widget _buildParallaxBackground(BuildContext context) {return Flow(delegate: ParallaxFlowDelegate(scrollable: Scrollable.of(context),listItemContext: context,backgroundImageKey: _backgroundImageKey,),children: [Image.network(imageUrl, key: _backgroundImageKey, fit: BoxFit.cover),],);}Widget _buildGradient() {return Positioned.fill(child: DecoratedBox(decoration: BoxDecoration(gradient: LinearGradient(colors: [Colors.transparent, Colors.black.withValues(alpha: 0.7)],begin: Alignment.topCenter,end: Alignment.bottomCenter,stops: const [0.6, 0.95],),),),);}Widget _buildTitleAndSubtitle() {return Positioned(left: 20,bottom: 20,child: Column(mainAxisSize: MainAxisSize.min,crossAxisAlignment: CrossAxisAlignment.start,children: [Text(name,style: const TextStyle(color: Colors.white,fontSize: 20,fontWeight: FontWeight.bold,),),Text(country,style: const TextStyle(color: Colors.white, fontSize: 14),),],),);}
}class ParallaxFlowDelegate extends FlowDelegate {ParallaxFlowDelegate({required this.scrollable,required this.listItemContext,required this.backgroundImageKey,}) : super(repaint: scrollable.position);final ScrollableState scrollable;final BuildContext listItemContext;final GlobalKey backgroundImageKey;BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints) {return BoxConstraints.tightFor(width: constraints.maxWidth);}void paintChildren(FlowPaintingContext context) {// Calculate the position of this list item within the viewport.final scrollableBox = scrollable.context.findRenderObject() as RenderBox;final listItemBox = listItemContext.findRenderObject() as RenderBox;final listItemOffset = listItemBox.localToGlobal(listItemBox.size.centerLeft(Offset.zero),ancestor: scrollableBox,);// Determine the percent position of this list item within the// scrollable area.final viewportDimension = scrollable.position.viewportDimension;final scrollFraction = (listItemOffset.dy / viewportDimension).clamp(0.0,1.0,);// Calculate the vertical alignment of the background// based on the scroll percent.final verticalAlignment = Alignment(0.0, scrollFraction * 2 - 1);// Convert the background alignment into a pixel offset for// painting purposes.final backgroundSize =(backgroundImageKey.currentContext!.findRenderObject() as RenderBox).size;final listItemSize = context.size;final childRect = verticalAlignment.inscribe(backgroundSize,Offset.zero & listItemSize,);// Paint the background.context.paintChild(0,transform:Transform.translate(offset: Offset(0.0, childRect.top)).transform,);}bool shouldRepaint(ParallaxFlowDelegate oldDelegate) {return scrollable != oldDelegate.scrollable ||listItemContext != oldDelegate.listItemContext ||backgroundImageKey != oldDelegate.backgroundImageKey;}}class Parallax extends SingleChildRenderObjectWidget {const Parallax({super.key, required Widget background}): super(child: background);RenderObject createRenderObject(BuildContext context) {return RenderParallax(scrollable: Scrollable.of(context));}void updateRenderObject(BuildContext context,covariant RenderParallax renderObject,) {renderObject.scrollable = Scrollable.of(context);}
}class ParallaxParentData extends ContainerBoxParentData<RenderBox> {}class RenderParallax extends RenderBoxwith RenderObjectWithChildMixin<RenderBox>, RenderProxyBoxMixin {RenderParallax({required ScrollableState scrollable}): _scrollable = scrollable;ScrollableState _scrollable;ScrollableState get scrollable => _scrollable;set scrollable(ScrollableState value) {if (value != _scrollable) {if (attached) {_scrollable.position.removeListener(markNeedsLayout);}_scrollable = value;if (attached) {_scrollable.position.addListener(markNeedsLayout);}}}void attach(covariant PipelineOwner owner) {super.attach(owner);_scrollable.position.addListener(markNeedsLayout);}void detach() {_scrollable.position.removeListener(markNeedsLayout);super.detach();}void setupParentData(covariant RenderObject child) {if (child.parentData is! ParallaxParentData) {child.parentData = ParallaxParentData();}}void performLayout() {size = constraints.biggest;// Force the background to take up all available width// and then scale its height based on the image's aspect ratio.final background = child!;final backgroundImageConstraints = BoxConstraints.tightFor(width: size.width,);background.layout(backgroundImageConstraints, parentUsesSize: true);// Set the background's local offset, which is zero.(background.parentData as ParallaxParentData).offset = Offset.zero;}void paint(PaintingContext context, Offset offset) {// Get the size of the scrollable area.final viewportDimension = scrollable.position.viewportDimension;// Calculate the global position of this list item.final scrollableBox = scrollable.context.findRenderObject() as RenderBox;final backgroundOffset = localToGlobal(size.centerLeft(Offset.zero),ancestor: scrollableBox,);// Determine the percent position of this list item within the// scrollable area.final scrollFraction = (backgroundOffset.dy / viewportDimension).clamp(0.0,1.0,);// Calculate the vertical alignment of the background// based on the scroll percent.final verticalAlignment = Alignment(0.0, scrollFraction * 2 - 1);// Convert the background alignment into a pixel offset for// painting purposes.final background = child!;final backgroundSize = background.size;final listItemSize = size;final childRect = verticalAlignment.inscribe(backgroundSize,Offset.zero & listItemSize,);// Paint the background.context.paintChild(background,(background.parentData as ParallaxParentData).offset +offset +Offset(0.0, childRect.top),);}
}class Location {const Location({required this.name,required this.place,required this.imageUrl,});final String name;final String place;final String imageUrl;
}const urlPrefix ='https://docs.flutter.dev/cookbook/img-files/effects/parallax';
const locations = [Location(name: 'Mount Rushmore',place: 'U.S.A',imageUrl: '$urlPrefix/01-mount-rushmore.jpg',),Location(name: 'Gardens By The Bay',place: 'Singapore',imageUrl: '$urlPrefix/02-singapore.jpg',),Location(name: 'Machu Picchu',place: 'Peru',imageUrl: '$urlPrefix/03-machu-picchu.jpg',),Location(name: 'Vitznau',place: 'Switzerland',imageUrl: '$urlPrefix/04-vitznau.jpg',),Location(name: 'Bali',place: 'Indonesia',imageUrl: '$urlPrefix/05-bali.jpg',),Location(name: 'Mexico City',place: 'Mexico',imageUrl: '$urlPrefix/06-mexico-city.jpg',),Location(name: 'Cairo', place: 'Egypt', imageUrl: '$urlPrefix/07-cairo.jpg'),
];

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/900442.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/900442.shtml
英文地址,請注明出處:http://en.pswp.cn/news/900442.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ARM------硬件程序開發

硬件程序開發流程 相關硬件的工作原理 理解硬件的工作原理&#xff0c;明確硬件的功能和用途。 硬件連接 將硬件設備正確連接到開發板上。 編寫程序 根據硬件功能編寫相應的程序代碼。 調試驗證 通過調試工具驗證程序的正確性&#xff0c;確保硬件功能正常。 控制LED的…

《QT從基礎到進階·七十四》Qt+C++開發一個python編譯器,能夠編寫,運行python程序改進版

1、概述 源碼放在文章末尾 根據上一篇文章回顧下利用QtC實現了一個簡易的python編譯器&#xff0c;類似pycharm或vsCode這樣的編譯器&#xff0c;該python編譯器目前實現了如下功能&#xff1a; &#xff08;1&#xff09;支持編寫python程序 &#xff08;2&#xff09;編寫代…

Winform MQTT客戶端連接方式

項目中使用到Winform的數據轉發服務&#xff0c;所以記錄下使用到的方法。 一.創建單例模板 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ConsoleApp.Scripts {public class SingleTon&…

Windows強制刪除任何你想刪除的文件和文件夾

Windows強制刪除任何你想刪除的文件和文件夾 本教程適用于 Windows 10/11 系統&#xff0c;工具和命令均經過驗證。 為什么刪除會失敗&#xff1f; 權限不足&#xff1a;文件或文件夾可能需要管理員權限才能刪除。文件被占用&#xff1a;某個程序正在使用目標文件&#xff0c…

Jmeter如何使用MD5進行加密?

在軟件測試中&#xff0c;使用 JMeter 對數據進行 MD5 加密是一項常見需求&#xff0c;尤其是在模擬用戶登錄等涉及密碼加密的場景時。下面詳細介紹在 JMeter 里運用 MD5 加密的具體步驟。 1. 添加 BeanShell 預處理器 JMeter 本身沒有直接的 MD5 加密功能&#xff0c;但可以…

4-c語言中的數據類型

一.C 語?中的常量 1.生活中的數據 整數&#xff1a; 100,200,300,400,500 小數: 11.11 22.22 33.33 字母&#xff1a; a&#xff0c;b&#xff0c;c&#xff0c;d A&#xff0c;B&#xff0c;C&#xff0c;D 在 C 語?中我們把字?叫做字符. 字符?單引號引?。例如A’ 單詞…

中鈞科技通過數字賦能,編織“數字互聯網”助力數字化進程!

時間飛逝轉眼間2025年已過去四分之一&#xff0c;作為一名95后回顧當下的生活&#xff0c;忍不住感慨10年和現在的對比。發現現在的手機支付、網上掛號、APP打車、在線學習、網絡訂餐、線上協同辦公都以逐漸成為人們生活、工作的常態。也正是在這樣的常態背景下&#xff0c;加快…

AI重塑云基礎設施,亞馬遜云科技打造AI定制版IaaS“樣板房”

AI正在徹底重塑云基礎設施。 IDC最新《2025年IDC MarketScape&#xff1a;全球公有云基礎設施即服務&#xff08;IaaS&#xff09;報告》顯示&#xff0c;AI正在通過多種方式重塑云基礎設施&#xff0c;公有云IaaS有望繼續保持快速增長&#xff0c;預計2025年全球IaaS的整體規…

高效深度學習lecture01

lecture01 零樣本學習(Zero-Shot Learning, ZSL)&#xff1a; 模型可以在沒有見過某種特定任務或類別的訓練樣本的情況下&#xff0c;直接完成對應的任務 利用知識遷移 模型在一個任務上訓練時學到的知識&#xff0c;能夠遷移到其他任務上比如&#xff0c;模型知道“狗”和“…

使用 iPerf 測試內網兩臺機器之間的傳輸速度

在現代網絡管理中&#xff0c;確保內部網絡&#xff08;內網&#xff09;的高效運行是至關重要的。為了評估和優化網絡性能&#xff0c;我們需要一種可靠的方法來測試內網中不同設備間的傳輸速率。iPerf 作為一款廣泛使用的工具&#xff0c;能夠幫助我們準確測量兩個節點之間的…

視頻設備軌跡回放平臺EasyCVR如何搭建公共娛樂場所遠程視頻監控系統

一、背景介紹 由于KTV、酒吧、足療店等服務場所人員流動頻繁、環境復雜&#xff0c;一直是治安管理的重點區域。為有效打擊 “黃賭毒”、打架斗毆、尋釁滋事等違法犯罪的活動&#xff0c;打造安全有序的娛樂消費環境&#xff0c;我國相關部門將加大對這類場所的清查與管控力度…

vue進度條組件

<div class"global-mask" v-if"isProgress"><div class"contentBox"><div class"progresstitie">數據加載中請稍后</div><el-progress class"progressStyle" :color"customColor" tex…

Css:如何解決絕對定位子元素內容被父級元素overflow:hidden屬性剪裁

一、問題描述 今天小伙伴提了一個bug&#xff0c;在點擊列表項的“…”按鈕應該出現的懸浮菜單顯示不完整&#xff1a; 二、問題排查 一般這種問題&#xff0c;是由于懸浮菜單采用的是絕對定位&#xff0c;而父級采用了overflow:hidden屬性。但需要注意的是&#xff0c;這里的…

JavaScript基礎--01-JS簡介

字面量&#xff1a;數字、字符串、布爾值 前言JavaScript背景Web前端有三層&#xff1a;發展歷史JavaScript的發展&#xff1a;蒸蒸日上 JavaScript介紹JavaScript入門易學性JavaScript是腳本語言JavaScript的組成 JavaScript 的特點特點1&#xff1a;解釋型語言特點2&#xff…

[leetcode] 面試經典 150 題——篇9:二叉樹(番外:二叉樹的遍歷方式)

二叉樹的遍歷是指按照某種順序訪問二叉樹中的每個節點。常見的遍歷方式有四種&#xff1a;前序遍歷&#xff08;Pre-order Traversal&#xff09;、中序遍歷&#xff08;In-order Traversal&#xff09;、后序遍歷&#xff08;Post-order Traversal&#xff09;以及層序遍歷&am…

es基本概念

Elasticsearch 的架構與基本概念 Elasticsearch&#xff08;簡稱 ES&#xff09;是一個開源的分布式搜索和分析引擎&#xff0c;基于 Apache Lucene 構建。它被廣泛用于全文搜索、日志分析、實時數據分析等場景。以下是其架構概述及其基本概念的詳細解釋。 Elasticsearch 的架…

《星環之城:量子迷霧下的網絡安全戰記》

點擊下面圖片帶您領略全新的嵌入式學習路線 &#x1f525;爆款熱榜 88萬閱讀 1.6萬收藏 序章&#xff1a;星環之隕 公元2145年&#xff0c;人類在火星軌道上建造了“星環之城”——一座由量子網絡連接的太空城邦。它的中樞AI“蓋婭”掌控著地球與殖民地的數據洪流&#xff…

《全棧+雙客戶端Turnkey方案》架構設計圖

今天分享一些全棧雙客戶端Turnkey方案的架構與結構圖。 1&#xff1a;三種分布式部署方案:網關方案&#xff0c;超級服務器單服方案&#xff0c;直連邏輯服方案 2: 單服多線程核心架構: 系統服務邏輯服服務 3: 系統服務的多線程池調度設計 4:LogicServer Update與ECS架構&…

打破界限:Android XML與Jetpack Compose深度互操作指南

在現有XML布局項目中逐步引入Jetpack Compose是現代Android開發的常見需求。本指南將全面介紹混合使用的最佳實踐、技術細節和完整解決方案。 一、基礎配置 1.1 Gradle配置 android {buildFeatures {compose true}composeOptions {kotlinCompilerExtensionVersion "1.5.3…

React-narice安卓打包流程

**1. 生成簽名密鑰 在項目的 android/app 目錄下生成簽名密鑰的步驟&#xff1a; 打開終端或命令提示符&#xff1a;導航到您的 React Native 項目的 android/app 目錄。 運行以下命令生成密鑰庫文件&#xff1a; keytool -genkeypair -v -keystore my-release-key.keystor…