مقدمة : 

إن الغرض الأكبر من التطبيقات هو عرض المعلومات على شكل منظم يسهل قراءته والتعامل معه , لهذا كانت القوائم في فلاتر ListView التي ستقوم بعرض قائمة من العناصر على المحور الشاقولي أو الأفقي مع مع خصائص متكاملة للتحكم الكامل بها .
في هذا المقال سنعرض أبرز استخدامات القوائم واهم خصائصه التي ستتعامل معها بشكل دوري أثناء إنجازك لواجهة التطبيق .

 

ListView Flutter Widget

تضمين القائمة ListView  : 

يتم تضمين قائمة العناصر ضمن عنصر آخر يمكن تحديد قياسه , مثل Container أو SizedBox , أو ضمن عنصر سيتحدد قياسه بناءً على مقاس الشاشة المتبقي مثل Flexble أو Expanded , و تحمل القائمة مصفوفة من العناصر داخلها List<Widget>  

سيقوم الكود التالي بعرض قائمة تحوي ثلاث حاويات Container لكل منها خصائصها ولونها 

 


ListView(
  padding: const EdgeInsets.all(8),
  children: [
    Container(
      height: 50,
      color: Colors.red,
      child: const Center(child: Text('Item 1')),
    ),
    Container(
      height: 50,
      color: Colors.blue,
      child: const Center(child: Text('Item 1')),
    ),
    Container(
      height: 50,
      color: Colors.orange,
      child: const Center(child: Text('Item 1')),
    ),
  ],
)

 

خصائص القوائم : 

• children : مصفوفة من العناصر List<Widget> المحتواة داخل القائمة .
scrollDirection : إتجاه القائمة و يأخذ قيمة  Axis وهو من نوع Enum ويحمل نوعين (Axis.vertical,Axis.horizental ) .
reverse : عكس القائمة , حيث ستعرض عناصر القائمة بشكل معكوس ويأخذ قيمة bool والقيمة الافتراضية له false .
• controller : يأخذ  instance من كلاس ScrollController ويستخدم للتحكم بالقائمة حيث يمكنك من خلاله قراءة أو تعيين حالة السحبscroll بشكل برمجي .
• physics : يتم من خلالها تعيين ماذا سيحدث عند وصول المستخدم لنهاية القائمة أو عند توقفه عن السحب و يأخذ قيمة من كلاس ScrollPhysics  .
shrinkWrap : من نوع bool و يعني أن  قياس القائمة سيحتاج إلى إعادة حساب كلما تغير السحب , وتستخدم عادة إذا كان قياس العناصر المحتواة ضمن القائمة غير محدد وقياس العنصر الحاوي للقائمة غير محدد ( كاستخدام القائمة ضمن Flexble أو Expanded ) والقيمة الافتراضية له هي false .
• padding : يستخدم لوضع حدود داخلية لبدء ظهور العناصر ويأخذ قيمة EdgeInsets كمثال  EdgeInsets.all(5)



سطر القائمة ListTile :

هي عناصر جاهزة على شكل سطور  , تحوي خصائصاً بسيطة يمكن وضعها داخل القائمة ( كأبناء )  أو تضمينها في أي مكان في التطبيق , لها ارتفاع ثابت و تحتوي نصوصاً وعناصر بادئة leading أو لاحقة trailing .

يقسم سطر العنصر إلى ثلاثة أقسام يمكن استعمالها جميعها أو بعضها وهي : 

leading : عنصر البادئة ( أول السطر ) ويظهر في الصورة التالية كشعار flutter .
النص : عبارة عن سطرين من النصوص الأول هو العنوان title و الثاني هو النص اللاحق subtitle .
trailing : عنصر اللاحقة ( في آخر السطر ) ويظهر في الصورة التالية كأيقونة النقاط الثلاث .

Flutter  ListTile

أبرز خصائص عنصر سطر القائمة : 

 
ListTile(
             title: const Text('Title will shown here'),
             subtitle: const Text('subTitle will shown here'),
             leading : Icon(Icons.heart),
             trailing  : Icon(Icons.more_vert),
             dense : true,
             tileColor: Colors.blue,
             onTap: () {
                          Navigator.pop(context);
             },
 ),


• leading : يأخذ قيمة Widget حيث يمكنك استعمال أي عنصر ( صورة - أيقونة - نص ) .

• title :  العنوان ويأخذ قيمة Widget و غالباً ما يستعمل فيه النص Text ويظهر بصورة افتراضية بلون غامق .

• subtitle : العنوان الفرعي ويأخذ قيمة Widget و غالباً ما يستعمل فيه النص Text ويظهر بصورة افتراضية بلون فاتح.

• trailing : يأخذ قيمة Widget و يمكنك استعمال أي عنصر وغالباً ما تستخدم الأيقونات فيه .

• isThreeLine : يأخذ قيمة bool ويحدد فيما إذا كان السطر سيعرض ثلاث سطور من النصوص ( سطرين في العنوان الفرعي ) .

