فلاتر: یک قانون پیشرفته که حتی افرادی که تازه شروع به یادگیری فلاتر میکنن هم باید بدونن

 

ترجمه شده از مقاله اصلی Marcelo Glasberg

 

وقتی افراد در حال یادگیری فلاتر هستن معمولا سوالی که براشون پیش میاد این هستش که چرا بعضی از widget ها با عرض 100 پیکسل در عمل همچین عرضی رو اشغال نمیکنن ، جواب پیش فرض معمولا این هست که اون ویجت رو باید داخل یک Center  قرار داد، درسته ؟

اما این کار رو انجام ندید!

اگر این کار انجام بشه، این مشکل بارها و بارها اتفاق میوفته، و سوالی که مدام پرسیده میشه اینه که چرا برخی FittedBox ها به درستی کار نمیکنن ، چرا Column  ها overflow  (سرریز) میشن، یا اینکه قرار هستش IntrinsicWidth دقیقا چه کاری انجام بده. 

در عوض، در ابتدا چیزی که باید درک بشه اینه که لایه ها در فلاتر با اونچه که در Html  باهاش آشنا هستیم متفاوت هستن، و بعدش باید این قانون رو به خاطر بسپاریم :

 

Constraints go down. Sizes go up. Positions are set by parents

constraint ها پایین میرن ، size ها  بالا میان و position ویجت ها توسط parent خودشون تعیین میشن.

 

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

بصورت جزئی تر :
یک ویجت، constraint  های خودش رو از parent  خودش میگیره. یک “constraint” فقط شامل

4 تا عدد double  هست : حداقل و حداکثر width( عرض)  و حداقل و حداکثر height (ارتفاع).

-سپس ویجت، فهرستی از child  های خودش رو بررسی میکنه. یک به یک ، ویجت به child های خودش اطلاع میده که constraint شون چی هست (که میتونه برای هر کدوم از child ها متفاوت باشه) و سپس از هر child  میپرسه که چه سایزی دوست داری داشته باشی؟

-سپس ویجت، childهای خودش رو در موقعیت (position) قرار میده ( بصورت افقی روی محور x ,عمودی روی محور y)

-و در آخر ویجت به parent خودش در رابطه با size خودش اطلاع میده.(البته در چارجوب constraint  های اولیه)

 

widget:  هی parent , محدودیت های من (Constraints) چیه ؟

parent :  تو باید عرضت 90  تا 300 پیکسل باشه ، و ارتفاعت هم 30 تا 85

widget:   همم، از اونجایی که میخوام یه padding  پنج پیکسلی داشته باشم، پس child هام میتونن حداکثر 290 پیکسل عرض داشته باشن و 75 پیکسل ارتفاع داشته باشن.

widget :  هی اولین child ، تو باید چیزی بین 0 تا 290 پیکسل عرض و 0 تا 75 پیکسل ارتفاع داشته باشی.

widget : هی اولین child، تو باید بین 0 تا 290 پیکسل عرض داشته باشی، و 0 تا 75 هم ارتفاع

first child : خیلی خب، پس من تمایل دارم 290 پیکسل عرض داشته باشم و 20 پیکسل ارتفاع

widget : همم، از اونجایی که میخوام دومین child خودم رو پایین child اول خودم بذارم، پس child دومم تنها 55 پیکسل میتونه ارتفاع داشته باشه.

widget: هی child دوم، تو باید خودت رو بین 0 تا 290 پیکسل عرض و 0 تا 55 پیکسل ارتفاع جا بدی.

child دوم : خیلی خب، من دوست دارم 140 پیکسل عرض داشته باشم و 30 پیکسل ارتفاع.

widget : خیلی عالی ، من child اولم رو توی موقعیت x=5 , y=5  قرار میدم و child دومم رو توی موقعیت x:80 , y:25.

widget:  هی parent، من تصمیم گرفتم که سایزم 300 پیکسل عرض داشته باشه و 60 پیکسل ارتفاع

 

محدودیت ها

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

