使用 Flutter 创建自适应应用
Flutter 已被廣泛采用,因為它可以靈活地構建應用程序,以使用一個代碼庫在您的 Android、iOS、macOS 和 Windows 機器上運行。 在大多數情況下,這些設備具有不同的尺寸,盡管 Flutter 具有跨平臺功能,但您不能保證應用程序的界面默認情況下會在這些設備上按預期呈現。 這是您在開發過程中必須考慮的功能。
本文將演示如何使用 Flutter 創建自適應應用。 您將學習如何構建適應給定設備尺寸的基本電子商務應用程序,而無需隨著屏幕尺寸的變化重新構建應用程序。 我們將介紹:
-
什么是自適應應用程序?
-
構建自適應應用程序時要考慮什么
-
使用顫振 LayoutBuilder創建自適應應用程序
-
項目概況
-
教程:使用 Flutter 創建自適應電子商務應用
-
配置
-
建設 Product小部件
-
構建導航抽屜
-
渲染手機屏幕
-
渲染桌面屏幕
-
實施 LayoutBuilder班級
-
什么是自適應應用程序?
當應用程序設計為在運行時根據特定參數更改其屬性值以響應不同的輸入或條件時,它被認為是自適應的。 例如,自適應應用程序使用相同的代碼庫在移動和桌面視圖上呈現不同的界面。
重要的是要注意自適應設計不應與 響應式設計 相混淆。 響應式應用程序會根據可用的屏幕尺寸動態更改其界面布局,但會保持布局設計。 應用程序的內容只是重新排列以適應屏幕大小。
另一方面,自適應設計要求您創建特定于平臺的設計、內容和模板。 也就是說,您的應用程序在移動設備上的設計在更大的屏幕(例如桌面設備)上會有所不同。
構建自適應應用程序時要考慮什么
為了改善用戶體驗,您應該設計您的應用程序以適應具有不同設計、尺寸、形狀和操作系統的不同設備(手機、可折疊設備、平板電腦、智能手表和 PC)。 您的用戶應該能夠在這些不同的設備上探索您的應用程序,并且仍然享受設備和操作系統的原生體驗。
您在設計或開發階段必須做出的一個重要決定是確定應用程序應該切換其布局的閾值。 在 Android 文檔的一部分中, 有一組推薦值,可幫助您決定應用程序在不同屏幕尺寸上的布局。
的影響,屏幕的可用寬度可能比可用高度更重要 在大多數情況下,由于垂直滾動 。 您還需要考慮每個平臺特有的鼠標、鍵盤、觸摸輸入和其他特性。 您應該自定義應用程序的體驗和界面以適應主機設備。
使用顫振 LayoutBuilder創建自適應應用程序
Flutter 提供了 許多 可以在構建自適應應用程序時使用的小部件。 還有一些外部包,例如 Flutter 自適應 UI 和 自適應布局 ,您可以將它們集成到您的應用程序中。 在本文中,我們將重點介紹使用 Flutter 提供的 LayoutBuilder widget構建自適應應用程序。
這 LayoutBuilder類對于構建響應式和自適應應用程序很有用,因為它有一個在布局時調用的構建器函數。 此函數返回一個小部件,接收應用程序上下文和約束,并根據約束的值執行特定操作。 例如,當設備寬度滿足通過 constraints.maxWidth財產:
超過 20 萬開發人員使用 LogRocket 來創造更好的數字體驗 了解更多 →
LayoutBuilder(builder: (ctx, constraints) {if (constraints.maxWidth < 600) {return widget;}else{return anotherWidget;}});
項目概況
本教程的演示應用程序是一個電子商務應用程序,它在可滾動視圖中顯示其產品。 在移動設備上,每個產品都會占用可用的寬度,用戶可以垂直滾動屏幕以查看每個可用的產品。 移動視圖還將包含一個帶有導航按鈕的應用程序抽屜。
在更大的屏幕上,例如在桌面設備上,產品分布在屏幕的寬度和高度上。 桌面視圖還將在屏幕頂部包含一個導航欄,以替換移動視圖中的應用程序抽屜。
如前所述,應用程序將使用 Flutter LayoutBuilder class確保它在運行時根據可用的屏幕大小呈現指定的界面,而無需重新構建應用程序。
這是應用程序在不同屏幕尺寸上的預期輸出:
先決條件
-
基礎知識 Flutter
-
上 Flutter SDK 安裝在你的機器
-
您選擇的任何合適的 IDE; 我將使用 Android Studio 進行此演示
教程:使用 Flutter 創建自適應電子商務應用
配置
打開您的終端并運行以下命令以創建引導的 Flutter 項目,然后在您首選的 IDE 中打開該項目。
flutter create shop_app在里面 lib文件夾,創建兩個包—— widgets和 screens— 將分別包含應用程序小部件和屏幕的 Dart 文件。
創建一個 dummy_data.dart文件中 lib文件夾,然后將 本教程的 GitHub 存儲庫中的內容 復制到該文件中。 您將使用此文件生成 Product后續部分中的小部件。
來自 LogRocket 的更多精彩文章:
-
不要錯過 The Replay 來自 LogRocket 的精選時事通訊
-
使用 React 的 useEffect 優化應用程序的性能
-
之間切換 在多個 Node 版本
-
了解如何 使用 AnimXYZ 為您的 React 應用程序制作動畫
-
探索 Tauri ,一個用于構建二進制文件的新框架
-
比較 NestJS 與 Express.js
-
發現 TypeScript 領域中使用的流行 ORM
建設 Product小部件
這 Product小部件代表應用程序上每個產品項目的模板。 在里面 widgets打包,創建一個 product.dart文件并添加以下代碼:
import 'package:flutter/material.dart'; ? class Product extends StatelessWidget {final String id;final String name;final Color color;final String imageUrl;final double price; ?const Product({required this.id,required this.name,this.color = Colors.amberAccent,required this.imageUrl,required this.price}); }這里是 build小部件的方法:
@overrideWidget build(BuildContext context) {return InkWell(onTap: () => (){},child: Card(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),elevation: 4,margin: EdgeInsets.fromLTRB(15, 20, 15, 20),child: Column(children: [Expanded(child: Stack(children: [ClipRRect(borderRadius: const BorderRadius.only(topLeft: Radius.circular(15),topRight: Radius.circular(15)),child: Image.network(imageUrl,height: 250,width: double.infinity,fit: BoxFit.cover,),),Positioned(bottom: 20,right: 10,child: Container(color: ?Colors.black54,width: 300,padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 20),child: Text(name,style: const TextStyle(fontSize: 18,color: Colors.white,fontWeight: FontWeight.bold),softWrap: true,overflow: TextOverflow.fade,),),)],),),Padding(padding: const EdgeInsets.all(20.0),child:Row(children: [const Icon(Icons.attach_money),const SizedBox(width: 6),Text('$price')],),),],),),);}上面的小部件使用了 Flutter 類和小部件的組合,包括:
-
InkWell 類 增強應用程序用戶體驗的
-
將 疊放的堆棧 小部件相互
-
的 Positioned小部件 將產品名稱放置在特定位置
這是輸出 Product小部件:
構建導航抽屜
將 導航抽屜 專門用于應用程序的移動視圖中; 也就是說,應用程序將在移動設備上打開時呈現抽屜。 內 widgets打包,創建一個名為的 Dart 文件 navigation_drawer并在文件中包含以下代碼:
import 'package:flutter/material.dart'; ? class NavigationDrawer extends StatelessWidget {const NavigationDrawer({Key? key}) : super(key: key); ?Widget buildListTile(String title, IconData icon){return ListTile(leading: Icon(icon,size: 26,),title: Text(title,style: const TextStyle(fontSize: 14,fontWeight: FontWeight.bold),),onTap: () {},);} ?@overrideWidget build(BuildContext context) {return Drawer(child: Column(children: [Container(height: 100,padding: EdgeInsets.all(20),alignment: Alignment.bottomCenter,color: Theme.of(context).accentColor,child: Text('App Menu',style: TextStyle(fontWeight: FontWeight.w900,fontSize: 20,color: Theme.of(context).primaryColor,),),),const SizedBox(height: 20),buildListTile('Home', Icons.home),buildListTile('About', Icons.info_outline),buildListTile('Contact', Icons.contact_phone_outlined),buildListTile('Order', Icons.shopping_cart),],),);} }從上面的代碼中, buildListTile方法為抽屜中的特定項目構建一個 ListTile 小部件 ,在這種情況下, Home, About, Contact, 和 Order.
國外小游戲網站(crazygames.com),游戲數量超豐富,全程無卡頓超快!
渲染手機屏幕
Next, create the screen to render the mobile view of the application. In the screens package, create a Dart file with the name mobile_product_view并在文件中包含以下代碼片段:
import 'package:flutter/material.dart'; import 'package:shop_app/widgets/product.dart'; ? import '../dummy_data.dart'; import '../widgets/navigation_drawer.dart'; ? class MobileProductView extends StatelessWidget {final String title; ?const MobileProductView({Key? key, required this.title}) : super(key: key); ?@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(title),),drawer: NavigationDrawer(),body: ?GridView.count(crossAxisCount: 1,children: DUMMY_DATA.map((product) =>Product(id: product.id, name: product.name, imageUrl: product.imageUrl, color: product.color, price: product.price)).toList(),));} }上面的代碼顯示了應用程序使用來自 dummy_data.dart文件來建立一個列表 Product呈現為 GridView 的小部件。
渲染桌面屏幕
本節將包含應用程序桌面視圖的實現。 創建一個名稱為 Dart 的文件 desktop_product_view在里面 screens包裹。 將以下代碼添加到文件中:
import 'package:flutter/material.dart'; import 'package:shop_app/widgets/product.dart'; ? import '../dummy_data.dart'; ? class DesktopProductView extends StatelessWidget {final String title;final int crossAxisCount; ?const DesktopProductView({Key? key, required this.title, required this.crossAxisCount}) : super(key: key);@overrideWidget build(BuildContext context) { ?Widget getAction(String actionName){return TextButton(onPressed: () {},child: Text(actionName,style: TextStyle(color: Theme.of(context).accentColor,fontWeight: FontWeight.w500),),);} ?return Scaffold(appBar: AppBar(title: Text(title),actions: [Padding(padding: const EdgeInsets.only(right: 100.0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [getAction('Home'),getAction('About'),getAction('Contact'),getAction('Order'),],),)],),body: Padding(padding: const EdgeInsets.all(18.0),child: GridView.count(crossAxisCount: crossAxisCount,children: DUMMY_DATA.map((product) =>Product(id: product.id,name: product.name,imageUrl: product.imageUrl,color: product.color,price: product.price)).toList(),),),);} }從上面的代碼中,小部件接收到 crossAxisCount值通過它的構造函數。 使用此值,它指定的數量 Product要在其中呈現的小部件 GridView在運行時。
中的動作 AppBar小部件將替換您為移動視圖創建的抽屜。 使用 getAction方法,您為 AppBar.
實施 LayoutBuilder班級
的實施 LayoutBuilder課程將在 main.dart文件。 這是因為我們將應用程序的整個屏幕設計為自適應的。 因此, LayoutBuilder應該從小部件的最外層構建界面,在這種情況下,它被放置在 main.dart文件。
這是您應該添加到 main.dart文件:
import 'package:flutter/material.dart'; import 'package:shop_app/screens/mobile_product_view.dart'; ? import 'screens/desktop_product_view.dart'; ? void main() {runApp(const MyApp()); } ? class MyApp extends StatelessWidget {const MyApp({super.key}); ?@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.purple,accentColor: Colors.amber),home: const MyHomePage(title: 'Flutter adaptive app'),);} } ? class MyHomePage extends StatefulWidget {const MyHomePage({super.key, required this.title});final String title; ?@overrideState<MyHomePage> createState() => _MyHomePageState(); } ? class _MyHomePageState extends State<MyHomePage> { ?@overrideWidget build(BuildContext context) {return LayoutBuilder(builder: (ctx, constraints){if(constraints.maxWidth < 600){return MobileProductView(title: widget.title);}int crossAxisCount = 0;if(constraints.maxWidth > 1400) {crossAxisCount = 4;} else if(constraints.maxWidth > 900) {crossAxisCount = 3;} else if (constraints.maxWidth >= 600) {crossAxisCount = 2;}return DesktopProductView(title: widget.title, crossAxisCount: crossAxisCount);});} }這 build的方法 MyHomePage小部件使用 LayoutBuilder基于以下約束:
-
如果設備屏幕的寬度小于 600 像素,則構建 MobileProductView,它代表您在上一節中為移動設備創建的界面
-
如果設備屏幕的寬度大于 600 像素,則構建 DesktopProductView但與指定 crossAxisCount,取決于設備寬度,如代碼所示
如果您打算只使應用程序的特定部分而不是如上所示的整個屏幕自適應,則必須實現 LayoutBuilder在小部件的所需部分。
結論
使您的應用程序適應不同的操作系統和設備屏幕尺寸是改善其用戶體驗的好方法。 本教程演示了如何使用 Flutter 使您的應用程序自適應 LayoutBuilder班級。 其他選項,例如 自適應布局包。 如文章開頭所述,在構建自適應應用程序時,您還可以采用
本教程中構建的項目可在 GitHub 上找到。 我還建議您瀏覽 Flutter 文檔,以更廣泛地了解如何在應用程序的不同部分構建自適應布局。
總結
以上是生活随笔為你收集整理的使用 Flutter 创建自适应应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows怎样让宽带自动连接
- 下一篇: 我是如何拿到腾讯头条美团小米的offer