Flutter ile Duyarlı Web ve Masaüstü Geliştirme

Yayınlanan: 2022-03-10
Kısa özet ↬ Flutter, mobil geliştirme sahnesinde şimdiden büyük bir sıçrama yaptı. Şimdi daha büyük cihazları da alıyor. İşte bu harika platformlar arası çerçeveyi kullanarak web ve masaüstü uygulamaları geliştirme görevini üstlenmeye hazır olmak için bilmeniz gerekenler.

Bu eğitim, Flutter'ın kendisine bir giriş değildir. Flutter'ın temellerini öğrenmenize yardımcı olacak basit tanıtımlarla çevrimiçi olarak sunulan çok sayıda makale, video ve birkaç kitap var. Bunun yerine, aşağıdaki iki hedefi ele alacağız:

  1. Flutter'ın mobil olmayan geliştirmesinin mevcut durumu ve Flutter kodunu bir masaüstü veya dizüstü bilgisayarda tarayıcıda nasıl çalıştırabileceğiniz;
  2. Flutter kullanarak duyarlı uygulamalar nasıl oluşturulur, böylece gücünü - özellikle bir web çerçevesi olarak - tam ekranda görebilirsiniz ve URL'ye dayalı yönlendirme hakkında bir notla biter.

Hadi içeri girelim!

Flutter Nedir, Neden Önemlidir, Neye Evrildi, Nereye Gidiyor?

Flutter, Google'ın en son uygulama geliştirme çerçevesidir. Google, her şeyi kapsayıcı olmasını öngörüyor: Aynı kodun tüm markaların akıllı telefonlarında, tabletlerde ve masaüstü ve dizüstü bilgisayarlarda yerel uygulamalar veya web sayfaları olarak yürütülmesini sağlayacak.

Bu çok iddialı bir proje, ancak Google şimdiye kadar özellikle iki açıdan inanılmaz derecede başarılı oldu: Android ve iOS yerel uygulamaları için gerçekten platformdan bağımsız, harika çalışan ve üretim kullanımına tamamen hazır bir çerçeve oluşturma ve etkileyici bir cephe oluşturma. - Kodun %100'ünü uyumlu bir Flutter uygulamasıyla paylaşabilen son web çerçevesi.

Bir sonraki bölümde, uygulamayı neyin uyumlu kıldığını ve şu an itibariyle mobil olmayan Flutter geliştirmenin durumunu göreceğiz.

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Flutter ile Mobil Olmayan Geliştirme

Flutter ile mobil olmayan geliştirme, ilk olarak Google I/O 2019'da önemli bir şekilde duyuruldu. Bu bölüm, nasıl çalıştırılacağı ve ne zaman çalıştığı hakkındadır.

Web ve Masaüstü Geliştirme Nasıl Etkinleştirilir

Web geliştirmeyi etkinleştirmek için öncelikle Flutter'ın beta kanalında olmanız gerekir. Bu noktaya ulaşmanın iki yolu vardır:

  • SDK arşivinden uygun en son beta sürümünü indirerek Flutter'ı doğrudan beta kanalına kurun.
  • Flutter'ı zaten yüklediyseniz, $ flutter channel beta ile beta kanalına geçin ve ardından Flutter sürümünüzü (aslında Flutter kurulum klasöründe bir git pull olan) $ flutter upgrade ile güncelleyerek geçişin kendisini gerçekleştirin.

Bundan sonra şunu çalıştırabilirsiniz:

 $ flutter config --enable-web

Masaüstü desteği, özellikle Linux ve Windows için araç eksikliği nedeniyle, eklenti geliştirmeyi özellikle büyük bir sorun haline getirdiğinden ve bunun için kullanılan API'lerin kavram kanıtı kullanımına yönelik olması nedeniyle çok daha deneyseldir. üretim. Bu, Windows ve Linux yerel masaüstü uygulamaları için bile desteklenmeyen sürüm derlemeleri için denenmiş ve test edilmiş dart2js derleyicisini kullanan web geliştirmeden farklıdır.

Not : macOS desteği, Windows ve Linux desteğinden biraz daha iyidir, ancak yine de web desteği kadar iyi değil ve neredeyse mobil platformlar için tam destek kadar iyi değil.

