طراحی صفحات در فلاتر

مواردی که در این قسمت خواهید آموخت:

  • چگونگی ترکیب صفحه در فلاتر
  • چیدمان افقی و عمودی ویدجت ها در فلاتر
  • چگونگی ساخت صفحه در فلاتر

در این قسمت راهنمای نحوه ساخت صفحه در فلاتر را خواهید آموخت در ادامه شما صفحه ای نظیر طراحی زیر خواهید ساخت

finished lakes app that you'll build in 'Building a Layout'

در این قسمت در ابتدا به نحوه نمایش یک ویدجت در فلاتر را می آموزید و پس از آن نحوه نمایش ویدجت ها بصورت افقی و عمودی در ادامه رایج ترین ترکیب صفحات را به شما یاد می دهیم.

ساخت یک صفحه

اگر می خواهید درک درستی از مکانیزم طراحی صفحات در فلاتر بدست آورید توصیه می کنیم با رویکرد فلاتر در طح بندی صفحه شروع کنید.

گام 0: راه اندازی

ابتدا، کد را دریافت کنید:

سپس، تصویر را به آن اضافه کنید:

  • یک فهرست (دایرکتوری) از تصاویر در بالای پروژه ایجاد کنید.
  • lake.jpg اضافه کنید. (حواستون باشه که wget برای ذخیره فایل باینری عمل نمی کند.)
  • لازم است فایل pubspec.yaml در قسمت assets به روز رسانی کنید تا بتوانید تصویر را در پروژه بیاورید.

گام 1: آنالیز قسمت های مختلف صفحه و تقسیم آن به بخش های کوچکتر

اولین گام خرد کردن طرح صفحه به المان های کوچکتر آن است:

  • سطرها و ستون ها را تشخیص دهید.
  • آیا طرح صفحه گیرید دارد؟
  • المان هایی که باهم تداخل داشته باشند در آن هستند؟
  • آیا رابط کاربری نیاز به تب دارد؟
  • فضاهایی که نیاز به ترازبندی، فاصله گذاری و مرز دارند را دقت کنید.

اول، المان های بزرگ صفحه را تشخیص دهید. در این مثال چهار المان اصلی در یک ستون قرار دارند که عبارتند از: تصویر، دو سطر و یک بلوک متنی

diagramming the rows in the lakes screenshot

سپس هر سطر را مجزا بررسی کنسد. اولین سط که بخش عنوان نام دارد صاحب 3 فرزند است یک ستون متنی، یک آیکون ستاره و یک عدد. اولین فرزند از دو خط متن تشکیل شده است. اولین ستون که متنی است و بیشترین فضا را گرفته باید در ویدجت Expanded قرار گیرد.

diagramming the widgets in the Title section

سطر دوم هم که بخش دکمه است صاحب سه فرزند استکه هر فرزندی یک ستون است که تشکیل شده از یک آیکون و یک متن.

diagramming the widgets in the button section

پس از به پایان رسیدن آنالیز بخش های مختلف صفحه نوبت به پیاده سازی بخش ها مختلف آن می رسد برای اینکه از تودرتویی کدهای صفحه کمتر گیج بشید لازمه که یه سری از آن ها را داخل متغیرها و توابع اجرا کنید.

گام2: اجرای سطر عنوان

ابتدا ستون سمت چپ این سطر را پیاده می کنیم لازم است که این ستون را داخل یک ویدجت Expanded قرار دهیم تا تمام فضا را در اختیار خود قرار دهد سپس CrossAxisAlignment.start رابه crossAxisAlignment مقدار دهی کنید تا ستون را در ابتدای سطر قرار دهد.

قراردادن اولین سطر داخل یک کانتینر (Container) باعث می شودکه بتوانید به آن پدینگ اضافه کنید. فرزند دوم در این ستون که متن است که به رنگ خاکستری در می آید.

دو آیتم آخر که در این سط قرار می گیند آیکون ستاره قرمز رنگ متن "41" است. کل این سطر را در یک کانتینر قرار دهید و پدینگ کل آن را 32 پیکسل بدهید.

کدی که سطر عنوان را پیاده می کند بصورت زیر است.




  

  

  

گام 3: پیاده سازی سطر دکمه ها

سطر ستون ها از 3 ستون با ترکیب یک متن و یک سطر آیکون بالای آن تشکیل شده است. ستون ها در این سط با فاصله مساوی چیده شده اند و رنگ مورد استفاده در متد build() آن رنگ پیش فرض آبی به کار گرفته شده است.

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      //...

      return new MaterialApp(
        title: 'Flutter Demo',
        theme: new ThemeData(
          primarySwatch: Colors.blue,
        ),

      //...
  }

به دلیل اینکه اینکه المان های سازهنده ستنون های این سطر تقریبا با هم مشابه است بهینه ترین را ه برای پیاده سازی نوشتن تابع buildButtonColumn() برای پیاده سازی کل این ستون هاست. که آیکون و یک متن می گیرد و به شما یک ستون چیده شده با رنگ پیش فرض آبی باز می گرداند.

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      //...

      Column buildButtonColumn(IconData icon, String label) {
        Color color = Theme.of(context).primaryColor;

        return new Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            new Icon(icon, color: color),
            new Container(
              margin: const EdgeInsets.only(top: 8.0),
              child: new Text(
                label,
                style: new TextStyle(
                  fontSize: 12.0,
                  fontWeight: FontWeight.w400,
                  color: color,
                ),
              ),
            ),
          ],
        );
      }
    //...
  }