• enabled : يأخذ قيمة bool ويحدد فيما إذا كان العنصر قابلاً للضغط عليه أم لا ( نشط أو غير نشط ) .

 

• minVerticalPadding : يأخذ قيمة double ويحدد التباعد الداخي  على المحور الرأسي لعنصر القائمة .

• contentPadding : يأخذ قيمة كلاس EdgeInsetsGeometry ويحدد التباعد الداخلي للسطر حسب القيمة المعينة مثل EdgeInsets.all(5)

• mouseCursor : شكل مؤشر الماوس ( في حال تشغيل التطبيق للويب ) يأخذ قيمة كلاس MouseCursor .

• style  : ستايل السطر ويأخذ قيمة ListTileStyle و هو من نوع Enum ويحمل خيارين : list و تعني أنه عنصر قائمة عادية أو drawer وتعني أنه عنصر قائمة جانبية .

• textColor : لون النص ويأخذ قيمة لون Color حيث يمكنك التحكم بلون النص من خصائص السطر دون الحاجة للتحكم به ضمن خصائص النص .

• tileColor : لون خلفية السطر ويأخذ قيمة لون Color .

• dense : يأخذ قيمة bool ويحدد فيما إذا كان السطر جزء من قائمة طويلة ( سيتقلص ارتفاعه إذا كانت قيمة dense هي true ) .

• onTap : يأخذ قيمة Function ويحدد ما سيتم تنفيذه عند الضغط على السطر 

ملاحظة هامة : 

يمكنك التحكم في خصائص السطور بشكل عام من خلال تحديد خصائصها عبر الثيم العامة  للتطبيق ThemeData داخل خصائص MaterialApp  , حيث لن تضطر لتعيين خصائص كل واحدة على حدا .


MaterialApp(
      theme: ThemeData(
          listTileTheme: const ListTileThemeData(
        textColor: Colors.white,
      )),
      home: Scaffold(
        appBar: AppBar(title: const Text('ListTile Samples')),
        body: const LisTileExample(),
      ),
);

هل من داع لاستخدام ListTile  , حيث يمكن بسهولة إنشاء عنصر شبيه من Row , Column ؟ 

الإجابة ببساطة أن هذا العنصر وجد لكي يسهل عليك إنشاء سطر قائمة و تم تخصيص الكثير من الخصائص له للتحكم بشكله و ألوانه , 
كما ان أغلب عناصره لها قيم افتراضية ( مقاسات ) تم وضعها استناداً لقواعد تصميم الواجهات , أنت بغنىً عن إعادة تصميمها وتشكيلها , لكن إذا كنت تحتاج لعنصر قائمة بخصائص محدودة يمكنك إنشاؤه بنفسك وتوفير مساحة من معالجة كافة خصائص سطر القائمة ListTile .

 



القائمة آلية البناء ListViewBuilder  : 

لنفرض أنك تريد عرض قائمة طويلة من المعلومات , قد تكون ضمن مصفوفة أو قائمة متغيرة من API خارجي , هل ستقوم بكتابة كود لكل عنصر كعنصر قائمة ؟ 
الحل هنا هو استخدام القائمة آلية البناء حيث يمكن من خلالها تحديد عدد العناصر المتوقع , وكيف سيتم بناء هذه العناصر وفق ترتيبها ضمن قائمة المعلومات .

في المثال التالي , قائمة معلومات عن أسماء الحيوانات ونود عرضها ضمن قائمة عناصر من نوع Text : 


final List animals = ["dog", "cat", "Cow", "Duck", "Horse", "Rabbit", "Hen"];

بكل سهولة سوف نستخدم عنصر ListView.builder الذي سنعطيه عدد العناصر والذي هو animals.length وسيتم الدوران على هذه القائمة مثل حلقة for في لغات البرمجة من خلال خاصية itemBuilder التي تأخذ 2 بارمتر هما BuildContext وهو يدل على مكان العنصر ضمن شجرة عناصر واجهة المستخدم و الثاني هو من نوع int وهو الرقم الحالي عند الدوران على عناصر القائمة ويبدأ من صفر "dog"وينتهي بموقع آخر عنصر ضمن عناصر قائمة الحيوانات السابقة 6 ويشير إلى "Hen"


ListView.builder(
    padding: const EdgeInsets.all(8),
    itemCount: animals.length,
    itemBuilder: (BuildContext context, int index) {
      return Container(
        height: 50,
        child: Center(child: Text(Animals [index])),
      );
    }
  )

أما عن خصائص العنصر فهو يحوي نفس خصائص القائمة ListView مع الخاصيتين (itemCount,itemBuilder)




المراجع : 

ListView class - widgets library - Dart API (flutter.dev)

ListTile class - material library - Dart API (flutter.dev)

ListTileStyle enum - material library - Dart API (flutter.dev)