Masaüstü geliştirme desteğini etkinleştirmek için, daha önce beta kanalı için özetlenen adımların aynısını izleyerek master yayın kanalına geçmeniz gerekir. Ardından, <OS_NAME> yerine linux , windows veya macos ile değiştirerek aşağıdakileri çalıştırın:

 $ flutter config --enable-<OS_NAME>-desktop

Bu noktada, Flutter aracı yapması gerektiğini söylediğim şeyi yapmadığı için açıklayacağım aşağıdaki adımlardan herhangi birinde sorun yaşıyorsanız, bazı yaygın sorun giderme adımları şunlardır:

  • Sorunları kontrol etmek için flutter doctor çalıştırın. Bu Flutter komutunun bir yan etkisi, ihtiyaç duyduğu ve sahip olmadığı araçları indirmesidir.
  • flutter upgrade çalıştırın.
  • Kapatıp tekrar açın. Bilgisayarınızı yeniden başlatmanın eski 1. kademe teknik destek yanıtı, Flutter'ın tüm zenginliklerinden yararlanabilmeniz için tam da ihtiyacınız olan şey olabilir.

Flutter Web Uygulamalarını Çalıştırma ve Oluşturma

Flutter web desteği hiç de fena değil ve bu, web için geliştirme kolaylığına yansıyor.

Bunu çalıştırmak…

 $ flutter devices

… bunun gibi bir şey için hemen bir giriş göstermelidir:

 Web Server • web-server • web-javascript • Flutter Tools

Ek olarak, Chrome tarayıcısını çalıştırmak, Flutter'ın bunun için de bir giriş göstermesine neden olmalıdır. Flutter'ı uyumlu bir Flutter projesinde flutter run (daha sonra bahsedeceğiz), görünen tek "bağlı cihaz" web sunucusu olduğunda Flutter'ın localhost:<RANDOM_PORT> üzerinde bir web sunucusu başlatmasına neden olur, bu da Flutter'ınıza erişmenizi sağlar herhangi bir tarayıcıdan web uygulaması.

Chrome'u yüklediyseniz ancak görünmüyorsa, Chrome yürütülebilir dosyasının yoluna CHROME_EXECUTABLE ortam değişkenini ayarlamanız gerekir.

Flutter Masaüstü Uygulamalarını Çalıştırma ve Oluşturma

Flutter masaüstü desteğini etkinleştirdikten sonra, flutter run -d <OS_NAME> ile geliştirme iş istasyonunuzda yerel olarak bir Flutter uygulaması çalıştırabilir, <OS_NAME> OS_NAME> yerine masaüstü desteğini etkinleştirirken kullandığınız değerle değiştirebilirsiniz. Ayrıca flutter build <OS_NAME> ile build dizininde ikili dosyalar oluşturabilirsiniz.

Ancak bunlardan herhangi birini yapmadan önce, Flutter'ın platformunuz için oluşturması gerekenleri içeren bir dizine sahip olmanız gerekir. Bu, yeni bir proje oluşturduğunuzda otomatik olarak oluşturulacaktır, ancak onu flutter create . . Ayrıca, Linux ve Windows API'leri kararsızdır, bu nedenle uygulama bir Flutter güncellemesinden sonra çalışmayı durdurursa bunları bu platformlar için yeniden oluşturmanız gerekebilir.

Bir Uygulama Ne Zaman Uyumludur?

Bir Flutter uygulamasının masaüstünde veya web'de çalışabilmesi için "uyumlu bir proje" olması gerektiğini söylerken başından beri ne demek istedim? Basitçe söylemek gerekirse, oluşturmaya çalıştığınız platform için platforma özel bir uygulaması olmayan herhangi bir eklenti kullanmaması gerektiğini kastediyorum.

Bu noktayı herkes için kesinlikle netleştirmek ve yanlış anlaşılmayı önlemek için, lütfen Flutter eklentisinin , özelliklerini sağlaması için gerekli olan platforma özel kodu içeren belirli bir Flutter paketi olduğunu unutmayın.

