اذهب إلى المحتوى

السؤال

نشر (معدل)

السلام عليكم ورحمه الله وبركاته

انا مبتدا فى تعلم flutter واعمل على برنامج مشغل صوتيات مستخدم باكدج assets_audio_playe مستخدم local files واحتاج مساعدة فى null safety من فضلكم

import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:flutter/material.dart';

class Episode6PlaylistView extends StatefulWidget {
  @override
  _Episode6PlaylistViewState createState() =>
      _Episode6PlaylistViewState();
}

class _Episode6PlaylistViewState extends State<Episode6PlaylistView> {
  final AssetsAudioPlayer audioPlayer = AssetsAudioPlayer();
  double screenHeight = 0;
  double screenWidth = 0;
  final Color mainColor = Color(0xff181c27);
  final Color inactiveColor = Color(0xff5d6169);
  List<Audio> audioList = [
    Audio('assets/1.mp3',
        metas: Metas(
            title: 'ring1',
            artist: 'unknown',
            image: MetasImage.asset('assets/'))),
    Audio('assets/2.mp3',
        metas: Metas(
            title: 'ring2',
            artist: 'unknown',
            image: MetasImage.asset('assets/'))),
    Audio('assets/3.mp3',
        metas: Metas(
            title: 'ring3',
            artist: 'unknown',
            image: MetasImage.asset('assets/'))),
    Audio('assets/4.mp3',
        metas: Metas(
            title: 'ring4',
            artist: 'unknown',
            image: MetasImage.asset('assets/'))),
    Audio('assets/5.mp3',
        metas: Metas(
            title: 'ring5',
            artist: 'unknown',
            image: MetasImage.asset('assets/'))),
    Audio('assets/6.mp3',
        metas: Metas(
            title: 'ring6',
            artist: 'unknown',
            image: MetasImage.asset('assets/'))),
  ];

  @override
  void initState() {
    super.initState();
    setupPlaylist();
  }

  void setupPlaylist() async {
    audioPlayer.open(Playlist(audios: audioList),
        autoStart: false, loopMode: LoopMode.playlist);
  }

  Widget playlistImage() {
    return Container(
      height: screenHeight * 0.25,
      width: screenHeight * 0.25,
      child: ClipRRect(
        borderRadius: BorderRadius.circular(20.0),
        child: Image.asset(
          'assets/background_circular.jpg',
          fit: BoxFit.cover,
        ),
      ),
    );
  }

  Widget playlistTitle() {
    return Text(
      'Chill Playlist',
      style: TextStyle(
          fontFamily: 'Barlow',
          color: Colors.white,
          fontSize: 30,
          fontWeight: FontWeight.bold),
    );
  }

  Widget playButton() {
    return Container(
      width: screenWidth * 0.25,
      child: TextButton(
          onPressed: () => audioPlayer.playlistPlayAtIndex(0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                Icons.play_circle_outline_rounded,
                color: mainColor,
              ),
              SizedBox(width: 5),
              Text(
                'Play',
                style: TextStyle(color: mainColor),
              ),
            ],
          ),
          style: ButtonStyle(
              backgroundColor:
              MaterialStateColor.resolveWith((states) => Colors.white),
              shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                  RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10.0),
                  )))),
    );
  }

  Widget playlist(RealtimePlayingInfos realtimePlayingInfos) {
    return Container(
      height: screenHeight * 0.35,
      alignment: Alignment.bottomLeft,
      child: ListView.builder(
          shrinkWrap: true,
          itemCount: audioList.length,
          itemBuilder: (context, index) {
            return playlistItem(index);
          }),
    );
  }

  Widget playlistItem(int index) {
    return InkWell(
      onTap: () => audioPlayer.playlistPlayAtIndex(index),
      splashColor: Colors.transparent,
      highlightColor: mainColor,
      child: Container(
        height: screenHeight * 0.07,
        child: Padding(
          padding: const EdgeInsets.only(left: 20, right: 20),
          child: Row(
            children: [
              Text(
                '0${index + 1}',
                style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                    fontFamily: 'Barlow'),
              ),
              SizedBox(width: screenWidth * 0.04),
              Expanded(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      audioList[index].metas.title,
                      style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                          fontWeight: FontWeight.bold,
                          fontFamily: 'Barlow'),
                    ),
                    SizedBox(height: screenHeight * 0.005),
                    Text(
                      audioList[index].metas.artist,
                      style: TextStyle(
                          fontSize: 13,
                          color: Color(0xff5d6169),
                          fontFamily: 'Barlow'),
                    ),
                  ],
                ),
              ),
              Icon(
                Icons.menu_rounded,
                color: inactiveColor,
              )
            ],
          ),
        ),
      ),
    );
  }

  Widget bottomPlayContainer(RealtimePlayingInfos realtimePlayingInfos) {
    return Container(
      height: screenHeight * 0.1,
      decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
              topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0))),
      child: Padding(
        padding: const EdgeInsets.only(left: 8.0),
        child: Row(
          children: [
            Container(
              height: screenHeight * 0.08,
              width: screenHeight * 0.08,
              child: ClipRRect(
                borderRadius: BorderRadius.circular(20.0),
                child: Image.asset(
                  realtimePlayingInfos.current.audio.audio.metas.image.path,
                  fit: BoxFit.cover,
                ),
              ),
            ),
            SizedBox(width: screenWidth * 0.03),
            Expanded(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    realtimePlayingInfos.current.audio.audio.metas.title,
                    style: TextStyle(
                        fontSize: 15,
                        color: mainColor,
                        fontWeight: FontWeight.bold,
                        fontFamily: 'Barlow'),
                  ),
                  SizedBox(height: screenHeight * 0.005),
                  Text(
                    realtimePlayingInfos.current.audio.audio.metas.artist,
                    style: TextStyle(
                        fontSize: 13, color: mainColor, fontFamily: 'Barlow'),
                  )
                ],
              ),
            ),
            Icon(
              Icons.favorite_outline_rounded,
              color: mainColor,
            ),
            SizedBox(
              width: screenWidth * 0.03,
            ),
            IconButton(
                icon: Icon(realtimePlayingInfos.isPlaying
                    ? Icons.pause_circle_filled_rounded
                    : Icons.play_circle_fill_rounded),
                iconSize: screenHeight * 0.07,
                splashColor: Colors.transparent,
                highlightColor: Colors.transparent,
                color: mainColor,
                onPressed: () => audioPlayer.playOrPause())
          ],
        ),
      ),
    );
  }

  /// List of placeholder icon buttons used for the bottom navigation bar
  Widget bottomNavigationBar() {
    return BottomNavigationBar(
      type: BottomNavigationBarType.fixed,
      backgroundColor: mainColor,
      selectedItemColor: Colors.white,
      unselectedItemColor: inactiveColor,
      iconSize: screenWidth*0.07,
      items: <BottomNavigationBarItem>[
        BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
        BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
        BottomNavigationBarItem(
            icon: Icon(Icons.library_music_rounded), label: 'Library'),
        BottomNavigationBarItem(
            icon: Icon(Icons.local_fire_department_rounded), label: 'Hotlist')
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    screenHeight = MediaQuery.of(context).size.height;
    screenWidth = MediaQuery.of(context).size.width;

    return Scaffold(
        backgroundColor: mainColor,
        bottomNavigationBar: Container(
          height: screenHeight * 0.1,
          color: Colors.white,
          child: ClipRRect(
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(20.0),
              topRight: Radius.circular(20.0),
            ),
            child: bottomNavigationBar(),
          ),
        ),
        body: audioPlayer.builderRealtimePlayingInfos(
            builder: (context, realtimePlayingInfos) {
              if (realtimePlayingInfos != null) {
                return Column(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: [
                    playlistImage(),
                    SizedBox(height: screenHeight * 0.02),
                    playlistTitle(),
                    SizedBox(height: screenHeight * 0.02),
                    playButton(),
                    SizedBox(height: screenHeight * 0.02),
                    playlist(realtimePlayingInfos),
                    bottomPlayContainer(realtimePlayingInfos)
                  ],
                );
              } else {
                return Column();
              }
            }));
  }
}

 