تابع سازنده (build) به طور مستقیم آیکون را به ستون اضافه می کند. به منظور افزودن حاشیه (padding) به متن لازم است آن را داخل یک container بگذارید تا از آیکون جدا شود.

سطر شامل این ستون ها با متن و آیکون ها را با فراخوانی تابع بسازید. و ستون هارا با استفاده از MainAxisAlignment.spaceEvenly که فاصله های ستون ها را به طور مساوی تقسیم می کند، به خط کنید.

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      //...

      Widget buttonSection = new Container(
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            buildButtonColumn(Icons.call, 'CALL'),
            buildButtonColumn(Icons.near_me, 'ROUTE'),
            buildButtonColumn(Icons.share, 'SHARE'),
          ],
        ),
      );
    //...
  }

گام 4: بخش متن را اجرا کنید

بخش متن را که نسبتا طولانی است به عنوان یک متغیر تعریف کنید. متن را داخل یک Container قرار دهید تا بتوانید پدینگ 32 پیکسل را به آن بدهید. ویژگی softwrap را به متن بدهید تا فواصی خطوط، کاما و نقطه رارعایت کند.

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      //...

      Widget textSection = new Container(
        padding: const EdgeInsets.all(32.0),
        child: new Text(
          '''
  Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese Alps. Situated 1,578 meters above sea level, it is one of the larger Alpine Lakes. A gondola ride from Kandersteg, followed by a half-hour walk through pastures and pine forest, leads you to the lake, which warms to 20 degrees Celsius in the summer. Activities enjoyed here include rowing, and riding the summer toboggan run.
          ''',
          softWrap: true,
        ),
      );
    //...
  }

گام 5: بخش تصویر را اجرا کنید

سه تا از چهار المان ستون پیاده شد و حالا نوبت تصویر است. تصویر را شما می توانید از طریق این لینک دریافت کنید. اما مشکل اینجاست که این تصویر نسبتا بزرگ است و برای نرم افزار دریافت این عکس زمانبر است. اگر به خاطر داشته باشید ما این تصویر را در گام 0 به پوشه های اصلی برنامه افزودیم حال بهترین کار فراخوانی این تصویر از دارایی های برنامه در فایل pubspec است. کد فراخوانی تصویر به صورت زیر است:

body: new ListView(
    children: [
      new Image.asset(
        '/images/layout/lake.jpg',
        height: 240.0,
        fit: BoxFit.cover,
      ),
      // ...
    ],
  )

تگ BoxFit.cover به نرم افزار می گوید که تصویر را به حدی کوچک کند که باکس تصویر را در کاملا پوشش دهد.

گام 6: بخش های بالا را کنارهم بگذارید

در گام آر تنها کافیست قطعه کدهایی که تاکنون نوشته اید را در کنار هم قرار دهید. کل ویدجت ها باید در یک ویدجت ListView قرار بگیرند تا در تلفن همرا با صفحات کوچک بصورت خودکار پیمایش (اسکرول) کنند.

//...
  body: new ListView(
    children: [
      new Image.asset(
        '/images/layout/lake.jpg',
        width: 600.0,
        height: 240.0,
        fit: BoxFit.cover,
      ),
      titleSection,
      buttonSection,
      textSection,
    ],
  ),
  //...

کد دارت: main.dart
تصویر: images
Pubspec: pubspec.yaml

Adding Interactivity to Your Flutter App.


رویکرد فلاتر به layout

مهمترین مفاهیم این بخش

  • تمامی ویدجت ها کلاس هایی هستند برای ساخت UI ها
  • ویدجت ها هم برای UI و هم برای layout کاربرد دارند.
  • ویدجت های پیچیده را با نوشتن چندین ویدجت ساده بسازید.

هسته اصلی طراحی صفحه در فلاتر ویدجت ها هستند. تقریا در فلاتر همه چیز یک ویدجت است حتی مدل های layout تصاویر، آیکون ها و متن و هرچیزی که شما در یک اپ فلاتر می توانید ببینید یک ویدجت است. اما چیزهایی که شما نمی بینید اما در شکل دهی و نظم دهی ویدجت ها همانن: سطرها، ستون ها و ... که ویدجت ها را منظم می کنند خود یک ویدجت هستند.

شما یک layout را با نوشتن ویدجت های مختلف و ساخت یک ویدجت پیچیده اجرا می کنید. به طور مثال تصویر زیر سه آیکون به همراه لیبل زیر آن ها را نشان می دهد:

sample layout      sample sample layout with visual debugging turned on

و تصویر دوم تحلیل این layout را نشان می دهد که تشکیل شده از یک سطر با سه ستون که هر ستون شامل یک آیکون و یک لیبل می باشد.

در زیر نمودار درختی برای این UI را مشاهده می کنید.

node tree representing the sample layout