Örneğin, Google tarafından geliştirilen url_launcher paketini istediğiniz kadar kullanabilirsiniz (ve web'in köprüler üzerine kurulu olduğu göz önüne alındığında, isteyebilirsiniz).

Kullanımı web geliştirmeyi engelleyebilecek, Google tarafından geliştirilen bir pakete örnek, dosyaların kaydedileceği yerel depolama yolunu almak için kullanılan path_provider . Bu, tesadüfen, bir web uygulaması için herhangi bir şekilde kullanılmayan bir paket örneğidir, bu nedenle, kodunuzu değiştirmek için kodunuzu değiştirmeniz gerektiği gerçeği dışında, onu kullanamamak gerçekten bir serseri değildir. kullanıyorsanız, web'de çalışması için.

Örneğin, web'de HTML localStorage dayanan shared_preferences paketini kullanabilirsiniz.

Benzer uyarılar masaüstü platformları için de geçerlidir: Çok az eklenti masaüstü platformlarıyla uyumludur ve bu yinelenen bir tema olduğundan, bu konuda Web için Flutter'da gerçekten gerekli olandan çok daha fazla çalışmanın masaüstü tarafında yapılması gerekir.

Flutter'da Duyarlı Düzenler Oluşturma

Yukarıda açıkladıklarımdan ve basitlik için, bu yazının geri kalanında hedef platformunuzun web olduğunu varsayacağım, ancak temel kavramlar masaüstü geliştirme için de geçerlidir.

Web'i desteklemenin yararları ve sorumlulukları vardır. Farklı ekran boyutlarını desteklemeye zorlanmış olmak bir dezavantaj gibi görünebilir, ancak uygulamayı web tarayıcılarında çalıştırmanın, uygulamanızın farklı boyut ve en boy oranlarındaki ekranlarda nasıl görüneceğini ayrı ayrı çalıştırmanıza gerek kalmadan çok kolay bir şekilde görmenizi sağladığını düşünün. mobil cihaz emülatörleri.

Şimdi koddan bahsedelim. Uygulamanızı nasıl duyarlı hale getirebilirsiniz?

Bu analizin yapıldığı iki bakış açısı vardır:

  1. "Farklı boyutlardaki ekranlara uyum sağlayabilen veya uyarlaması gereken hangi widget'ları kullanıyorum veya kullanabilir miyim?"
  2. “Ekranın boyutu hakkında nasıl bilgi alabilirim ve bunu UI kodu yazarken nasıl kullanabilirim?”

İlk soruyu sonra cevaplayacağız. Önce ikincisinden bahsedelim çünkü çok kolay halledilebilir ve meselenin merkezinde yer alır. Bunu yapmanın iki yolu vardır:

  1. Bir yol, bir Flutter uygulamasının çalışması için widget ağacında bulunması gereken MediaQuery kökü InheritedWidget MediaQueryData öğesinden bilgi almaktır (bu, MaterialApp/WidgetsApp/CupertinoApp bir parçasıdır), tıpkı aşağıdaki gibi Size türünde bir size özelliğine sahip olan ve bu nedenle double türünde iki width ve height özelliğine sahip olan MediaQuery.of(context) içeren herhangi bir InheritedWidget .
  2. Diğer yol, builder işlevine ( context birlikte) geçen bir oluşturucu pencere aracı olan (tıpkı StreamBuilder veya FutureBuilder gibi) bir LayoutBuilder minWidth LayoutBuilder minHeight maxHeight maxWidth bir BoxConstraints nesnesi.

Kısıtlamaları almak için MediaQuery kullanan bir DartPad örneği, kodu aşağıdaki gibidir:

 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: MyHomePage() ); } class MyHomePage extends StatelessWidget { @override Widget build(context) => Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Text( "Width: ${MediaQuery.of(context).size.width}", style: Theme.of(context).textTheme.headline4 ), Text( "Height: ${MediaQuery.of(context).size.height}", style: Theme.of(context).textTheme.headline4 ) ] ) ) ); }

Ve işte aynı şey için LayoutBuilder kullanan bir tane:

 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: MyHomePage() ); } class MyHomePage extends StatelessWidget { @override Widget build(context) => Scaffold( body: LayoutBuilder( builder: (context, constraints) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Text( "Width: ${constraints.maxWidth}", style: Theme.of(context).textTheme.headline4 ), Text( "Height: ${constraints.maxHeight}", style: Theme.of(context).textTheme.headline4 ) ] ) ) ) ); }

Şimdi hangi widget'ların kısıtlamalara uyum sağlayabileceğini düşünelim.

Öncelikle, ekranın boyutuna göre birden çok widget'ı yerleştirmenin farklı yollarını düşünelim.

