۱۰ پکیج برتر و محبوب فلاتر | فهرست کاربردی

۴۵۲ بازدید
آخرین به‌روزرسانی: ۱۴ شهریور ۱۴۰۲
زمان مطالعه: ۸ دقیقه
۱۰ پکیج برتر و محبوب فلاتر | فهرست کاربردی

فلاتر (Flutter) یک کیت ابزار UI ارائه شده از سوی گوگل است که برای ساخت اپلیکیشن‌های زیبایی استفاده می‌شود که به صورت نیتیو از یک کدبیس منفرد برای موبایل، وب و دسکتاپ کامپایل می‌شوند. در این مقاله 10 پکیج برتر و محبوب فلاتر را در یک فهرست کاربردی ارائه می‌کنیم که ایده‌ای کلی در مورد میزان بلوغ فلاتر به عنوان یک پلتفرم ارائه می‌کنند.

فلاتر بر مینای زبان برنامه‌نویسی دارت (Dart) عمل می‌کند. این زبان یک جامعه بزرگ و زنده روی وب‌سایت Dart.dev دارد که هم پشتیبانی رسمی از این زبان انجام می‌دهند و هم پکیج‌های شخص ثالث برای ایجاد بهره‌وری بیشتر در فرایند توسعه فلاتر عرضه می‌کنند.

اگر هنوز با فلاتر آشنا نشده‌اید، پیشنهاد می‌کنیم ابتدا با استفاده از مقاله‌های زیر در مورد فلاتر، ویژگی‌ها و کاربردهای آن اطلاعات مقدماتی را به دست آورید:

HTTP

این پکیج (+) روی پلتفرم‌های اندروید، iOS و وب کار می‌کند. این روزها هر چیزی مبتنی بر وب است و از این رو یک کتابخانه قوی HTTP چیزی است که هر کس به آن نیاز دارد. این پکیج دارت شامل یک مجموعه از تابع‌ها و کلاس‌های سطح بالا است که امکان مصرف منابع HTTP را تسهیل می‌کند. این پکیج به خوبی توسعه یافته است و به صورت فعالانه‌ای از سوی تیم دارت نگهداری می‌شود. این پکیج از سال 2012 معرفی شده است و از این رو در حال حاضر به بلوغ کامل رسیده است.

کتابخانه HTTP دارت تابع‌های سطح بالایی ارائه می‌کند که موجب می‌شود کار با HTTP آسان باشد:

1import 'package:http/http.dart' as http;
2# Posting data
3var url = 'https://example.com/whatsit/create';
4var data = {'name': 'Jack', 'age': 38};
5var response = await http.post(url, body: data);
6print('Response status: ${response.statusCode}');
7print('Response body: ${response.body}');
8# A simple GET request
9print(await http.read('https://example.com/foobar.txt'));

flutter_slidable

این پکیج فلاتر (+) روی پلتفرم‌های اندروید، iOS و وب کار می‌کند.

پلاگین flutter_slidable یک ویجت اسلایدر با امکانات زیاد به پروژه شما اضافه می‌کند. اسلایدرهای مانند این غالباً در لیست‌های قابل اسکرول دیده می‌شوند. اپلیکیشن جیمیل یک مثال مهم از این ویجت است و نشان می‌دهد که لیست اسلایدی یک بهینه‌سازی چشمگیر در زمینه بهره‌وری استفاده از اپلیکیشن محسوب می‌شود.

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

  • لیست‌های ویجت اصلی (چپ/بالا) و ثانویه (راست/پایین) را به صورت اکشن‌های گزینه‌های اسلاید می‌پذیرد.
  • می‌تواند محو شود.
  • دارای چهار پنل اکشن داخلی است.
  • دو ویجت اکشن اسلاید داخلی دارد.
  • انیمیشن داخلی برای محو شدن دارد.
  • لی‌آوت‌ها و انیمیشن‌های سفارشی به آسانی تولید می‌شوند.
  • زمانی که روی یک اکشن اسلاید ضربه بزنید، بسته خواهد شد (قابل override است).
  • گزینه‌ای آسان برای غیر فعال‌سازی افکت اسلاید دارد.

Shared Preferences

این پکیج (+) روی پلتفرم‌های اندروید، iOS، وب و لینوکس عمل می‌کند. پکیج Shared Preferences کتابخانه‌های ذخیره‌سازی دائمی خاص هر پلتفرم را درون خود جای داده است. به این ترتیب می‌توان داده‌های ساده‌ای مانند ترجیح‌های کاربر را ذخیره ساخت. کاربردهای آن به شرح زیر هستند:

  • NSUserDefaults روی iOS و macOS
  • SharedPreferences روی اندروید
  • LocalStorage روی وب‌سایت‌ها
  • یک فایل JSON روی فایل‌سیستم لوکال برای لینوکس