تقریبا همه ی این نمودار درختی همان طوری که تصور می کردید شده است قسمت تعجب آور container هست که به رتگ صورتی نمایش داده شده است. یک ویدجتی است که اجازه می دهد ویدجت فرزندش را آنطور که می خواهید جانمایی کنمید. container اکر در جایی از نرم افزار قصد ایجاد یک باکس را داشتید که بتوانید به آن border ، margin، padding و یا background-color بدهید لازم است آن را داخل یک container جای دهید.

در این مثال ویدجت text را داخل container قراردادیم تا بتوانیم به آن margin بدهیم. همچنین کل Row را در یک container قرار داده ایم تا بتوانیم به آن padding اضافه کنیم.

بقیه UI توسط سایر ویژگیها (properties) کنترل شده اند. یک آیکون را یا استفاده از ویژگی color آیکون رنگی کنید. از ویژگی style برای تغییر فونت، رنگ، وزن و سایر قابلیت ها اصتفاده کنید. سطرها و ستون ها قبلیت هایی دارند که می توانید با آن ها مشخص کنید که بصورت عمودی یا افقی به خط بشوند و فرزندان شان چقدر فضا در اختیار بگیرند.


طراحی یک ویدجت

نکات مهم این بخش

  • حتی app هم خود یک ویدجت به حساب می آید.
  • به راحتی می توانید یک ویدجت بسازید و آن را به طراحی خود اضافه کنید.
  • برای نشان دادن یک ویدجت در نرم افزار کافی است آن را در ویدجت app اضافه کنید.
  • آسان ترین کار استفاده از ویدجت Scaffold است که ویدجت از کتابخانه متریال است که دارای یک ظاهر پیش فرض و جانمایی منوو یک نوار رنگی در بالا و پایین صفحه است که دارای رنگ زمینه و API برای افزودن drawer، snack bar و bottom sheet است.
  • اگر ترجیح می دهید می توانید یک اپ با استفاده از ویدجت های استاندارد در کتابخانه ویدجت ها بسازید.

چگونه یک ویدجت در فلاتر بسازیم؟ ما در این بخش قصد داریم نحوه ی ساخت یک ویدجت ساده و نمایش در صفحه نمایش را آموزش بدهیم. در این بخش نحوه نمایش یک Hello World را خواهید آموخت.

در فلاتر تنها با چند گام ساده می توانید یک متن، آیکون و یا تصویر را در صفحه نمایش دهید.

  1. یک layout برای نگهداری شئ انتخاب کنید.
    می توانید ویدجت را از تنوع Scaffold که براساس Choose from a variety of Scaffold based on how you want to align or constrain the visible widget, as these characteristics are typically passed on to the contained widget. This example uses Center which centers its content horizontally and vertically.

  2. Create a widget to hold the visible object.

    برای مثال یک ویدجت متن بسازید:

    new Text('Hello World', style: new TextStyle(fontSize: 32.0))

    یک ویدجت تصویر بسازید

    new Image.asset('/images/layout/myPic.jpg', fit: BoxFit.cover)

    یک ویدجت آیکون بسازید:

    new Icon(Icons.star, color: Colors.red[500])
  3. ویدجت قابل نمایش را به ویدجت layout اضافه کنید.
    تمام ویدجت های طرح بندی دارای ویژگی child که ممکن است یک فرزند داشته باشند (به طور مثال Center یا container) و یا اینکه دارای چندین فرزند باشند که در این صورت از ویژگی children باید استفاده کنیم تا بتوانیم لیستی از ویدجت ها را به وی نسبت دهیم. (به طور مثال Row، Column، ListView یا Stack)

    ویدجت متن را به ویدجت Center اضافه کنید

    new Center(
        child: new Text('Hello World', style: new TextStyle(fontSize: 32.0))
  4. ویدجت layout را به صفحه اضافه کنید.
    اپلیکیشن فلاتر هم خود یک ویدجت است و اغلب ویدجت ها یک متد build() دارند استفاده از این متد ویدجت شما را در اپلیکیشن نمایش می دهد.

    برای یک اپلیکیشن متریال شما می توانید ویدجت Center را مستقیما در body برای صفحه اصلی اضافه کنید.

    class _MyHomePageState extends State<MyHomePage> {
        @override
        Widget build(BuildContext context) {
          return new Scaffold(
            appBar: new AppBar(
              title: new Text(widget.title),
            ),
            body: new Center(
              child: new Text('Hello World', style: new TextStyle(fontSize: 32.0)),
            ),
          );
        }
      }

    برای اپلیکیشن های غیرمتریال شما می توانید ویدجت Center را در متد build() مطابق با مد زیر استفاده کنید:

    // This app doesn't use any Material Components, such as Scaffold.
      // Normally, an app that doesn't use Scaffold has a black background
      // and the default text color is black. This app changes its background
      // to white and its text color to dark grey to mimic a Material app.
      import 'package:flutter/material.dart';
    
      void main() {
        runApp(new MyApp());
      }
    
      class MyApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return new Container(
            decoration: new BoxDecoration(color: Colors.white),
            child: new Center(
              child: new Text('Hello World',
                  textDirection: TextDirection.ltr,
                  style: new TextStyle(fontSize: 40.0, color: Colors.black87)),
            ),
          );
        }
      }

    به یاد داشته باشید که اپلیکیشن غیرمتریال به طور پیشفرض دارای AppBar، title و یا رنگ پ زمینه نیستند. و اگر این قابلیت ها را در یک اپلیکیشن غیرمتریال می خواهید باید آن ها را خودتان بسازید. این اپلیکیشن رنگ زمینه را به سفید و رنگ متن را به خاکستری تیره تبدیل می کند تا همانند متریال شود.