En kolay uyarlanan pencere öğesi GridView . Aslında, bu çok basit örnekte görebileceğiniz gibi, GridView.extent yapıcısı kullanılarak oluşturulan bir GridView duyarlı hale getirilmesi için katılımınıza bile ihtiyacı yoktur:

 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: MyHomePage() ); } class MyHomePage extends StatelessWidget { final List elements = [ "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit" ]; @override Widget build(context) => Scaffold( body: GridView.extent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, children: elements.map((el) => Card(child: Center(child: Padding(padding: EdgeInsets.all(8.0), child: Text(el))))).toList() ) ); } import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: MyHomePage() ); } class MyHomePage extends StatelessWidget { final List elements = [ "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit" ]; @override Widget build(context) => Scaffold( body: GridView.extent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, children: elements.map((el) => Card(child: Center(child: Padding(padding: EdgeInsets.all(8.0), child: Text(el))))).toList() ) ); }

maxCrossAxisExtent değiştirerek farklı boyutlardaki içeriği barındırabilirsiniz.

Bu örnek çoğunlukla GridView.extent GridView yapıcısının varlığını gösterme amacına hizmet etti, ancak bunu yapmanın çok daha akıllı bir yolu, bu durumda widget'ların ızgarada gösterileceği SliverGridDelegateWithMaxCrossAxisExtent ile bir GridView.builder kullanmak olacaktır. bu örnekte görebileceğiniz gibi, başka bir veri yapısından dinamik olarak oluşturulur:

 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: MyHomePage() ); } class MyHomePage extends StatelessWidget { final List<String> elements = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit"]; @override Widget build(context) => Scaffold( body: GridView.builder( itemCount: elements.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, ), itemBuilder: (context, i) => Card( child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: Text(elements[i]) ) ) ) ) ); }

Farklı ekranlara uyum sağlayan bir GridView örneği, Cards biraz daha karmaşık ve daha büyük olması dışında, tıpkı önceki örnek kodda olduğu gibi, bir grup Cards içeren bir GridView içeren çok basit bir Flutter web uygulaması olan kişisel açılış sayfamdır. .

Telefonlar için tasarlanmış uygulamalarda yapılabilecek çok basit bir değişiklik, yer olduğunda Çekmeceyi soldaki kalıcı bir Drawer değiştirmek olacaktır.

Örneğin, gezinme için kullanılan aşağıdaki gibi bir widget'ların ListView sahip olabiliriz:

 class Menu extends StatelessWidget { @override Widget build(context) => ListView( children: [ FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_one), title: Text("First Link"), ) ), FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_two), title: Text("Second Link"), ) ) ] ); }

Bir akıllı telefonda, Drawer içinde (hamburger menüsü olarak da bilinir) ortak bir kullanım yeri bulunur.

Bunun alternatifleri, TabBarView ile kombinasyon halinde BottomNavigationBar veya TabBar TabBarView , ancak her ikisinde de çekmecede gerekenden daha fazla değişiklik yapmamız gerekecek, bu yüzden çekmeceye bağlı kalacağız.

Daha önce daha küçük ekranlarda gördüğümüz Menu içeren Drawer göstermek için, aşağıdaki kod parçasına benzeyen bir kod yazar, Scaffold MediaQuery.of(context) kullanarak genişliği kontrol eder ve yalnızca bir Drawer nesnesini İskeleye iletirsiniz. uygulamamız için uygun olduğuna inandığımız bir genişlik değerinden daha az:

 Scaffold( appBar: AppBar(/* ... \*/), drawer: MediaQuery.of(context).size.width < 500 ? Drawer( child: Menu(), ) : null, body: /* ... \*/ )

Şimdi Scaffold body düşünelim. Uygulamamızın örnek ana içeriği olarak, daha önce oluşturduğumuz ve karışıklığı önlemek için Content adlı ayrı bir pencere öğesinde tuttuğumuz GridView kullanacağız:

 class Content extends StatelessWidget { final List elements = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit"]; @override Widget build(context) => GridView.builder( itemCount: elements.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, ), itemBuilder: (context, i) => Card( child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: Text(elements[i]) ) ) ) ); } class Content extends StatelessWidget { final List elements = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit"]; @override Widget build(context) => GridView.builder( itemCount: elements.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, ), itemBuilder: (context, i) => Card( child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: Text(elements[i]) ) ) ) ); }