*یک ویجت میتونه تنها درمورد سایز خودش با توجه به constraint ای که توسط parentش بهش داده شده تصمیم بگیره. به این معنی که یک ویجت به طور معمول نمیتونه هر سایزی که خواست، داشته باشه.

*یک ویجت درمورد موقعیتش توی صفحه اطلاعی نداره و نمیتونه هم تصمیمی در موردش بگیره.و این parent  ویجت هست که تصمیم میگیره که موقعیت ویجت کجا باشه.

* از این جهت که سایز و موقعیت parent، همیشه  وابسته به parent بالاتر از خودش هست، این غیر ممکنه که به صورت دقیق سایز و موقعیت هر ویجتی بدون توجه به کل درخت تشکیل شده تعیین بشه.

 

مثال ها :

برای یک تجربه محسوس :

-code pen  پایین رو اجرا کنید ، اول باید run pen  رو بزنید و بعد  از اون  دکمه Rerun  رو که پایین سمت راست ظاهر میشه.

یا این dart pad  رو اجرا کنید.

-یا کد ها رو از ریپازیتوری گیت هاب بگیرید.

 

 

 

مثال 1 :

 

 

Container(color: Colors.red)

 

اسکرین، parent این container هست . و container  قرمز رو مجبور میکنه که سایز یکسانی با خودش داشته باشه .

بنابر این container  کل صفحه رو اشغال میکنه و اون رو قرمز میکنه.

 

مثال 2 :

 

 

Container(width: 100, height: 100, color: Colors.red)

 

container قرمز میخواد سایز 100*100  داشته باشه اما نمیتونه، چرا که اسکرین مجبورش میکنه که سایزی دقیقا یکسان با اسکرین داشته باشه.

بنابراین container  کل صفحه رو پر میکنه.

 

مثال 3 :

 

 