زمانیکه اپلیکیشن را اجرا می کنید باید صفحه زیر را مشاهده کنید.

screenshot of a white background with grey 'Hello World' text.

کد دارت (Material app): main.dart
کد دارت (widgets-only app): main.dart


طرح ریزی چندین ویدجت بصورت عمودی و افقی

یکی از رایج ترین الگوهای طراحی، ویدجت ها را بصورت عمودی و یا افقی نمایش دادن می باشد. شما می توانید از ویدجت Row برای منظم کردن ویدجت ها بصورت افقی و از ویدجت Column برای منظم کردن آن ها بصورت عمودی استفاده کنید.

نکات این بخش

  • Row و Column رایجترین الگوهای طراحی هستند.
  • Row و Column هرکدام صاحب لیست از ویدجت های فرزند هستند.
  • یک ویدجت child به خودی خود می تواند یک Row یا Column و یا یک ویدجت مختلط باشد.
  • شما می توانید تعیین کنید Row و یا Column چگونه فرزندان را بصورت افقی یا عمودی نظم دهند.
  • You can stretch or constrain specific child widgets.
  • شما می توانید تعیین کنید که ویدجت child از فضای سطر یا ستون در ئسترس خود استفاده کند.

مطالب

به منظئر ایجاد یک سط یا ستوئ در فلاتر، یک سری ویدجت به Row یا ویدجت Column اضافه کنید. به نوبت هریک از فرزندها می تواند خود دارای یک سط یا ستون باشد. مثال زیر چونه سطها و ستون ها را بصورت تو در تو در یکدیگر قرار دهید. .

این طراحی به طور کلی یک Row در نظر گرفته می شود که این سطر خودش دارای دو فرزند است: یک ستون سمت چپ و یک تصویر سمت راست

screenshot with callouts showing the row containing two children: a column and an image.


ستون سمت چپ حاوی چندین سطر و ستون است

diagram showing a left column broken down to its sub-rows and sub-columns


شما طراحی Pavlova را در قسمت سطرها و ستون های تودرتواجرا خواهید کرد. .

ویدجت های تراز کننده

با استفاده از mainAxisAlignment و crossAxisAlignment می توانید تعیین کنید که فرزندان سطر یا ستون شما چگونه تراز شوند. برای یک سط محور اصلی بصورت افقی و محور جانبی بصورت عمودی و برای یک ستون محور اصلی بصورت عمودی و محور جانبی بصورت افقی می باشد.

diagram showing the main axis and cross axis for a row

diagram showing the main axis and cross axis for a column

کلاس های MainAxisAlignment و CrossAxisAlignment ثابت های متنوعی را برای ترازبندی در خود دارند.

در مثال زیر عرض هر یک از تصاویر 100 پیکسل است و صفحه ی نمایش دهنده در این مثال بیش از 300 پیکسل عرض دارد پس تنظیم محور اصلی بصورت spaceEvenly فضای باقیمانده را بطور یکسان قبل و بعد از تصاویر تقسیم می کند.