Daha büyük ekranlarda, gövdenin kendisi iki widget gösteren bir Row olabilir: sabit bir genişlikle sınırlandırılmış Menu ve ekranın geri kalanını dolduran Content .

Daha küçük ekranlarda, tüm body Content olacaktır.

Her şeyi bir SafeArea ve bir Center pencere aracına saracağız, çünkü bazen Flutter web uygulaması pencere öğeleri, özellikle Row s ve Column s kullanılırken, görünür ekran alanının dışında kalır ve bu, SafeArea ve/veya Center ile düzeltilir.

Bu, Scaffold body aşağıdaki gibi olacağı anlamına gelir:

 SafeArea( child:Center( child: MediaQuery.of(context).size.width < 500 ? Content() : Row( children: [ Container( width: 200.0, child: Menu() ), Container( width: MediaQuery.of(context).size.width-200.0, child: Content() ) ] ) ) )

İşte bunların hepsi bir araya getirildi:

(Büyük önizleme)
 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: HomePage() ); } class HomePage extends StatelessWidget { @override Widget build(context) => Scaffold( appBar: AppBar(title: Text("test")), drawer: MediaQuery.of(context).size.width < 500 ? Drawer( child: Menu(), ) : null, body: SafeArea( child:Center( child: MediaQuery.of(context).size.width < 500 ? Content() : Row( children: [ Container( width: 200.0, child: Menu() ), Container( width: MediaQuery.of(context).size.width-200.0, child: Content() ) ] ) ) ) ); } class Menu extends StatelessWidget { @override Widget build(context) => ListView( children: [ FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_one), title: Text("First Link"), ) ), FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_two), title: Text("Second Link"), ) ) ] ); } class Content extends StatelessWidget { final List<String> elements = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit"]; @override Widget build(context) => GridView.builder( itemCount: elements.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, ), itemBuilder: (context, i) => Card( child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: Text(elements[i]) ) ) ) ); }

Bu, Flutter'daki duyarlı kullanıcı arayüzüne genel bir giriş olarak ihtiyaç duyacağınız şeylerin çoğu. Uygulamasının çoğu, uygulamanızın özel kullanıcı arayüzüne bağlı olacaktır ve uygulamanızı duyarlı hale getirmek için tam olarak ne yapabileceğinizi belirlemek zordur ve tercihinize bağlı olarak birçok yaklaşımda bulunabilirsiniz. Şimdi, ortak uygulama öğelerini ve UI akışlarını düşünerek, duyarlı bir uygulamaya nasıl daha eksiksiz bir örnek oluşturabileceğimizi görelim.

Bağlamına Yerleştirmek: Bir Uygulamayı Duyarlı Hale Getirmek

Şimdiye kadar sadece bir ekranımız var. Bunu, çalışan URL tabanlı gezinme ile iki ekranlı bir uygulamaya genişletelim!

Duyarlı Giriş Sayfası Oluşturma

Uygulamanızın bir giriş sayfası olma ihtimali yüksektir. Bunu nasıl duyarlı hale getirebiliriz?

Mobil cihazlarda giriş ekranları genellikle birbirine oldukça benzer. Kullanılabilir alan fazla değil; genellikle sadece widget'larının etrafında bir miktar Padding bulunan bir Column ve bir kullanıcı adı ve parola yazmak için TextField s ve oturum açmak için bir düğme içerir. Yani, oldukça standart (diğer şeylerin yanı sıra, bunun gerektirdiği gibi çalışmıyor olsa da) , bir mobil uygulama için her TextField için bir TextEditingController ) giriş sayfası aşağıdaki olabilir:

 Scaffold( body: Container( padding: const EdgeInsets.symmetric( vertical: 30.0, horizontal: 25.0 ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Text("Welcome to the app, please log in"), TextField( decoration: InputDecoration( labelText: "username" ) ), TextField( obscureText: true, decoration: InputDecoration( labelText: "password" ) ), RaisedButton( color: Colors.blue, child: Text("Log in", style: TextStyle(color: Colors.white)), onPressed: () {} ) ] ), ), )