1.png

2.png

3.png

تم التعديل في بواسطة محمد صلاح28
تم اضافة صور

Recommended Posts

  • 1
نشر

أخطاء null safety ليس لها علاقة بالحزمة أو المكتبة التي تستخدمها، بل تتعلق بلغة Dart نفسها. ولذلك يجب عليك فهم آلية عملها لتستطيع استخدامها في الشيفرة البرمجية لديك وتجنب هذه الأخطاء مع المكتبات الخارجية.

Null Safety أو اختصاراً NNBD هي آلية تعتمدها Dart بدءً من الإصدار الثاني ويقوم بها المترجم للتأكد من صحة نمط المتغيّرات أثناء كتابة الكود البرمجي لتجنّب الأخطاء مستقبلاً أثناء التشغيل أو runtime مما يسمح بكتابة شيفرة برمجية عالية الأداء وخالية من الأخطاء.

باختصار إن وضع الأمان في null safety يعني أن المتغيرات لا يمكن أن تحتوي على قيم فارغة، ففي حال أراد المطوّر تعريف متغيّر على أنه قيمة فارغة أو null، يجب عليه ذكر ذلك صراحةً أثناء تعريف هذا المتغيّر. فعلى سبيل المثال، بمجرّد تعريف نمط لمتغيّر على أنه int، أي سيحوي حصراً قيمة عددية من نمط int ولا يمكن أن تكون هذه القيمة (null):

void main() {
  int marks;
 
  marks = null; //سيسبب بظهور رسالة خطأ أثناء الترجمة
}

وهنا ستظهر لك رسالة الخطأ نفسها الظاهرة في الصورة، وهي أنه لا يمكن للمتغيّر marks أن يحوي القيمة null لأنه من نمط int.

في حال أردنا إضافة القيمة null إلى هذا المتغيّر أثناء التعريف يجب استخدام الإشارة ? فيصبح من النمط int?

int? marks = 36;  // تتيح الإشارة إمكانية اسناد القيمة الفارغة لهذا المتغيّر
marks = null; 

وهنا سيتم اسناد القيمة null إلى هذا المتغيّر دون حدوث خطأ أثناء الترجمة.

وأيضاً في حالتك وعند وجود خصائص فرعية يمكنك إضافة العلامة ? إلى هذه الخصائص:

final value = person?.address?.street?.value;

وبنفس الطريقة أثناء استخدام هذا المتغيّر فيما بعد ضمن الشيفرة البرمجية، في حال كان يقبل القيمة null، يجب عليك إحاطة أماكن استخدام هذا المتغيّر بجمل شرطية، مثل شرط if:

if(marks != null){
....
}

وإلا ستظهر لك الرسالة الظاهرة في الصورة: "The property audio can't be unconditionally accessed" والتي تعني أنه لا يمكنك استخدام متغيّر ما بشكل مباشر ضمن الشيفرة البرمجية لأنه يقبل القيمة null، وبالتالي يجب عليك استخدام شرط ما للتحقق من أنه لا يساوي null.

ويمكنك قراءة المزيد من المعلومات والأمثلة من قسم Null Safety في التوثيق الرسمي لـ Dart.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...