appBar: new AppBar(
    title: new Text(widget.title),
  ),
  body: new Center(
    child: new Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        new Image.asset('images/pic1.jpg'),
a row showing 3 images spaced evenly in the row

کد دارت: main.dart
Images: images
Pubspec: pubspec.yaml

ستون ها هم مشابه سطرها عمل می کنند. مثال زیر یک ستون محتوی 3 تصویر را نشان می دهد که هرکدام 100 پیکسل ارتفاع دارند. ارفاع کلی صفحه نمایش از بیش از 300 پیکسل است. بنابرای تنظیم محور اصلی ترازبندی بصورت spaceEvenly فضای آزاد عمودی را بطور مساوی به بالا و پایین تصاویر تقسیم می کند.

appBar: new AppBar(
    title: new Text(widget.title),
  ),
  body: new Center(
    child: new Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        new Image.asset('images/pic1.jpg'),

کد دارت: main.dart
Images: images
Pubspec: pubspec.yaml

a column showing 3 images spaced evenly in the column

ویدجت های اندازه گیری

شاید شما یک ویدجتی بخواهید که دو برابر ویدجت های اطراف خودش فضا در اختیار بگیرد برای این کار باید فرزند سطر یا ستون را Expanded قرار دهید. این ویدجت قبلیتی به نام flex دارد که که نسبت این چند برابری را می گیرد که پیش فرض عدد آن 1 است و تنها اعداد صحیح می گیرد.

به طور مثال برای ساخت یک ستون با 3 ویدجت که ویدجت میانی 2 برابر عرض دارد باید flex را برای ویدجت میانی عدد 2 قرار دهید.

appBar: new AppBar(
    title: new Text(widget.title),
  ),
  body: new Center(
    child: new Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        new Expanded(
          child: new Image.asset('images/pic1.jpg'),
        ),
        new Expanded(
          flex: 2,
          child: new Image.asset('images/pic2.jpg'),
        ),
        new Expanded(

a row of 3 images with the middle image twice as wide as the others

کد دارت: main.dart
Images: images
Pubspec: pubspec.yaml

To fix the example in the previous section where the row of 3 images was too wide for its render box, and resulted in the red strip, wrap each widget with an Expanded widget. By default, each widget has a flex factor of 1, assigning one-third of the row to each widget.

appBar: new AppBar(
    title: new Text(widget.title),
  ),
  body: new Center(
    child: new Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        new Expanded(
          child: new Image.asset('images/pic1.jpg'),
        ),
        new Expanded(
          child: new Image.asset('images/pic2.jpg'),
        ),
        new Expanded(

a row of 3 images that are too wide, but each is constrained to take only 1/3 of the row's available space

کد دارت: main.dart
Images: images
Pubspec: pubspec.yaml

Packing widgets

By default, a row or column occupies as much space along its main axis as possible, but if you want to pack the children closely together, set its mainAxisSize to MainAxisSize.min. The following example uses this property to pack the star icons together.

class _MyHomePageState extends State<MyHomePage> {
    @override
    Widget build(BuildContext context) {
      var packedRow = new Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          new Icon(Icons.star, color: Colors.green[500]),
          new Icon(Icons.star, color: Colors.green[500]),
          new Icon(Icons.star, color: Colors.green[500]),
          new Icon(Icons.star, color: Colors.black),
          new Icon(Icons.star, color: Colors.black),
        ],
      );

    // ...
  }

a row of 5 stars, packed together in the middle of the row

کد دارت: main.dart
Icons: Icons class
Pubspec: pubspec.yaml

سطر و ستون های تودرتو

فلاتر به شما اجازه می دهد تا سطر و ستون ها را تا جایی که لازم دارید در یکدیگر قرار دهید. بیایید نگاهی بکنیم به کد قسمت مشخص شده قالب زیر:

a screenshot of the pavlova app, with the ratings and icon rows outlined in red

قسمت مشخص شده با استفاده از 2 سط اجرا شده است. سط ستاره ها تشکیل شده از 5 ستاره و تعداد نظرات . سطر آیکون ها تشکیل شده از 3 ستون آیکون و متن The outlined section is implemented as two rows. The ratings row contains five stars and the number of reviews. The icons row contains three columns of icons and text.

درخت ویدجت برای سط ستاره ها بصورت زیر می باشد:

a node tree showing the widgets in the ratings row


سطر ratings تشکیل شده از یک سطر کوچکتر از آیکونه ها ستاره و یک متن:

class _MyHomePageState extends State<MyHomePage> {
    @override
    Widget build(BuildContext context) {
      //...

      var ratings = new Container(
        padding: new EdgeInsets.all(20.0),
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            new Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                new Icon(Icons.star, color: Colors.black),
                new Icon(Icons.star, color: Colors.black),
                new Icon(Icons.star, color: Colors.black),
                new Icon(Icons.star, color: Colors.black),
                new Icon(Icons.star, color: Colors.black),
              ],
            ),
            new Text(
              '170 Reviews',
              style: new TextStyle(
                color: Colors.black,
                fontWeight: FontWeight.w800,
                fontFamily: 'Roboto',
                letterSpacing: 0.5,
                fontSize: 20.0,
              ),
            ),
          ],
        ),
      );
      //...
    }
  }

سطر آیکون ها زیر سطر ستاره ها تشکیل شده از 3 ستون که هرکدارم تشکیل شده از یک آیکون و یک متن بنابراین درخت ویدجت برای این قسمت بصورت زیر خواهد بود:

a node tree for the widets in the icons row

The iconList variable defines the icons row:

class _MyHomePageState extends State<MyHomePage> {
    @override
    Widget build(BuildContext context) {
      // ...

      var descTextStyle = new TextStyle(
        color: Colors.black,
        fontWeight: FontWeight.w800,
        fontFamily: 'Roboto',
        letterSpacing: 0.5,
        fontSize: 18.0,
        height: 2.0,
      );

      // DefaultTextStyle.merge allows you to create a default text
      // style that is inherited by its child and all subsequent children.
      var iconList = DefaultTextStyle.merge(
        style: descTextStyle,
        child: new Container(
          padding: new EdgeInsets.all(20.0),
          child: new Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              new Column(
                children: [
                  new Icon(Icons.kitchen, color: Colors.green[500]),
                  new Text('PREP:'),
                  new Text('25 min'),
                ],
              ),
              new Column(
                children: [
                  new Icon(Icons.timer, color: Colors.green[500]),
                  new Text('COOK:'),
                  new Text('1 hr'),
                ],
              ),
              new Column(
                children: [
                  new Icon(Icons.restaurant, color: Colors.green[500]),
                  new Text('FEEDS:'),
                  new Text('4-6'),
                ],
              ),
            ],
          ),
        ),
      );
      // ...
    }
  }

متغیر leftColumn تشکیل شده از سطرهای ستاره ها و آیکون ها همچنین یک عنوان و یک متن که در مورد Pavlov توضیح داده است:

