يعد عرض مقاطع فيديو YouTube في تطبيق Flutter أمرًا سهلاً باستخدام المكون الإضافي المناسب. في هذا المنشور، ستتعلم كيفية استخدام مكون Youtube Player Flutter الإضافي لإضافة مقاطع فيديو YouTube إلى تطبيقك. سنغطي كل ما تحتاج إلى معرفته، من الإعداد والتخصيص إلى معالجة المشكلات الشائعة مع المكون الإضافي.
إضافة Flutter لمشغل YouTube
السبب الذي يجعلنا نحدد إصدارًا محددًا هو أن الإصدار الأحدث https://pub.dev/packages/youtube_player_flutter/versions/9.0.2 ، وقت كتابة هذا التقرير، يحتوي على خطأ https://github.com/sarbagyastha/youtube_player_flutter/issues/955 يتسبب في ظهور شريط تحميل بشكل مستمر في الفيديو.
الرئيسية.دارت
<C>
dependencies:
youtube_player_flutter: ^8.1.2
<C>
تنفيذ البرنامج الإضافي لمشغل اليوتيوب
لتنفيذ مكون Youtube Player Flutter، سنقوم بإنشاء YoutubePageعنصر واجهة مستخدم في ملف Dart منفصل باسم . سيتم بعد ذلك عرض youtube_page.dartهذا العنصر باستخدام سمة العنصر في الملف.YoutubePagehomeMaterialAppmain.dart
<C>
import 'package:flutter/material.dart';
import 'package:youtube_videos_demo/youtube_page.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: YoutubePage(),
);
}
}
<C>
في main.dartالملف، نقوم بإرجاع عنصر واجهة المستخدم الخاص بالتطبيق MaterialApp. داخل MaterialAppعنصر واجهة المستخدم، نستخدم homeالسمة لعرض YoutubePageعنصر واجهة المستخدم.
صفحة اليوتيوب.دارت
يمكنك بسهولة العثور على معرف الفيديو في عنوان URL لمقطع فيديو YouTube الذي تريد عرضه. يقع المعرف بعد watch?v=عنوان URL. على سبيل المثال، في عنوان URL https://www.youtube.com/watch?v=PAOAjOR6K_Q، يكون معرف الفيديو هو PAOAjOR6K_Q.
كما هو موضح في لقطة الشاشة أعلاه، يمكننا عرض مقاطع فيديو YouTube في Flutter باستخدام قدر صغير فقط من التعليمات البرمجية.
تجنب تسربات الذاكرة
ولمنع تسرب الذاكرة، من الضروري التخلص من وحدة التحكم بشكل صحيح عندما لا تكون هناك حاجة إليها بعد الآن.
<C>
import 'package:flutter/material.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
class YoutubePage extends StatefulWidget {
const YoutubePage({super.key});
@override
State<YoutubePage> createState() => _YoutubePageState();
}
class _YoutubePageState extends State<YoutubePage> {
final YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: 'PAOAjOR6K_Q',
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: YoutubePlayer(
controller: _controller,
),
),
);
}
}
<C>
في مقتطف التعليمات البرمجية أعلاه، نتخلص من الدالة _controllerعن طريق استدعاء دالة disposeداخل disposeالدالة التي تم تجاوزها. عند استخدام disposeالدالة التي تم تجاوزها، تأكد دائمًا من استدعاء الدالة super.disposeالأخيرة.
إضافة YoutubePlayerFlags
بالإضافة إلى initialVideoIdسمة YoutubePlayerController، يمكننا أيضًا استخدام flagsالسمة. تتيح لنا هذه السمة تعيين مثيل للفئة YoutubePlayerFlagsلتخصيص كيفية تصرف اللاعب.
<C>
final YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: 'PAOAjOR6K_Q',
flags: const YoutubePlayerFlags(
forceHD: true,
endAt: 20,
enableCaption: false,
hideThumbnail: true,
),
);
<C>
في مقتطف التعليمات البرمجية هذا، أضفنا flagsالسمة إلى YoutubePlayerControllerمثيل المتغير _controller. على flagsالسمة، قمنا بتعيين مثيل للفئة YoutubePlayerFlagsوأضفنا أربع سمات لفرض الدقة العالية وإنهاء الفيديو بعد 20 ثانية وتعطيل التسميات التوضيحية وإخفاء الصورة المصغرة.
تخصيص الإجراءات السفلية والعلوية
داخل YoutubePlayer، يمكننا أيضًا تخصيص الإجراءات السفلية والعلوية. راجع المثال أدناه:
<C>
import 'package:flutter/material.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
class YoutubePage extends StatefulWidget {
const YoutubePage({super.key});
@override
State<YoutubePage> createState() => _YoutubePageState();
}
class _YoutubePageState extends State<YoutubePage> {
final YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: 'PAOAjOR6K_Q',
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: YoutubePlayer(
bottomActions: [
const SizedBox(width: 14),
CurrentPosition(),
const SizedBox(width: 8),
ProgressBar(
isExpanded: true,
colors: const ProgressBarColors(
playedColor: Color(0xFFFF0000),
handleColor: Color(0xFFFF0000),
backgroundColor: Colors.grey,
),
),
RemainingDuration(),
],
controller: _controller,
topActions: const [
PlaybackSpeedButton(),
],
),
),
);
}
}
<C>
في مقتطف التعليمات البرمجية أعلاه، قمنا بتخصيص كل من الإجراءات السفلية والعلوية لعلامتي YoutubePlayer. بالنسبة للإجراءات السفلية، قمنا بتضمين CurrentPositionالمؤشر وعلامة ProgressBar, والمؤشر RemainingDuration. لقد استخدمنا SizedBoxعناصر واجهة المستخدم لإضافة مسافات بين هذه العناصر وضبطنا ProgressBarألوان عناصر واجهة المستخدم لتتوافق مع مشغل YouTube الأصلي.
تخصيص مشغل اليوتيوب
لمزيد من المرونة، يمكننا استخدام YoutubePlayerBuilderالفئة لتخصيص المشغل. يوفر هذا النهج تحكمًا أكبر في سلوك المشغل، وخاصةً عند دخوله أو خروجه من وضع ملء الشاشة.
<C>
import 'package:flutter/material.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
class YoutubePage extends StatefulWidget {
const YoutubePage({super.key});
@override
State<YoutubePage> createState() => _YoutubePageState();
}
class _YoutubePageState extends State<YoutubePage> {
final YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: 'PAOAjOR6K_Q',
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final width = size.width;
final height = size.height;
return Scaffold(
body: Center(
child: OrientationBuilder(
builder: (BuildContext context, Orientation orientation) =>
YoutubePlayerBuilder(
builder: (BuildContext context, Widget player) => SizedBox(
width: orientation == Orientation.landscape ? height : width,
height: orientation == Orientation.landscape ? width : height,
child: player,
),
player: YoutubePlayer(
controller: _controller,
),
onExitFullScreen: () {},
onEnterFullScreen: () {},
),
),
),
);
}
}
<C>
في مقتطف التعليمات البرمجية أعلاه، نستخدم OrientationBuilderالأداة لتحديد اتجاه الشاشة الحالي. داخل منشئها، نعيد YoutubePlayerBuilder، والتي تعيد بدورها SizedBoxأداة. يتم تعديل أبعاد الأداة SizedBoxبناءً على الاتجاه.
في YoutubePlayerBuilder، نقوم بتعريف player، والتي تأخذ مثيلًا من YoutubePlayerالفئة. لدينا أيضًا إمكانية الوصول إلى السمات onEnterFullScreenو onExitFullScreen، والتي يمكن استخدامها لتحريك الإجراءات عندما يدخل اللاعب إلى وضع ملء الشاشة أو يخرج منه. في القسم القادم ، سنناقش onExitFullScreenالسمة بمزيد من التفصيل، وخاصةً لمعالجة مشكلة في شريط التنقل في Android.
تغيير الصورة المصغرة
بالاستمرار في استخدام الكود من القسم السابق، ربما لاحظت أن الصورة المصغرة لا يتم عرضها بشكل صحيح عند إيقاف تشغيل الفيديو مؤقتًا، وخاصة في الوضع الأفقي. لحسن الحظ، يمكننا تخصيص الصورة المصغرة لمعالجة هذه المشكلة.
<C>
import 'package:flutter/material.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
class YoutubePage extends StatefulWidget {
const YoutubePage({super.key});
@override
State<YoutubePage> createState() => _YoutubePageState();
}
class _YoutubePageState extends State<YoutubePage> {
final YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: 'PAOAjOR6K_Q',
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final width = size.width;
final height = size.height;
return Scaffold(
body: Center(
child: OrientationBuilder(
builder: (BuildContext context, Orientation orientation) =>
YoutubePlayerBuilder(
builder: (BuildContext context, Widget player) => SizedBox(
width: orientation == Orientation.landscape ? height : width,
height: orientation == Orientation.landscape ? width : height,
child: player,
),
player: YoutubePlayer(
controller: _controller,
thumbnail: ColoredBox(
color: Colors.black,
child: Image.network(
YoutubePlayer.getThumbnail(
videoId: _controller.metadata.videoId.isEmpty
? _controller.initialVideoId
: _controller.metadata.videoId,
),
fit: BoxFit.contain,
loadingBuilder: (_, child, progress) =>
progress == null ? child : Container(color: Colors.black),
errorBuilder: (context, _, __) => Image.network(
YoutubePlayer.getThumbnail(
videoId: _controller.metadata.videoId.isEmpty
? _controller.initialVideoId
: _controller.metadata.videoId,
webp: false,
),
fit: BoxFit.contain,
loadingBuilder: (_, child, progress) => progress == null
? child
: Container(color: Colors.black),
errorBuilder: (context, _, __) => Container(),
),
),
),
),
),
),
),
);
}
}
<C>
في مقتطف التعليمات البرمجية أعلاه، أضفنا thumbnailالسمة إلى YoutubePlayerالمثيل. thumbnailتقبل السمة عنصر واجهة مستخدم، وفي هذه الحالة، استخدمنا عنصر ColoredBoxواجهة مستخدم بخلفية سوداء. داخل ColoredBoxعنصر واجهة المستخدم، قمنا بتضمين عنصر Image.networkواجهة مستخدم لعرض الصورة المصغرة.
نقوم باسترجاع الصورة المصغرة باستخدام getThumbnailوظيفة الفئة YoutubePlayer. بالإضافة إلى ذلك، أضفنا بديلاً للحالات التي لا يمكن فيها تحميل الصورة المصغرة. في هذه المواقف، يتم عرض حاوية سوداء أثناء جلب الصورة المصغرة.
إصلاح المشكلات المتعلقة بشريط التنقل في Android بعد الخروج من وضع ملء الشاشة