در این مطلب میخوایم با همدیگه نحوه ساخت اپلیکیشن های واکنشگرا و با استفاده از فریمورک فلاتر یاد بگیریم.
بعضی اوقات ممکن هست که تنظیمات اپلیکیشن در اثر چرخیدن صفحه نمایش تغییر کند و یا به دلیل وجود طیف گسترده و متنوعی از گوشی های هوشمند و تبلت با سایز های مختلف صفحه نمایش, طراحی صفحه ما در دستگاه های دیگر دچار مشکل شود.
برای تمام این کارها شما نیاز دارید تا اپلیکیشن خودتون و بصورت واکنشگرا طراحی کنید تا در حالت های مختلف به درستی کار کند.
در این مطلب نحوه پیاده سازی صفحات واکنشگرا در فلاتر را در قالب یک پروژه پیام رسان پیاده سازی میکنیم. همچنین موارد زیر را هم فرا خواهید گرفت.
طراحی واکنشگرا یا طراحی ریسپانسیو (Responsive Design) روشی برای طراحی وب سایت یا اپلیکیشن است که به طور خودکار چیدمان و اندازه عناصر رابط کاربری را متناسب با اندازه صفحه نمایش دستگاه کاربر تنظیم می کند.
به عبارت دیگر، با طراحی واکنشگرا، وب سایت یا اپلیکیشن شما در هر دستگاهی، چه دسکتاپ، چه لپ تاپ، چه تبلت و چه موبایل، به درستی نمایش داده خواهد شد.
مزایای طراحی واکنشگرا:
اصول طراحی واکنشگرا:
اپلیکیشنی که شما طراحی میکنید ممکن است روی آیفون,تبلت و گوشی های اندروید و یا تلویزیون اجرا شود.
به همین دلیل باید اطمینان حاصل کنید طراحی که انجام داده اید روی تمام صفحه نمایش ها با سایز و تنظیمات مختلف به درستی کار میکند.
فلاتر ویجت و کلاس های مختلفی و برای پیاده سازی برنامه های واکنشگرا در خود جای داده است که با چندتا از اون ها کار خواهیم کرد.
برنامه شما ممکن است شامل یک TextField باشه که باعث می شود هنگام استفاده از آن یک صفحه کلید بصورت پاپ آپ باز شود و طراحی صفحه شما را به هم بریزد.
در فلاتر ویجت Scaffold بصورت خودکار کار مدیریت تغییرات حالت صفحه کلید را انجام می دهد.
به طور خلاصه این کار و با تنظیم کردن فاصله و ستون های اضافی در پایین صفحه انجام می دهد. که البته میتونید آن را غیرفعال کنید.
کاربران میتونند صفحه نمایش گوشی خودشون و بصورت مکرر در حالت های افقی و عمودی تغییر دهند.
شما میتونید این تغییر جهت را در اپلیکیشن خودتون غیرفعال کنید اما در این صورت تجربه کاربری خوبی را برای استفاده کنند به ارمغان نمی آورید.
هنگام تغییر جهت صفحه نمایش MediaQuery به شما کمک میکنه که رابط کاربری خودتون و دوباره بسازید.
ویجت MaterialApp از این قابلیت استفاده میکنه و اگر لایه اصلی شما MaterialApp باشد به طور خودکار دوباره ساخته می شود.
برای شروع کار سورس کدی که در انتهای مطلب قرار دارد را دانلود کنید و فایل starter و داخل محیط برنامه نویسی فلاتر خودتون باز کنید.
یکی از راه هایی که میتونید صفحات واکنشگرا طراحی کنید استفاده از MediaQuery هست تا سایز واقعی صفحه گوشی را بدست بیاورید.
وارد فایل ChatListPage.dart شوید و محتویات build(BuildContext context) را با کدهای زیر جایگزین کنید.
var hasDetailPage =
MediaQuery.of(context).orientation == Orientation.landscape;
// 2
Widget child;
if (hasDetailPage) {
// 3
child = Row(
children: [
// 4
SizedBox(
width: 250,
height: double.infinity,
child: _buildList(context, hasDetailPage),
),
// 5
Expanded(child: _buildChat(context, selectedIndex)),
],
);
} else {
// 6
child = _buildList(context, hasDetailPage);
}
return Scaffold(
appBar: AppBar(
title: Text("Chats"),
),
body: SafeArea(
// 7
child: child,
),
);
بریم سراغ توضیحات کدهای بالا.
ویجت دیگه ای که میتونید همین کار و هم با اون انجام بدید LayoutBuilder نام داره که بالاتر اشاره کردیم بهش.
مشکل دیگه ای که وجود داره در طراحی بالا اندازه نبودن سایز آواتار کاربران هست که باید رفع کنیم.
فایل ChatListPage.dart را باز کنید و کدهای زیر را در آن قرار دهید.
return Scaffold(
appBar: AppBar(
title: Text("Chats"),
),
body: SafeArea(
// 1
child: LayoutBuilder(builder: (builder, constraints) {
// 2
var hasDetailPage = constraints.maxWidth > 600;
if (hasDetailPage) {
// 3
return Row(
children: [
// 4
SizedBox(
width: 250,
height: double.infinity,
child: _buildList(context, hasDetailPage),
),
// 5
Expanded(child: _buildChat(context, selectedIndex)),
],
);
} else {
// 6
return _buildList(context, hasDetailPage);
}
}),
),
);
این بار ما از LayoutBuilder استفاده کردیم و بیاید نگاهی بندازیم ببینیم چیکار کردیم.
با اجرا کردن کد بالا میبینید که تفاوتی بین دو روش وجود ندارد.
همونطور که در تصاویر بالا دیدید متنی که در داخل کادر های رنگی قرار دارد در حالت افقی به شکل کوچک باقی مانده اند و تمام بخش کادر را پوشش نمیدهند.
کاری که باید انجام دهید این هست که اندازه متن هماهنگ با اندازه ویجت والد خودش تغییر کند.
این کار و با ویجت FittedBox انجام میدیم.
فایل AvatarImageView.dart را باز کنید. محتویات _buildContent(Color textColor) را نگاه کنید.
یک ویجت Text میبینید. این Text را داخل FittedBox قرار دهید به شکل زیر.
// 1
return FittedBox(
// 2
fit: BoxFit.contain,
// 3
child: Text(
initials,
style: TextStyle(color: textColor, fontSize: 14),
),
);
این کار باعث می شود که ویجت Text ویجت والد خودش و پر کند و حالت BoxFit.contain نیز را برای آن قرار میدهیم.
این کار باعث می شود که به اندازه ویجت والد ویجت فرزند بزرگ شود فقط و از کادر بیرون نرود.
نتیجه به شکل زیر است.
شما بنا به نیاز خودتون میتونید از حالت های دیگه BoxFit هم استفاده کنید که در تصویر زیر تمام آنها به خوبی نمایش داده شده است.
در انتهای صفحه چت یک آیکون عکس از شکلی شبیه به کاغذ قرار داره که با انتخاب اون میتونید عکس های گالری خودتون و داخل صفحه چت ارسال کنید.
معمولا همزمان که صفحه گفتگو نمایش داده می شود کاربر میتواند عکس های خود را نیز انتخاب کند.
اما در حال حاضر شما نمیتونید عکسی از گالری ارسال کنید چون بخش گالری نمایش داده نمیشود و شما تصویر زیر را میبینید.
برای حل این مشکل فایل ConversationPage.dart را باز کنید و به دنبال بخش SquareGallery() بگردید.
این ویجت نمایش داده نمیشود برای اینکه فرزند یک Column هست و نمیتونه اندازه ارتفاع Height خودش و متوجه بشه.
به همین دلیل برای اعمال محدودیت آن را داخل یک AspectRatio قرار میدهیم.
AspectRatio(
aspectRatio: 3,
child: SquareGallery(),
),
گالری ما حالا به نسبت محدودیتی که تعیین کردیم نمایش داده می شود. در واقع سه برابر عریض تر از ارتفاع.
بسیار خب ما تونستیم که برنامه خودمون و به شکل واکنشگرا طراحی کنیم.
فلاتر به غیر موارد پایه ای که در بالاتر با همدیگه بررسی کردیم روش دیگری هم برای بهینه سازی اپلیکیشن در سایز های مختلف صفحه نمایش دارد به اسم CustomMultiChildLayout.
CustomMultiChildLayout(
delegate: delegate,
children: widgets,
)
در کد بالا به شکل ساده از CustomMultiChildLayout کردیم که ویژگی delegate حتما باید مقدار دهی شود.
این delegate میتونه یک آبجکت از کلاس باشد.
// 1
class RWDelegate extends MultiChildLayoutDelegate {
// 2
@override
void performLayout(Size size) {
// Do your layout here
}
// 3
@override
bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) => false;
}
برای مطالعه بیشتر میتونید به لینک زیر مراجعه کنید.
https://api.flutter.dev/flutter/widgets/CustomMultiChildLayout-class.html
برای یادگیری برنامه نویسی فلاتر به صورت مقدماتی تا پیشرفته به صورت کاملا پروژه محور نیز میتوانید از دوره آموزش فلاتر مجموعه استفاده نمایید.