class _MyHomePageState extends State<MyHomePage> {
    @override
    Widget build(BuildContext context) {
      //...

      var leftColumn = new Container(
        padding: new EdgeInsets.fromLTRB(20.0, 30.0, 20.0, 20.0),
        child: new Column(
          children: [
            titleText,
            subTitle,
            ratings,
            iconList,
          ],
        ),
      );
      //...
    }
  }

ستون سمت چپ در یک Container قرار گرفته تا عرض آن را بتوان محدود کرد. و نهایتا این قالب با یک سطر کلی (متشکل از ستون سمت چپ و یک تصویر) که در یک Card قرار گرفته به پایان می رسد.

تصویر Pavlova از وبسایت Pixabay گرفته شده است که بجای آن هر تصویر دیگری می توانید بگذارید. همچنین با دستور Image.network می توانید یک تصویر از اینترنت را بجای آن قرار دهید. اما در این مثال تصویر در خود پروژه قرار گرفته است و آدرس و نام آن در فایل فایل pubspec اضافه شده است. برای یادگیری بیشتر در این مورد به قسمت افزودن دارایی ها و تصاویر در فلاتر مراجعه کنید.

body: new Center(
    child: new Container(
      margin: new EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 30.0),
      height: 600.0,
      child: new Card(
        child: new Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            new Container(
              width: 440.0,
              child: leftColumn,
            ),
            mainImage,
          ],
        ),
      ),
    ),
  ),

کد دارت: main.dart
Images: images
Pubspec: pubspec.yaml


ویدجت های رایج طراحی صفحات فلاتر

فلاتر دارای کتابخانه ی کاملی از ویدجت های متنوع در طراحی صفحات است اما اینجا به چند نمونه از پرکاربردترین آن ها اشاره کرده ایم. هدف اصلی ارتقا دانش شما در فلاتر و رسیدن به محصول در حداقل زمان با بیشترین سرعت می باشد بنابراین قصد نداریم با توضیح تمام ویدجت ها شما را در آغاز کار با فلاتر خسته کنیم. برای اطلاعات بیشتر درمورد ویدجت ها به گذری در ویدجت های فلاتر مراجعه کنید. همچنین برای دانش بیشتر به قسمت مستندات API ها

ویدجت های زیر شامل دو دسته کلی هستند که عبارتند از ویدجت های استاندارد که در کتابخانه ویدجت ها قرار گرفتند. و ویدجت های اختصاصی که در کتابخانه کامپوننت های متریال جای گرفتند. هر اپلیکیشنی می تواند از کتابخانه ویدجت ها استفاده کند اما تنها اپلیکیشن های متریال می توانند از کامپوننت های متریال استفاده کنند.

ویدجت های استاندارد

  • Container
    با استفاده از این ویدجت می توانید پدینگ، مارجین، رنگ زمینه، و سایر دکراسیون ها را به آن اضافه کنید.
  • GridView
    ویدجت ها را بصورت یک طرح ریزی قابل پیمایش تبدیل می کند.
  • ListView
    یک لیست قابل پیمایش از ویدجت ها می سازد.
  • Stack
    یک ویدجت را بر روی ویدجت دیگر قرار می دهد.

کامپوننت های متریال

  • Card
    اطلاهات مرتبط باهم داخل یک باکس سایه دار با گوشه های گرد شده قرار می دهد.
  • ListTile
    تا 3 خط متن همراه با آیکون های پیشین یا پسین را منظم می کند.

Container

بسیاری از قالب ها لازم هستند که به صورت اختصاصی آن ها را طراحی کرد و ویدجت های آماده دارای محدودیت هایی هستند اما شما با اسستفاده از Container به راحتی می توانید قسمت مورد نظر و رنگ زمینه، تصویر زمینه، مقدار مرزها و سایر پارامترهای طراحی را با سلیقه خودتان تغییر دهید.

خلاصه کارای کانتینر:

  • افزودن پدینگ، مارجین و مرز
  • تغییر تصویر یا رنگ پس زمینه
  • دارای یک child که این فرزند می تواند سطر ستون و یا ویدجت پدر ویدجت های دیگر باشد.

a diagram showing that margins, borders, and padding, that surround content in a container

مثال های کانتینر:

علاوه بر مثال زیر در بسیاری از آموزش ها و مثال ها در در فلاتر از این ویدجت استفاده شده است که درصورت لزوم می توانید در گالری فلاتر آن ها را بیابید.

این قالب از یک ستون با دو سط تشکیل شده است که هر سطر آن دارای 2 تصویر است. هریک از این تصاویر در یک کانتینر قرار گرفته تا بتوان به هرکدام، پدینگ، مارجین و مرزهای گوشه گرد خاکستری داد. ستونی که سطرهای تصاویر در آن قرار گرفته خود از یک کانتینر استفاده کرده تا بتوان رنگ زمینه را خاکستری روشن تر کرد.

کد دارت: main.dart, snippet below
تصاویر images
فایل Pubspec: pubspec.yaml

a screenshot showing 2 rows, each containing 2 images; the images have grey rounded borders, and the background is a lighter grey