Bir mobil cihazda iyi görünüyor, ancak bu çok geniş TextField daha büyük bir ekran bir yana, tablette bile sarsıcı görünmeye başlıyor. Ancak, telefonların farklı ekran boyutları olduğu için sabit bir genişliğe karar veremiyoruz ve bir dereceye kadar esnekliği korumalıyız.

Örneğin, deney yoluyla, maksimum genişliğin 500 olması gerektiğini bulabiliriz. Peki, Container constraints 500'e ayarlardık (önceki örnekte Padding yerine bir Container kullandım çünkü bununla nereye gideceğimi biliyordum. ) ve gitmeye hazırız, değil mi? Pek değil, çünkü bu, oturum açma widget'larının ekranın sol tarafına yapışmasına neden olur ve bu, her şeyi uzatmaktan bile daha kötü olabilir. Bu nedenle, aşağıdaki gibi bir Center widget'ına sarıyoruz:

 Center( child: Container( constraints: BoxConstraints(maxWidth: 500), padding: const EdgeInsets.symmetric( vertical: 30.0, horizontal: 25.0 ), child: Column(/* ... \*/) ) )

Bu zaten iyi görünüyor ve ne LayoutBuilder ne de MediaQuery.of MediaQuery.of(context).size kullanmak zorunda kalmadık. Yine de bunun çok iyi görünmesi için bir adım daha ileri gidelim. Ön plan kısmı arka plandan bir şekilde ayrılmış olsaydı, bence daha iyi görünürdü. Bunu, girdi widget'ları ile Container arkasında ne olduğuna bir arka plan rengi vererek ve ön plan Container beyaz tutarak başarabiliriz. Biraz daha iyi görünmesini sağlamak için, Container büyük cihazlarda ekranın üstüne ve altına doğru esnemesini engelleyelim, köşeleri yuvarlatalım ve iki düzen arasında ona güzel bir animasyonlu geçiş yapalım.

Artık bunların tümü, hem arka plan rengini ayarlamak hem de yalnızca daha büyük ekranlarda yanlara değil, Container her tarafına dolgu eklemek için bir LayoutBuilder ve bir dış Container gerektirir. Ayrıca, dolgu miktarındaki değişikliği animasyonlu hale getirmek için, bu dış Container bir AnimatedContainer çevirmemiz yeterlidir; bu, animasyon için bir duration gerektirir, bu da yarım saniyeye ayarlayacağız, yani Duration(milliseconds: 500) kod.

İşte duyarlı bir giriş sayfası örneği:

(Büyük önizleme)
 class LoginPage extends StatelessWidget { @override Widget build(context) => Scaffold( body: LayoutBuilder( builder: (context, constraints) { return AnimatedContainer( duration: Duration(milliseconds: 500), color: Colors.lightGreen[200], padding: constraints.maxWidth < 500 ? EdgeInsets.zero : EdgeInsets.all(30.0), child: Center( child: Container( padding: EdgeInsets.symmetric( vertical: 30.0, horizontal: 25.0 ), constraints: BoxConstraints( maxWidth: 500, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(5.0), ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Text("Welcome to the app, please log in"), TextField( decoration: InputDecoration( labelText: "username" ) ), TextField( obscureText: true, decoration: InputDecoration( labelText: "password" ) ), RaisedButton( color: Colors.blue, child: Text("Log in", style: TextStyle(color: Colors.white)), onPressed: () { Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => HomePage() ) ); } ) ] ), ), ) ); } ) ); }

Gördüğünüz gibi, RaisedButton 'ın onPressed , bizi HomePage adlı bir ekrana yönlendiren bir geri aramaya değiştirdim (bu, örneğin, daha önce GridView ve bir menü veya çekmece ile oluşturduğumuz görünüm olabilir). Şimdi, yine de, bu navigasyon kısmı, odaklanacağımız şey.

Adlandırılmış Rotalar: Uygulamanızın Navigasyonunu Daha Uygun Bir Web Uygulaması Gibi Hale Getirme

Web uygulamalarının sahip olduğu yaygın bir şey, ekranları URL'ye göre değiştirme yeteneğidir. Örneğin, https://appurl/login somethingelse'den farklı bir şey https://appurl/somethingelse . Aslında Flutter, iki amacı olan adlandırılmış rotaları destekler:

  1. Bir web uygulamasında, bir önceki cümlede bahsettiğim özelliğe tam olarak sahipler.
  2. Herhangi bir uygulamada, uygulamanız için rotaları önceden tanımlamanıza ve onlara adlar vermenize ve ardından yalnızca adlarını belirterek onlara gitmenize olanak tanırlar.