داده‌ها ممکن است روی دیسک به صورت ناهمگام ذخیره شوند و هیچ تضمینی نیست که پس از بازگشت روی دیسک باقی مانده باشند، بنابراین این پلاگین به معنی ذخیره داده‌های مهم نیست. به این منظور باید از sqflite استفاده کنید که در ادامه توضیح داده‌ایم.

Sqflite

این پکیج (+) روی پلتفرم‌های اندروید، iOS و MacOS کار می‌کند. Sqflite یک پلاگین SQLite برای فلاتر است. این پکیج از پلتفرم‌های مختلف پشتیبانی می‌کند، اما وب پشتیبانی نشده است چون هیچ سیستم ذخیره‌سازی دائمی مبتنی بر SQL در مرورگرهای وب تعبیه نشده است. برخی از قابلیت‌های آن به شرح زیر هستند:

  • پشتیبانی از تراکنش‌ها و batch-ها
  • مدیریت خودکار نسخه
  • تابع‌های کمکی برای درج، اجرای کوئری، به‌روزرسانی و حذف داده‌ها
  • عملیات مختلف در نخ پس‌زمینه روی iOS و اندروید اجرا می‌شود تا UI را از قفل شدن بازدارد.

اگر به چیزی بیش از ذخیره ساده داده‌ها نیاز دارید، این بهترین گزینه است.

url_launcher

این پکیج (+) برای پلتفرم‌های اندروید، iOS و وب ارائه شده است. این پلاگین به اجرای یک URL کمک می‌کند. URL-ها می‌توانند به صورت‌های زیر باشند:

  • HTTP مانند http://example.org و https://example.org
  • ایمیل مانند mailto:<e-mail address>‎
  • شماره تلفن مانند tel:<phone number>‎
  • متن‌های پیامک مانند sms:<phone number>‎

کاربرد ابتدایی آن کاملاً سرراست است:

1const url = 'https://flutter.dev';
2if (await canLaunch(url)) {
3  await launch(url);
4} else {
5  throw 'Could not launch $url';
6}

video_player

این پکیج (+) برای پلتفرم‌های اندروید، iOS و وب ارائه شده است.

10 پکیج برتر و محبوب فلاتر

پکیج video_player از فرمت‌های مختلفی پشتیبانی می‌کند، اما همه آن‌ها به پلتفرمی که اجرا می‌کنید، وابسته است. برای نمونه کتابخانه‌های پشتیبانی سیستم‌های iOS و اندروید متفاوت هستند. همچنین روی وب فرمت‌هایی که پشتیبانی می‌شوند به مرورگری که استفاده می‌کنید، وابسته‌اند.

توجه کنید که گرچه این پکیج ویدئو پلیر نام دارد، اما این پلاگین می‌تواند صوت را نیز پخش کند. از آنجا که این پلاگین کاملاً به بلوغ رسیده است و API با ثباتی دارد، می‌توانید از آن به جای برخی موارد دیگر، برای پخش صوت استفاده کنید.

این پلاگین می‌تواند ویدئو را از فایل لوکال (assets) سرور ریموت (مانند یک وب‌سایت) پخش کند. برای نمونه در قطعه کد زیر یک نمونه از روش استفاده از این پکیج را مشاهده می‌کنید.