class _MyHomePageState extends State<MyHomePage> {
    @override
    Widget build(BuildContext context) {

      var container = new Container(
        decoration: new BoxDecoration(
          color: Colors.black26,
        ),
        child: new Column(
          children: [
            new Row(
              children: [
                new Expanded(
                  child: new Container(
                    decoration: new BoxDecoration(
                      border: new Border.all(width: 10.0, color: Colors.black38),
                      borderRadius:
                          const BorderRadius.all(const Radius.circular(8.0)),
                    ),
                    margin: const EdgeInsets.all(4.0),
                    child: new Image.asset('images/pic1.jpg'),
                  ),
                ),
                new Expanded(
                  child: new Container(
                    decoration: new BoxDecoration(
                      border: new Border.all(width: 10.0, color: Colors.black38),
                      borderRadius:
                          const BorderRadius.all(const Radius.circular(8.0)),
                    ),
                    margin: const EdgeInsets.all(4.0),
                    child: new Image.asset('images/pic2.jpg'),
                  ),
                ),
              ],
            ),
            // ...
            // See the definition for the second row on GitHub:
            // https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/container/main.dart
          ],
        ),
      );
      //...
    }
  }

GridView

استفاده از GridView به شما اجازه می دهد که ویدچت های تان را در یک لیست دوبعدی قرار دهید. GridView دارای دو حالت پیش فرض است که البته می توانید متناسب با نیازتان آن را مختص خودتان تغییر دهید. از جمله قابلیت های GridView این است که زمانی که تشخیص می دهد محتوای شما طولانی است بصورت خودکار آن را قابل پیمایش می کند. Use GridView to lay widgets out as a two-dimensional list. GridView provides two pre-fabricated lists, or you can build your own custom grid. When a GridView detects that its contents are too long to fit the render box, it automatically scrolls.

خلاصه گیرید ویو:

  • ویدجت ها را در یک شبکه قرار می دهد.
  • زمانی که محتوا بزرگتر از محده صفحه نمایش است آن را قابل پیمایش می کند.
  • شما می توانید از گرید پیش فرض استفاده کنید و یا آن را برای خودتان اختصاصی کنید. دو مدل پیش فرض بصورت زیر هستند:
    • GridView.count به شما اجازه می دهد تعداد ستون ها را مشخص کنید
    • به شما اجازه می دهد عرض یک تایل را مشخص کنید

مثال های GridView:

a 3-column grid of photos

از GridView.extent استفاده کنید تا شبکه ای از تایل های با عرض ماکزیمم 150 پیکسل ایجاد کنید
کد دارت: main.dart, snippet below
تصاویر: images
فایل Pubspec: pubspec.yaml

a 2 column grid with footers containing titles on a partially translucent background

از GridView.count استفاده کنید تا شبکه ای بسازید که در در عرض خود 2 تایل جا می دهد و در حالت افقی 3 تایل می توانید با تنظیم کردن footer به تایل های خود عنوان و مشخصات بدهید.
دارت کد: grid_list_demo.dart from the گالری فلاتر




  

ListView

فلان یک ویدجت ستونی شکل است و زمانی که محتوای آن طولانی است بصورت خودکار ساکرول را در صفحه نمایش فعال می کند.

خلاصه ListView:

  • یک ستون اختصاصی شده برای نمایش لیستی منظم شده محتوا
  • هم می تواند بصورت افقی و هم بصورت عمودی باشد
  • محتوایی که در صفحه نمایش جا نگیرد خودکار اسکرول می کند.
  • کمتر از ستون قابل تنظیم است ولی به راحتی و در کمترین زمان می توان از آن استفاده کرد و اسکرول خودکار دارد.

مثال های ListView:

a ListView containing movie theaters and restaurants

از یک ListView برای نمایش سالن های تئاتر و سینما و رستوران ها استفاده شده که دارای Dividder برای جداسازی رستوران ها از از سینما و تئاتر است.
کد دارت main.dart, snippet below
آیکون ها Icons class
فایل Pubspec pubspec.yaml

a ListView containing shades of blue from the Material Design color palette

استفاده از ListView برای نمایش رنگ ها برای یک خانواده رنگ از گروه رنگ های متریال
کد دارت: colors_demo.dart از گالری فلاتر