Bunu yapmak için MaterialApp yapıcısını aşağıdakine benzer bir şekilde değiştirmemiz gerekiyor:

 MaterialApp( initialRoute: "/login", routes: { "/login": (context) => LoginPage(), "/home": (context) => HomePage() } );

Ardından Navigator.push(context, route Navigator.push(context, route) ve Navigator.pushReplacement(context, route) (context, route) yerine Navigator.pushNamed(context, routeName) ve Navigator.pushReplacementNamed(context, routeName) kullanarak farklı bir rotaya geçebiliriz.

İşte bu makalenin geri kalanında oluşturduğumuz varsayımsal uygulamaya uygulananlar. DartPad'de eylemdeki adlandırılmış yolları gerçekten göremezsiniz, bu nedenle bunu kendi makinenizde flutter run ile denemeli veya örneği çalışırken kontrol etmelisiniz:

(Büyük önizleme)
 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( initialRoute: "/login", routes: { "/login": (context) => LoginPage(), "/home": (context) => HomePage() } ); } class LoginPage extends StatelessWidget { @override Widget build(context) => Scaffold( body: LayoutBuilder( builder: (context, constraints) { return AnimatedContainer( duration: Duration(milliseconds: 500), color: Colors.lightGreen[200], padding: constraints.maxWidth < 500 ? EdgeInsets.zero : const EdgeInsets.all(30.0), child: Center( child: Container( padding: const EdgeInsets.symmetric( vertical: 30.0, horizontal: 25.0 ), constraints: BoxConstraints( maxWidth: 500, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(5.0), ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Text("Welcome to the app, please log in"), TextField( decoration: InputDecoration( labelText: "username" ) ), TextField( obscureText: true, decoration: InputDecoration( labelText: "password" ) ), RaisedButton( color: Colors.blue, child: Text("Log in", style: TextStyle(color: Colors.white)), onPressed: () { Navigator.pushReplacementNamed( context, "/home" ); } ) ] ), ), ) ); } ) ); } class HomePage extends StatelessWidget { @override Widget build(context) => Scaffold( appBar: AppBar(title: Text("test")), drawer: MediaQuery.of(context).size.width < 500 ? Drawer( child: Menu(), ) : null, body: SafeArea( child:Center( child: MediaQuery.of(context).size.width < 500 ? Content() : Row( children: [ Container( width: 200.0, child: Menu() ), Container( width: MediaQuery.of(context).size.width-200.0, child: Content() ) ] ) ) ) ); } class Menu extends StatelessWidget { @override Widget build(context) => ListView( children: [ FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_one), title: Text("First Link"), ) ), FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_two), title: Text("Second Link"), ) ), FlatButton( onPressed: () {Navigator.pushReplacementNamed( context, "/login");}, child: ListTile( leading: Icon(Icons.exit_to_app), title: Text("Log Out"), ) ) ] ); } class Content extends StatelessWidget { final List<String> elements = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit"]; @override Widget build(context) => GridView.builder( itemCount: elements.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, ), itemBuilder: (context, i) => Card( child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: Text(elements[i]) ) ) ) ); }

Flutter Maceranızla İlerleyin

Bu size Flutter ile daha büyük ekranlarda, özellikle de web'de neler yapabileceğiniz konusunda bir fikir verecektir. Çok hoş bir çerçeve, kullanımı çok kolay ve platformlar arası aşırı desteği, öğrenmeyi ve kullanmaya başlamayı daha da gerekli kılıyor. Öyleyse devam edin ve web uygulamaları için de Flutter'a güvenmeye başlayın!

Diğer Kaynaklar

  • "Masaüstü kabukları", GitHub
    Flutter'ın masaüstünde mevcut, her zaman güncel durumu
  • Flutter için masaüstü desteği, Flutter
    Tam olarak desteklenen masaüstü platformları hakkında bilgi
  • “Flutter için web desteği”, Flutter
    Web için Flutter hakkında bilgi
  • "Tüm Örnekler", Flutter
    Flutter örneklerinin ve uygulamalarının küratörlüğünde bir listesi