1/// An example of using the plugin, controlling lifecycle and playback of the
2/// video.
3
4import 'package:flutter/cupertino.dart';
5import 'package:flutter/material.dart';
6import 'package:video_player/video_player.dart';
7
8void main() {
9  runApp(
10    MaterialApp(
11      home: _App(),
12    ),
13  );
14}
15
16class _App extends StatelessWidget {
17  @override
18  Widget build(BuildContext context) {
19    return DefaultTabController(
20      length: 3,
21      child: Scaffold(
22        key: const ValueKey<String>('home_page'),
23        appBar: AppBar(
24          title: const Text('Video player example'),
25          actions: <Widget>[
26            IconButton(
27              key: const ValueKey<String>('push_tab'),
28              icon: const Icon(Icons.navigation),
29              onPressed: () {
30                Navigator.push<_PlayerVideoAndPopPage>(
31                  context,
32                  MaterialPageRoute<_PlayerVideoAndPopPage>(
33                    builder: (BuildContext context) => _PlayerVideoAndPopPage(),
34                  ),
35                );
36              },
37            )
38          ],
39          bottom: const TabBar(
40            isScrollable: true,
41            tabs: <Widget>[
42              Tab(
43                icon: Icon(Icons.cloud),
44                text: "Remote",
45              ),
46              Tab(icon: Icon(Icons.insert_drive_file), text: "Asset"),
47              Tab(icon: Icon(Icons.list), text: "List example"),
48            ],
49          ),
50        ),
51        body: TabBarView(
52          children: <Widget>[
53            _BumbleBeeRemoteVideo(),
54            _ButterFlyAssetVideo(),
55            _ButterFlyAssetVideoInList(),
56          ],
57        ),
58      ),
59    );
60  }
61}
62
63class _ButterFlyAssetVideoInList extends StatelessWidget {
64  @override
65  Widget build(BuildContext context) {
66    return ListView(
67      children: <Widget>[
68        _ExampleCard(title: "Item a"),
69        _ExampleCard(title: "Item b"),
70        _ExampleCard(title: "Item c"),
71        _ExampleCard(title: "Item d"),
72        _ExampleCard(title: "Item e"),
73        _ExampleCard(title: "Item f"),
74        _ExampleCard(title: "Item g"),
75        Card(
76            child: Column(children: <Widget>[
77          Column(
78            children: <Widget>[
79              const ListTile(
80                leading: Icon(Icons.cake),
81                title: Text("Video video"),
82              ),
83              Stack(
84                  alignment: FractionalOffset.bottomRight +
85                      const FractionalOffset(-0.1, -0.1),
86                  children: <Widget>[
87                    _ButterFlyAssetVideo(),
88                    Image.asset('assets/flutter-mark-square-64.png'),
89                  ]),
90            ],
91          ),
92        ])),
93        _ExampleCard(title: "Item h"),
94        _ExampleCard(title: "Item i"),
95        _ExampleCard(title: "Item j"),
96        _ExampleCard(title: "Item k"),
97        _ExampleCard(title: "Item l"),
98      ],
99    );
100  }
101}
102
103/// A filler card to show the video in a list of scrolling contents.
104class _ExampleCard extends StatelessWidget {
105  const _ExampleCard({Key key, this.title}) : super(key: key);
106
107  final String title;
108
109  @override
110  Widget build(BuildContext context) {
111    return Card(
112      child: Column(
113        mainAxisSize: MainAxisSize.min,
114        children: <Widget>[
115          ListTile(
116            leading: const Icon(Icons.airline_seat_flat_angled),
117            title: Text(title),
118          ),
119          ButtonBar(
120            children: <Widget>[
121              FlatButton(
122                child: const Text('BUY TICKETS'),
123                onPressed: () {
124                  /* ... */
125                },
126              ),
127              FlatButton(
128                child: const Text('SELL TICKETS'),
129                onPressed: () {
130                  /* ... */
131                },
132              ),
133            ],
134          ),
135        ],
136      ),
137    );
138  }
139}
140
141class _ButterFlyAssetVideo extends StatefulWidget {
142  @override
143  _ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState();
144}
145
146class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> {
147  VideoPlayerController _controller;
148
149  @override
150  void initState() {
151    super.initState();
152    _controller = VideoPlayerController.asset('assets/Butterfly-209.mp4');
153
154    _controller.addListener(() {
155      setState(() {});
156    });
157    _controller.setLooping(true);
158    _controller.initialize().then((_) => setState(() {}));
159    _controller.play();
160  }
161
162  @override
163  void dispose() {
164    _controller.dispose();
165    super.dispose();
166  }
167
168  @override
169  Widget build(BuildContext context) {
170    return SingleChildScrollView(
171      child: Column(
172        children: <Widget>[
173          Container(
174            padding: const EdgeInsets.only(top: 20.0),
175          ),
176          const Text('With assets mp4'),
177          Container(
178            padding: const EdgeInsets.all(20),
179            child: AspectRatio(
180              aspectRatio: _controller.value.aspectRatio,
181              child: Stack(
182                alignment: Alignment.bottomCenter,
183                children: <Widget>[
184                  VideoPlayer(_controller),
185                  _ControlsOverlay(controller: _controller),
186                  VideoProgressIndicator(_controller, allowScrubbing: true),
187                ],
188              ),
189            ),
190          ),
191        ],
192      ),
193    );
194  }
195}
196
197class _BumbleBeeRemoteVideo extends StatefulWidget {
198  @override
199  _BumbleBeeRemoteVideoState createState() => _BumbleBeeRemoteVideoState();
200}
201
202class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> {
203  VideoPlayerController _controller;
204
205  Future<ClosedCaptionFile> _loadCaptions() async {
206    final String fileContents = await DefaultAssetBundle.of(context)
207        .loadString('assets/bumble_bee_captions.srt');
208    return SubRipCaptionFile(fileContents);
209  }
210
211  @override
212  void initState() {
213    super.initState();
214    _controller = VideoPlayerController.network(
215      'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
216      closedCaptionFile: _loadCaptions(),
217      videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
218    );
219
220    _controller.addListener(() {
221      setState(() {});
222    });
223    _controller.setLooping(true);
224    _controller.initialize();
225  }
226
227  @override
228  void dispose() {
229    _controller.dispose();
230    super.dispose();
231  }
232
233  @override
234  Widget build(BuildContext context) {
235    return SingleChildScrollView(
236      child: Column(
237        children: <Widget>[
238          Container(padding: const EdgeInsets.only(top: 20.0)),
239          const Text('With remote mp4'),
240          Container(
241            padding: const EdgeInsets.all(20),
242            child: AspectRatio(
243              aspectRatio: _controller.value.aspectRatio,
244              child: Stack(
245                alignment: Alignment.bottomCenter,
246                children: <Widget>[
247                  VideoPlayer(_controller),
248                  ClosedCaption(text: _controller.value.caption.text),
249                  _ControlsOverlay(controller: _controller),
250                  VideoProgressIndicator(_controller, allowScrubbing: true),
251                ],
252              ),
253            ),
254          ),
255        ],
256      ),
257    );
258  }
259}
260
261class _ControlsOverlay extends StatelessWidget {
262  const _ControlsOverlay({Key key, this.controller}) : super(key: key);
263
264  static const _examplePlaybackRates = [
265    0.25,
266    0.5,
267    1.0,
268    1.5,
269    2.0,
270    3.0,
271    5.0,
272    10.0,
273  ];
274
275  final VideoPlayerController controller;
276
277  @override
278  Widget build(BuildContext context) {
279    return Stack(
280      children: <Widget>[
281        AnimatedSwitcher(
282          duration: Duration(milliseconds: 50),
283          reverseDuration: Duration(milliseconds: 200),
284          child: controller.value.isPlaying
285              ? SizedBox.shrink()
286              : Container(
287                  color: Colors.black26,
288                  child: Center(
289                    child: Icon(
290                      Icons.play_arrow,
291                      color: Colors.white,
292                      size: 100.0,
293                    ),
294                  ),
295                ),
296        ),
297        GestureDetector(
298          onTap: () {
299            controller.value.isPlaying ? controller.pause() : controller.play();
300          },
301        ),
302        Align(
303          alignment: Alignment.topRight,
304          child: PopupMenuButton<double>(
305            initialValue: controller.value.playbackSpeed,
306            tooltip: 'Playback speed',
307            onSelected: (speed) {
308              controller.setPlaybackSpeed(speed);
309            },
310            itemBuilder: (context) {
311              return [
312                for (final speed in _examplePlaybackRates)
313                  PopupMenuItem(
314                    value: speed,
315                    child: Text('${speed}x'),
316                  )
317              ];
318            },
319            child: Padding(
320              padding: const EdgeInsets.symmetric(
321                // Using less vertical padding as the text is also longer
322                // horizontally, so it feels like it would need more spacing
323                // horizontally (matching the aspect ratio of the video).
324                vertical: 12,
325                horizontal: 16,
326              ),
327              child: Text('${controller.value.playbackSpeed}x'),
328            ),
329          ),
330        ),
331      ],
332    );
333  }
334}
335
336class _PlayerVideoAndPopPage extends StatefulWidget {
337  @override
338  _PlayerVideoAndPopPageState createState() => _PlayerVideoAndPopPageState();
339}
340
341class _PlayerVideoAndPopPageState extends State<_PlayerVideoAndPopPage> {
342  VideoPlayerController _videoPlayerController;
343  bool startedPlaying = false;
344
345  @override
346  void initState() {
347    super.initState();
348
349    _videoPlayerController =
350        VideoPlayerController.asset('assets/Butterfly-209.mp4');
351    _videoPlayerController.addListener(() {
352      if (startedPlaying && !_videoPlayerController.value.isPlaying) {
353        Navigator.pop(context);
354      }
355    });
356  }
357
358  @override
359  void dispose() {
360    _videoPlayerController.dispose();
361    super.dispose();
362  }
363
364  Future<bool> started() async {
365    await _videoPlayerController.initialize();
366    await _videoPlayerController.play();
367    startedPlaying = true;
368    return true;
369  }
370
371  @override
372  Widget build(BuildContext context) {
373    return Material(
374      elevation: 0,
375      child: Center(
376        child: FutureBuilder<bool>(
377          future: started(),
378          builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
379            if (snapshot.data == true) {
380              return AspectRatio(
381                aspectRatio: _videoPlayerController.value.aspectRatio,
382                child: VideoPlayer(_videoPlayerController),
383              );
384            } else {
385              return const Text('waiting for video to load');
386            }
387          },
388        ),
389      ),
390    );
391  }
392}