List<Widget> list = <Widget>[
    new ListTile(
      title: new Text('CineArts at the Empire',
          style: new TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
      subtitle: new Text('85 W Portal Ave'),
      leading: new Icon(
        Icons.theaters,
        color: Colors.blue[500],
      ),
    ),
    new ListTile(
      title: new Text('The Castro Theater',
          style: new TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
      subtitle: new Text('429 Castro St'),
      leading: new Icon(
        Icons.theaters,
        color: Colors.blue[500],
      ),
    ),
    // ...
    // See the rest of the column defined on GitHub:
    // https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/listview/main.dart
  ];

  class _MyHomePageState extends State<MyHomePage> {
    @override
    Widget build(BuildContext context) {
      return new Scaffold(
        // ...
        body: new Center(
          child: new ListView(
            children: list,
          ),
        ),
      );
    }
  }

Stack

از Stack برای قراردادن یک ویدجت برروی ویدجتی دیگر استفاده کنید و ویدجت می تواند کاملا برروی ویدجت دیگر قرار بگیرد.

خلاصه Stack:

  • برای قرار دادن یک ویدجت برروی ویدجت دیگر
  • اولین ویدجت در لیست لیست فرزندان ویدجت پایه است. و فرزندان ویدجت های دیگر روی ویدجت پایه قرار می گیرد.
  • محتوای یک استک قابل اسکرول نیست
  • برش دادن فرزندان که باکس نمایش سرریز می کنن

مثال های Stack:

a circular avatar containing the label 'Mia B' in the lower right portion of the circle

Uses Stack to overlay a Container (that displays its Text on a translucent black background) on top of a Circle Avatar. The Stack offsets the text using the alignment property and Alignments.
کد دارت: main.dart, snippet below
Image: images
Pubspec: pubspec.yaml

an image with a grey gradient across the top; on top of the gradient is tools painted in white

استفاده از استک برای قراردادن گرادیانت روی تصویر .
کد دارت: contacts_demo.dart from the گالری فلاتر

class _MyHomePageState extends State<MyHomePage> {
    @override
    Widget build(BuildContext context) {
      var stack = new Stack(
        alignment: const Alignment(0.6, 0.6),
        children: [
          new CircleAvatar(
            backgroundImage: new AssetImage('images/pic.jpg'),
            radius: 100.0,
          ),
          new Container(
            decoration: new BoxDecoration(
              color: Colors.black45,
            ),
            child: new Text(
              'Mia B',
              style: new TextStyle(
                fontSize: 20.0,
                fontWeight: FontWeight.bold,
                color: Colors.white,
              ),
            ),
          ),
        ],
      );
      // ...
    }
  }

Card

Card از چمله کامچوننت های کتابخانه متریال است که اغلب همرا با ListTile استفاده می شود. کارد دارای یک child است که می تواند سطر، ستون، لیست، Grid و یا سایر ویدجت های چند فرزندی باشد. به طور پیش فرض Card سایز خود را تا تطابق با صفحه نمایش کوچک می کند. اما می توانید با استفاده از SizedBox به آن ابعاد و ویژکیهای مشخصی بدهید.

در فلاتر از جمله ویژگیهای کارد گوشه های گرد، سایه بالا و زیرین و افکت 3 بعدی هست. تغییر elevation کارد امکان کنترل سایه های اطراف آن را به شما می دهد و هرچه عدد elevation بیشتر باشد آن را از صفحه نمایش بیشتر جدا می کند. برای اطلاعات بیشتر به قسمت Elevation and Shadows مراجعه کنید.

خلاصه کارد:

  • اجرای کارد متریال دیزاین/li>
  • برای نمایش اطلاعات بیشتر درمورد چیزی استفاده می شود/li>
  • تنها دارای یک فرزند است و آن فرزند هرویدجت می تواند باشد
  • همیشه با گوشه های گرد و سایه نمایش داده می شود
  • محتوای کارد قابل اسکرول نیست
  • از کتابخانه کامپوننت های متریال است

مثال های کارد:

a Card containing 3 ListTiles

یک کارد تشکیل شده از 3 تا ListTile که ابعاد دارد. یک Divider قسمت اول ListTile را از قسمت دوم جدا کرده است.

کد دارت: main.dart, snippet below
آیکون ها: Icons class
فایل Pubspec: pubspec.yaml

a Card containing an image and text and buttons under the image

یک کارد تشکیل شده از متن و عکس
کد دارت: cards_demo.dart از گالری فلاتر

class _MyHomePageState extends State<MyHomePage> {
    @override
    Widget build(BuildContext context) {
      var card = new SizedBox(
        height: 210.0,
        child: new Card(
          child: new Column(
            children: [
              new ListTile(
                title: new Text('1625 Main Street',
                    style: new TextStyle(fontWeight: FontWeight.w500)),
                subtitle: new Text('My City, CA 99984'),
                leading: new Icon(
                  Icons.restaurant_menu,
                  color: Colors.blue[500],
                ),
              ),
              new Divider(),
              new ListTile(
                title: new Text('(408) 555-1212',
                    style: new TextStyle(fontWeight: FontWeight.w500)),
                leading: new Icon(
                  Icons.contact_phone,
                  color: Colors.blue[500],
                ),
              ),
              new ListTile(
                title: new Text('costa@example.com'),
                leading: new Icon(
                  Icons.contact_mail,
                  color: Colors.blue[500],
                ),
              ),
            ],
          ),
        ),
      );
    //...
  }

ListTile

لیست تایل یک ویدجت سطری شکل از کامپوننت های متریال است که برای استفاده آسان و ایجاد یک سطر با 3 خط متن و آیکون کاربرد دارد اغلی این ویدجت همراه با ویCard و یا ListView استفاده می شود. اما در هرجای دیگری که لازم باشد می تون به کار برد.

خلاصه لیست تایل:

  • ویدجت سری اختصای شده با سه خط متن و یک آیکون اختیاری
  • قابلیت تنظیم کتر از سطر دارد اما به آسانی قابل استفاده است
  • از کتابخانه متریال است

مثال های لیست تایل:

a Card containing 3 ListTiles

یک کارد تشکیل شده از 3 لیست تایل
کد دارت: See مثال های کارد.

3 ListTiles, each containing a pull-down button

استفاده از لیست تایل برای دکمه های پایین رونده
کد دارت: buttons_demo.dart از گالری فلاتر


منابع

منابع زیر می توانند در نوشتن قالب به شما کمک فروانی بکنند.