前言
在现代移动应用开发中,用户界面的布局设计至关重要。Flutter作为一个高效的UI框架,提供了丰富的布局组件,能够帮助开发者轻松构建灵活多变的用户界面。本文将深入探讨Flutter中的各种UI布局方式,包括线性布局(如Column和Row)、非线性布局(如Stack、Flex、Positioned)以及Wrap布局。通过具体的示例代码,我们将展示如何利用这些布局组件来创建简洁而富有表现力的界面。
UI布局
线性布局
return const Scaffold( body:Column( children:[ Text('hello'), Text('world'), Text('welcome'), ]) );
body:Row( children: [ Text('hello+'), Text('world+'), Text('welcome+') ], )
平分
Widget buildColumn(){ return Container( decoration: BoxDecoration(border: Border.all()), child: Column( children: [ Expanded(child: Container(color: Colors.grey,),flex: 1,), Expanded(child: Container(color: Colors.red,),flex: 1,), Expanded(child: Container(color: Colors.blue,),flex: 1,), ], ), ); }
先使用一个 之后会占满
child: Row( children: [ ElevatedButton( onPressed: () { print("hello"); }, child: Text( "hello", style: TextStyle(fontSize: 20, color: Colors.black), ), ), Expanded( child: ElevatedButton( onPressed: () { print("hello"); }, child: Text( "hello", style: TextStyle(fontSize: 20, color: Colors.black), ), ), ) ], ),
return Scaffold( body:Container( child: buildColumn(), ) );
return Scaffold( body: Row( children: [ Expanded(flex:1,child:Container( alignment: Alignment.center, height: 33, color: Colors.blue, child: Text('二级导航栏',style: TextStyle( color: Colors.white ),), ) ) ], ), );
非线性布局
Stack
可以容纳多个组件,以叠加的方式摆放子组件,后者居上。拥有Alignment属性,可以与Positioned组件联合使用,精准并有效摆放。同Android端FramLayout布局相似。
@override Widget build(BuildContext context) { return Stack( // alignment alignment: Alignment.center, children: [ Container( height: 400, width: 300, color: Colors.red, ),Text('hello,flutter',style: TextStyle(color: Colors.blue),), Container( height: 200, width: 200, color: Colors.yellow, ),Text('hello,flutter',style: TextStyle(color: Colors.green),) ], ); }
Flex
return Container( child: Row( children: [ Expanded( flex: 2, child: Container( width: 100,height: 100, color: Colors.red, )), Expanded( flex: 1, child: Container( width: 100,height: 100, color: Colors.blue, )), ], ), );
positioned
层叠布局和 Web 中的绝对定位、Android 中的 Frame 布局是相似的,子组件可以根据距父容器四个角的位置来确定自身的位置。层叠布局允许子组件按照代码中声明的顺序堆叠起来。Flutter中使用Stack
和Positioned
这两个组件来配合实现绝对定位。Stack
允许子组件堆叠,而Positioned
用于根据Stack
的四个角来确定子组件的位置
return Container( height: 400, width: 300, color: Colors.red, child: Stack( children: [ Positioned( // 改位置的地方 left:0, bottom: 0, child: Container( height: 100, width: 100, color: Colors.yellow, ), ), Text('hello,world'), ], ), );
stack 加 positioned
实现 布局
return Stack( children: [ Positioned( height: 40, width: 40, right: 20, bottom: 20, child: Row( children: [ Expanded( flex: 1, child: Container( alignment: Alignment.center, height: 44, color: Colors.blue, child: Icon(Icons.circle), )) ], ), ) ], );
获取屏幕的高度
final size = MediaQuery.of(context).size; final width = size.width height..一样
aspectRadio
宽高比
// 高度是容器的一半 return AspectRatio(aspectRatio: 2/1, child: Container( color: Colors.red, ), ); }
wrap 布局
需要用padding 包裹
return Padding( // 加 边距 需要在外面加 padding: EdgeInsets.all(10), child: Wrap( // 一行满了之后 换行 spacing: 10, // x axis 水平间距 runSpacing: 10, // y axis 垂直 direction: Axis.horizontal, // 默认 direction: Axis.vertical alignment: WrapAlignment.center, // 看 参数 children: [ Button("chapter one",onPressed: (){},), Button("chapter two",onPressed: (){},), Button("chapter three",onPressed: (){},), Button("chapter four",onPressed: (){},), Button("chapter five",onPressed: (){},), Button("chapter six",onPressed: (){},), Button("chapter seven",onPressed: (){},), Button("chapter eight",onPressed: (){},), ], ), );
demo
import 'package:flutter/material.dart'; class Myapp extends StatelessWidget { const Myapp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'hello flutter', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar(title: Text("flutter app"),), body: LayoutDemo(), ), ); } } class LayoutDemo extends StatelessWidget { const LayoutDemo({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Padding( // 加 边距 需要在外面加 padding: EdgeInsets.all(10), child: Wrap( // 一行满了之后 换行 spacing: 10, // x axis 水平间距 runSpacing: 10, // y axis 垂直 direction: Axis.horizontal, // 默认 direction: Axis.vertical alignment: WrapAlignment.center, // 看 参数 children: [ Button("chapter one",onPressed: (){},), Button("chapter two",onPressed: (){},), Button("chapter three",onPressed: (){},), Button("chapter four",onPressed: (){},), Button("chapter five",onPressed: (){},), Button("chapter six",onPressed: (){},), Button("chapter seven",onPressed: (){},), Button("chapter eight",onPressed: (){},), ], ), ); } } // 自定义按钮 class Button extends StatelessWidget { final String text; final void Function()? onPressed; Button(this.text,{Key? key,required this.onPressed}) : super(key: key); @override Widget build(BuildContext context) { return ElevatedButton( style:ButtonStyle( backgroundColor: MaterialStateProperty.all(Color.fromRGBO(241, 255, 244, 244)), foregroundColor: MaterialStateProperty.all(Colors.black45) ), onPressed: onPressed, child:Text(text)); } } void main(){ runApp( const Myapp() ); }