Crypto

این پکیج (+)‌ روی همه پلتفرم‌ها کار می‌کند. این پکیج که از سوی تیم خود دارت توسعه یافته است، در واقع یک مجموعه از تابع‌های هش رمزنگارانه است که در دارت خالص پیاده‌سازی شده‌اند. این بدان معنی است که نیازی به کتابخانه‌های بیرونی برای عملیاتی ساختن آن ندارید. این پکیج از الگوریتم‌های هش‌سازی زیر پشتیبانی می‌کند:

  • SHA-1
  • SHA-224
  • SHA-256
  • SHA-384
  • SHA-512
  • MD5
  • HMAC (i.e. HMAC-MD5, HMAC-SHA1, HMAC-SHA256)

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

این پکیج (+) روی پلتفرم‌های اندروید، iOS و وب کار می‌کند.

10 پکیج برتر و محبوب فلاتر

یک اسلایدر کاروسل بخشی از بسیاری از وب‌اپلیکیشن‌ها و وب‌سایت‌ها محسوب می‌شود. پلاگین carousel_slider یک اسلایدر زیبا و قابل سفارشی‌سازی عرضه می‌کند که روی پلتفرم‌های مختلف کار می‌کند.

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

1CarouselSlider(
2  options: CarouselOptions(height: 400.0),
3  items: [1,2,3,4,5].map((i) {
4    return Builder(
5      builder: (BuildContext context) {
6        return Container(
7          width: MediaQuery.of(context).size.width,
8          margin: EdgeInsets.symmetric(horizontal: 5.0),
9          decoration: BoxDecoration(
10            color: Colors.amber
11          ),
12          child: Text('text $i', style: TextStyle(fontSize: 16.0),)
13        );
14      },
15    );
16  }).toList(),
17)

کاروسل چند گزینه قابل پیکربندی به شرح زیر دارد:

  • ارتفاع و نسبت ابعادی
  • فعال‌سازی اسکرول بی‌نهایت
  • معکوس کردن جهت کاروسل
  • فعال‌سازی پخش خودکار با بازه زمانی و مدت انیمیشن قابل پیکربندی
  • تعریف کردن جهت اسکرول (افقی یا عمودی)

Path

این پکیج (+) روی پلتفرم‌های اندروید، iOS و وب کار می‌کند. مسیرها هم از یک سو ساده و از سوی دیگر به طرز خارق‌العاده‌ای پیچیده هستند، زیرا بسته به هر پلتفرم متفاوت هستند. برای این که مطمئن شویم که هیچ نوع آسیب‌پذیری به شکل باگ یا مشکل امنیتی در کد خود نداریم، باید در زمان کار با مسیرها، همواره از یک کتابخانه مسیر استفاده کنیم. جهت الحاق یک دایرکتوری و یک فایل با استفاده از جداکننده فایل روی سیستم عامل به صورت زیر عمل می‌کنیم:

import 'package:path/path.dart' as p;
p.join('directory', 'file.txt');

location

این پکیج (+) روی پلتفرم‌های اندروید، iOS، وب و MacOS عمل می‌کند. یکی از مهم‌ترین نکته‌ها در مورد گوشی‌های تلفن، امکان تحرک آن‌ها است که با توانایی ردگیری دقیق موقعیت ترکیب می‌شود. این امکانات موجب شده که کاربردهای بسیار مفیدی به دست آوریم. پلاگین location در فلاتر امکان دسترسی به موقعیت کنونی کاربر را تا حدود زیادی تسهیل می‌کند. این پلاگین زمانی که موقعیت تغییر یابد، Callback-هایی ارائه می‌کند. همچنین نقاط انتهایی API ارائه می‌کند که امکان دسترسی درخواست مناسب را به موقعیت کاربر را فراهم می‌سازد.

10 پکیج برتر و محبوب فلاتر

سخن پایانی

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

بر اساس رای ۲ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
better-programming
نظر شما چیست؟

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