(Center(child: Container(width: 100, height: 100, color: Colors.red)

 

 

اسکرین، Center رو مجبور میکنه تا دقیقا هم سایز خودش باشه . بنابراین Center کل صفحه رو اشغال میکنه

ویجت Center در اینجا به Container میگه که هر سایزی که دلخواهش هست رو میتونه داشته باشه، اما نه بزرگ تر از سایزی که الان اسکرین داره . حالا container میتونه واقعا سایز 100 * 100 رو داشته باشه.

 

مثال 4

 

Align(
   alignment: Alignment.bottomRight,
   child: Container(width: 100, height: 100, color: Colors.red),
)

 

این مورد با مثال قبلی توی استفاده از ویجت Align بجای Center متفاوت هست.

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

 

مثال 5

 

Center(
    child: Container(
         color: Colors.red,
         width: double.infinity,
         height: double.infinity,
    )
)

اسکرین ویجت Center رو مجبور میکنه که دقیقا سایز یکسانی با خودش داشته باشه. بنابراین Center کل اسکرین رو اشغال میکنه.

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

 

مثال 6 : 

 

 

Center(child: Container(color: Colors.red))

اسکرین ویجت Center رو مجبور میکنه که دقیقا سایز یکسانی با اسکرین داشته باشه، بنابراین Center کل صفحه رو اشغال میکنه.

ویجت Center به Container میگه که آزاده که هر سایزی که دوست داره داشته باشه ، اما نه بزرگتر از اسکرین ، از اونجایی که Container بچه ای نداره ، و سایزی هم براش تعیین نشده ، تصمیم میگیره که تا جایی که میتونه فضای بیشتری رو اشغال کنه ، بنابراین کل اسکرین رو اشغال میکنه.

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

 

مثال 7

 

 

Center(
     child: Container(
       color: Colors.red,
       child: Container(color: Colors.green, width: 30, height: 30),
      )
 )

 

اسکرین در اینجا Center رو مجبور میکنه که دقیقا سایز یکسانی با خودش داشته باشه ، بنابراین Center کل صفحه رو اشغال میکنه.

Center به Container قرمز میگه که هر سایزی که دلخاهش هست رو میتونه داشته، اما نه بزرگتر از اسکرین . از اونجایی که Container سایزی نداره و تنها یک child داره ، تصمیم میگیره که سایزی هم اندازه child خودش داشته باشه.

Container قرمز به child خودش میگه که هر سایزی که دوست داره میتونه داشته باشه، اما نه بزرگتر از سایزی که اسکرین داره 🙂 .

childمون هم از قضا اینجا یه Container سبزه، که میخواد سایزش 30*30 باشه، همونطور که گفته شد، Container قرمز خودش رو هم سایز بچه های خودش میکنه، بنابراین  اونم  30*30 خواهد بود. هیچ رنگ قرمزی نمایش نخواهد داده شد، به این خاطر که Container سبز کل Container قرمز رو اشغال میکنه.

 

مثال 8

 

 

Center(
     child: Container(
              color: Colors.red,
              padding: const EdgeInsets.all(20.0),
              child: Container(color: Colors.green, width: 30, height: 30),
      )
)

Container قرمز خودش رو هم سایز بچه های خودش میکنه، اما به padding خودش هم توجه میکنه. بنابراین سایز 70*70 خواهد داشت ( 30*30 بعلاوه 20 پیکسل padding همه ضلع ها ).رنگ قرمز نشون داده شده به این خاطر هست که از padding استفاده شده و Container سبز سایزی یکسان با مثال قبلی خواهد داشت.

 

مثال 9

 

ConstrainedBox(
         constraints: ConstrainedBox (
         minWidth: 70,
         minHeight: 70,
         maxWidth: 150,
         maxHeight: 150,
       ),
      child: Container(color: Colors.red, width: 10, height: 10),
)

شاید حدث بزنید Container باید سایزی بین 70 تا 150 پیکسل داشته باشه، اما شما در اشتباهید.ConstrainedBox  تنها  Constraint(محدودیت) های بیشتری رو نسبت به اونچه که از parent خودش گرفته تحمیل میکنه .

اینجا، اسکرین ConstraintBox رو مجبور میکنه که دقیقا سایزی هم اندازه خودش خودش داشته باشه، بنابراین به بچه خودش Container میگه که از سایز اسکرین استفاده کنه، به این ترتیب از پارامتر های constraints چشم پوشی میکنه.

 

مثال 10 

 

 

Center(
    child: ConstrainedBox(
           constraints: BoxConstraints(
                     minWidth: 70,
                     minHeight: 70,
                     maxWidth: 150,
                     maxHeight: 150,
            ),
           child: Container(color: Colors.red, width: 10, height: 10),
     )
)

حالا، Center به ConstrainedBox اجازه خواهد داد که هر سایزی حداکثر تا اندازه اسکرین داشته باشه. ConstrainedBox محدودیت های بیشتر رو از طریق constraints خودش روی بچه خودش اعمال میکنه.

بنابراین Container باید بین 70 تا تا 150 پیکسل باشه. البته که سایزی که خودش میخواد 10 پیکسل هستش که در نهایت با سایز 70 پیکسل(حداقل) همه چی تموم میشه

 

مثال 11

 

 

Center(
      child: ConstrainedBox(
           constraints: BoxConstraints(
                minWidth: 70,
                minHeight: 70,
                maxWidth: 150,
                maxHeight: 150,
                ),
          child: Container(color: Colors.red, width: 1000, height: 1000),
      )
)

 

Center به ConstrainedBox اجازه خواهد داد که سایز دلخواهش رو حداکثر تا سایز اسکرین داشته باشه. ConstrainedBox محدودیت های خودش رو با constraint ای که داره روی بچه ش اعمال خواهد کرد .

بنابراین Container باید سایزی بین 70 تا 150 پیکسل داشته باشه. چیزی که البته میخواد سایز 1000 پیکسل هستش، که در نهایت با سایز 150 پیکسل (حداکثر) این داستان هم به پایان میرسه

 

مثال 12

 

 

Center(
       child: ConstrainedBox(
           constraints: BoxConstraints(
                minWidth: 70,
                minHeight: 70,
                maxWidth: 150,
                maxHeight: 150,
            ),
           child: Container(color: Colors.red, width: 100, height: 100),
     )
)

 

Center در اینجا هم مثل مثال های قبلی به ConstrainedBox اجازه خواهد داد که هر سایزی که درلخواهش هست رو حداکثر تا سایز اسکرین داشته باشه.

ConstrainedBox محدودیت های بیشتری رو روی بچه ی خودش از طریق constraints خودش اعمال میکنه.

بنابراین Container باید بین 70 تا 150 پیکسل فضا رو اشغال کنه . البته که چیزی که خودش میخواد سایز 100 پیکسلی هست، که این سایزی هست که در نهایت خواهد داشت چرا که بین 70 تا 150 پیکسل هستش.

 

مثال 13

 

UnconstrainedBox(
        child: Container(color: Colors.red, width: 20, height: 50),
)

اسکرین ، UnconstrainedBox رو مجبور میکنه که دقیقا سایزی هم اندازه خودش داشته باشه .اما به هر حال UnconstrainedBox به Container خودش این اجازه رو میده که هر سایزی که میخواد باشه.

 

مثال 14

 

 

UnconstrainedBox(
       child: Container(color: Colors.red, width: 4000, height: 50),
);

اسکرین، UnconstranedBox رو مجبور میکنه که دقیقا سایز یکسانی با صفحه داشته باشه، UnConstrainedBox به Container خودش این اجازه رو میده که هر سایزی که خواست رو داشته باشه.

متاسفانه، توی این مورد Container ما 4000 پیکسل عرض داره و این سایز بزرگتر از اون هستش که متناسب با UnconstrainedBox باشه، بنابراین UnConstrainedBox ارور وحشتناک “overflow warning” رو نشون میده.

 

مثال 15

 

 

OverflowBox(
       minWidth: 0.0,
       minHeight: 0.0,
       maxWidth: double.infinity,
       maxHeight: double.infinity,
       child: Container(color: Colors.red, width: 4000, height: 50),
);

 

اسکرین در اینجا OverflowBox رو مجبور میکنه که سایز یکسانی با خودش داشته باشه، و OverflowBox به Container خودش این اجازه رو میده که هر سایزی که میخواد رو داشته باشه.

OverflowBox استفاده شده در اینجا مشابه UnConstrainedBox هست، با این تفاوت که این ویجت حتی اگر هم child خودش سایز متناسبی با خودش نداشته باشه ، هیچ خطایی رو نمایش نمیده.

در این مورد Container عرض 4000 پیکسلی داره، و این سایز برای اینکه مناسب ویجت OverflowBox باشه بسیار بزرگه، اما OverflowBox به سادگی فقط اون قسمتی که میتونه رو نمایش میده، و هیچ خطایی هم نمیده :).

 

مثال 16

 

 

UnconstrainedBox(
      child: Container(
          color: Colors.red,
          width: double.infinity,
          height: 100,
    )
)

این کد هیچ چیزی برای ارائه دادن نداره، و در نهایت یک ارور در کنسول مشاهده خواهید کرد.

UnconstrainedBox به child خودش این اجازه رو میده که هر سایزی که دلخواهش باشه داشته باشه،و در اینجا child ش یه Container هست که سایز بی نهایت داره.

فلاتر توانایی نمایش دادن سایز های بینهایت رو نداره، بنابراین دچار خطایی با این پیغام میشه: BoxConstraints forces an infinite width

 

مثال 17

 

 

UnconstrainedBox(
       child: LimitedBox(
             maxWidth: 100,
             child: Container(
                 color: Colors.red,
                 width: double.infinity,
                 height: 100,
             )
        )
)

در اینجا با خطایی مواجه نخواهید شد، چرا که وقتی به LimetedBox یک سایز بینهایت توسط UnConstrainedBox داده شده، اون تنها به child های خودش این اجازه رو میده که در نهایت عرضی با 100 پیکسل داشته باشن.

نکته، اگر UnConstrainedBox رو به یک ویجت Center تغییر بدین، LimitedBox دیگه محدودیت خودش رو اعمال نمیکنه ( چرا که محدودیتش تنها وقتی اعمال میشه که در یک constraint نا محدود قرار بگیره)، و عرض Container میتونه فراتر از 100 پیکسل هم باشه.

این مثال میتونه تفاوت بین LimitedBox  و ConstrainedBox رو شفاف بکنه.

 

مثال 18

 

 

FittedBox(
     child: Text(‘Some Example Text.’),
)

اسکرین در اینجا FittedBox رو مجبور میکنه که دقیقا سایز یکسانی با خودش داشته باشه. Text به صورت طبیعی عرض مورد نیازش رو اشغال میکنه(عرض intrinsic یا ذاتی هم گفته میشه) که وابسته به مقدار متن و فونت متن و … هستش.

FittedBox به Text این اجازه رو میده که هر سایزی که دلخواهش هست رو داشته باشه، اما بعد از اینکه Text سایز خودش رو به FittedBox، اعلام میکنه، FittedBox مقیاس Text رو متناسب با صفحه تغییر میده تا همه ی عرضی که در اختیار هست رو پر کنه.

 

مثال 19

 

Center(
     child: FittedBox(
            child: Text(‘Some Example Text.’),
     )
)

اما چه اتفاقی میوفته اگر Fittedbox رو در یک ویجت Center قرار بدیم ؟ Center به FittedBox این اجازه رو میده که هر سایزی که دلخواهش هست رو داشته باشه، البته حداکثر تا سایزی که اسکرین اجازه میده.

FittedBox اینجا اختیار سایز خودش رو به Text میسپاره، و به Text این اجازه رو میده سایز دلخواهش رو داشته باشه، از اونجایی که FittedBox و Text  سایز یکسانی دارن، اینجا FittedBox لازم نیست زحمت متناسب کردن Text رو با عرضی که در اختیارش هست بکشه.

 

مثال 20

 

 

Center(
     child: FittedBox(
           child: Text(‘This is some very very very large text that is too big to fit a regular screen in a single line.’),
      )
)

حالا چه اتفاقی میوفته اگر FittedBox درون ویجت Center باشه، اما Text بزرگتر از اون باشه که بتونه متناسب سایز اسکرین باشه؟

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

 

مثال 21

 

 

Center(
     child: Text(‘This is some very very very large text that is too big to fit a regular screen in a single line.’),
)

اگر به هر دلیلی FittedBox رو حذف کنیم، Text حداکثر عرضی که اسکرین داره رو اشغال میکنه، و متن رو هم با توجه به نیازش به دوتا خط تبدیل میکنه تا متناسب با صفحه بشه.

 

مثال 22

 

 

FittedBox(
      child: Container(
              height: 20.0,
              width: double.infinity,
      )
)

نکته : FittedBox فقط میتونه ویجت هایی رو تغییر سایز بده و متناسبشون بکنه که باشن (به این معنی که عرض و ارتفاع مشخصی داشته باشن). در غیر این صورت چیزی رو نمایش نخواهد داد، و در نهایت یک خطا در کنسول ایجاد میکنه.

 

مثال 23

 

 

Row(
    children:[
           Container(color: Colors.red, child: Text(‘Hello!’)),
           Container(color: Colors.green, child: Text(‘Goodbye!)),
    ]
)

اسکرین Row رو مجبور میکنه که سایزی هم اندازه خودش داشته باشه.

درست مثل یک UnConstrainedBox، ویجت Row هیچ constraint ای روی child های خودش اعمال نمیکنه، و بهشون این اجازه رو میده که هر سایزی که دلخواهشون هست رو داشته باشن. سپس Row اونهارو یک به یک کنار هم قرار میده، و هر فضای اضافه ای اگر باقی بمونه، خالی خواهد موند.

 

 مثال 24

 

 

Row(
      children:[
           Container(color: Colors.red, child: Text(‘This is a very long text that won’t fit the line.’)),
           Container(color: Colors.green, child: Text(‘Goodbye!’)),
      ]
)

از اونجایی که Row هیچ constraint ای روی child های خودش اعمال نمیکنه، کاملا قابل تصور هست که بچه هاش عرضی بزرگتر از اونچه که Row براش مقدور هست رو اشغال بکنن. توی این مورد ، درست مثل UnConstrainedBoxt، ویجت Row خطای  “overflow warning” رو نمایش میده.

 

مثال 25

 

 

Row(
     children:[
          Expanded(
               child: Container(color: Colors.red, child: Text(‘This is a very long text that won’t fit the line.’))
          ),
         Container(color: Colors.green, child: Text(‘Goodbye!’)),
     ]
)

وقتی که یکی از child های Row توی یک ویجت Expanded قرار میگیره، Row دیگه به اون child این اجازه رو نمیده که عرض خودش رو ، خودش تعیین کنه.

در عوض، عرضش توسط Expanded متناسب با بقیه child ها تعیین میشه،و بعد از اون ویجت Expanded،اون child ای که در حصارش هست رو مجبور میکنه که سایزی مثل ویجت Expanded داشته باشه.

به عبارت دیگه، هنگامی که از ویجت Expanded استفاده کنید،عرض child اصلی در واقع بی اعتبار میشه و نادیده گرفته میشه.

 

مثال 26

 

 

Row(
      children:[
          Expanded(
               child: Container(color: Colors.red, child: Text(‘This is a very long text that won’t fit the line.’)),
          ),
         Expanded(
              child: Container(color: Colors.green, child: Text(‘Goodbye!’),
         ),
     ]
)

اگر همه ی child های Row توی ویجت Expanded محصور شده باشن، هر کدوم از Expanded ها مقداری رو به پارامتر flex خودش اختصاص میده، و بعد از اون هر کدوم از ویجت های Expanded میاد و child خودش رو مجبور میکنه که سایزی هم اندازه خودش داشته باشه.

به عبارت دیگه، Expanded از عرض ترجیحی child های خودش چشم پوشی میکنه. 

 

مثال 27

 

 

Row(children:[
       Flexible(
            child: Container(color: Colors.red, child: Text(‘This is a very long text that won’t fit the line.’))),
       Flexible(
          child: Container(color: Colors.green, child: Text(‘Goodbye!’))),
    ]
)

 اگر از Flexible بجای Expanded استفاده کنید، تنها تفاوتی که خواهید دید این هست که Flexible به child خودش این اجازه رو میده که عرض یکسان یا کوچکتر از اونچه که خودش هست رو داشته باشه، در حالی که Expanded بچه های خودش رو مجبور میکنه که دقیقا سایزی هم اندازه خودش داشته باشن.

اما هردوی Expanded  و Flexible موقعی که میخوان سایز خودش رو تعیین کنن از عرضی که child شون داره رو نادیده میگیرن.

نکته : این صحبت ها به این معنی هست که این غیرممکنه که child های Row به تناسب سایزی که دارن فضا رو اشغال کنن. Row یا دقیقا از عرض child استفاده میکنه یا وقتی از ویجت های Expanded  و Flexible استفاده میشه، کاملا ازش چشم پوشی میکنه.

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

 

مثال 28

 

 

Scaffold(
     body: Container(
           color: blue,
           child: Column(
                 children: [
                       Text(‘Hello!’),
                       Text(‘Goodbye!’),
                  ]
      )))

اسکرین، Scaffold رو مجبور میکنه که سایز یکسانی با خودش داشته باشه. بنابراین Scaffold کل صفحه رو اشغال میکنه.

Scaffold به Container میگه که هر سایزی که دلخواهش هست رو میتونه داشته باشه، اما نه بزرگتر از اونچه که اسکرین هست.

نکته : وقتی که یه ویجت به بچه ی خودش میگه که میتونه کوچکتر از از یک سایز مشخصی باشه،  ما میگیم که اون ویجت constraint یا محدودیت های شل و سستی(“loose”) روی بچه های خودش اعمال کرده. در این مورد بیشتر در آینده صحبت خواهیم کرد.

 

مثال 29

 

 

Scaffold(
      body: SizedBox.expand(
           child: Container(
                   color: blue,
                   child: Column(
                        children: [
                           Text(‘Hello!’),
                           Text(‘Goodbye!’),
                  ],
              ))))

اگر ما بخواهیم بچه ی Scaffold رو دقیقا هم سایز خودش بکنیم، میتونیم اون رو درون یک SizedBox.expand قرار بدیم.

نکته : وقتی یک ویجت به بچه ی خودش میگه که باید سایز مشخصی داشته باشی، ما میگیم که

constraint یا محدودیت های محکم و سختی (“tight”) روی بچه های خودش اعمال کرده .

 

Tight × Loose Constraints

محدودیت های سخت و نرم

 

خیلی رایجه که بشنوید بعضی از constraint ها tight یا loose هستن، بنابر ارزششو داره که درموردش بیشتر بدونید.

یک constraint وقتی که tight هست، فقط یک راه رو جلوی پای ما میذاره، سایز دقیق و مشخص. به عبارت دیگه یک tight constraint حداقل و حداکثر عرضی که داره دقیقا مساوی هم دیگه هستن;  و حداقل و حداکثر ارتفاعش هم به همین ترتیب با هم دیگه مساوی هستن.

اگر box.dart رو توی فلاتر بیشتر کنکاش کنید و constructor اون رو ببینید این کد رو پیدا میکنید:

 

BoxConstraints.tight(Size size)
      : minWidth = size.width,
        maxWidth = size.width,
        minHeight = size.height,
        maxHeight = size.height;

اگر مثال دوم رو دوباره ببینید، اون به ما میگه که اسکرین، Container قرمز رو مجبور میکنه که دقیقا هم سایز خودش باشه،البته که اسکرین این کارو با اعمال tight constraint ها روی Container انجام میده.

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

 

BoxConstraints.loose(Size size)
            : minWidth = 0.0,
              maxWidth = size.width,
              minHeight = 0.0,
              maxHeight = size.height;

 

یادگرفتن قوانین لایه ها برای ویجت های خاص

دونستن قانون عمومی لایه ها، لازم هست ولی کافی نیست.

 

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

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

سورس کد مربوط به لایه معمولا پیچیده ست ، پس شاید بهتر باشه که داکیومنت رو بخونید. بهرحال اگر تصمیم به خوندن سورس لایه ها دارید، میتونید به سادگی از امکانات IDE خودتون استفاده کنید (مثلا ctrl+click رو ویجت) 

 

اینجا یک مثال وجود داره :

  • یک ویجت Column توی کد خودتون پیدا کنید و سورس کدش رو باز کنید(Ctrl+B توی InteliJ). به فایل basic.dart خواهید رفت. از اونجایی که Column از Flex ارث بری کرده (extend شده) ، به سورس کد Flex برید ( همچنان در basic.dart)
  • حالا به پایین اسکرول کنید تا یک متد با نام createRenderObject رو پیدا کنید.همون طور که میبینداین متد RenderFlex رو برمیگردونه که متناظر با render-object برای Column هستش. حالا به سورس کد RenderFlex برید که شما رو به فایل flex.dart خواهد برد.
  • حالا به پایین اسکرول کنید تا یک متد به نام performLayout رو مشاهده کنید. این متدی هست هست که چیدمان ویجت Column رو انجام میده.

یک تشکر ویژه از  Simon Lightfoot برای ساختن هدر و عکس این مقاله و پیشنهاداتش برای محتوا این مقاله.

 

پکیج های مرتبط با Layout که توسط Marcelo Glasberg نوشته شدن

پکیج های دیگر این نویسنده :

 

https://github.com/marcglasberg

https://twitter.com/GlasbergMarcelo

https://stackoverflow.com/users/3411681/marcg

 

 

 

2 پاسخ

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *