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

Flutter Dev

الأعضاء
  • المساهمات

    787
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    2

أجوبة بواسطة Flutter Dev

  1. تحيه طيبه للجميع

    لدي استفسار لو تكرمتم

    الان انا ارغب بعمل تسجيل دخول للمستخدمين من خلال خدمة جوجل في فلاتر ويب

    ولكني وجدت شرح استعمال خدمة جوجل بدون الفايربيز 

    حقيقه لم افهم ما هيا الطريقه الافضل هل مع استعمال الفاير بيز او بدونه؟ ولو لم استعمل فايربيز ماذا سوف ينقص

    في الخدمه او ما هيا فائدة الفاير بيز في هذا الحاله حتى حتى تتوضح الصوره؟

     

    لم افهم موضع الفايربيز في هذا الحاله دام احنا قادرين على استعمال خدمة جوجل بدونها !

     

     

     

  2. بتاريخ منذ ساعة مضت قال Ahmed Sadek:

    نص الخطأ يوضح بأنك عند إنشاءك لمفاتيح token الخاصة ب google auth لم تقم بإضافة urls الخاصة ب test مثل localhost و 127.0.0.1 . لذلك يرجى الذهاب إلى https://console.developers.google.com/ ثم اختيار تطبيقك وقم بإضافة url التي تعمل عليها

     

    اهلا بك اخي الكريم

    طيب اخوي بعد نشر الموقع بيكون فيه url  حقيقي 

    هل اقوم فقط باضافته بشكل عام مثلا 

    www.test.com

    او انا محتاج احدد اسم الصفحة من ضمن url?

  3. تحيه طيبه للجميع

    احاول عمل تسجيل دخول جوجل للمسخدمين في flutter web 

    ولكن كل ما احاول الدخول يجيني المسج التالي:

    Error signing in PlatformException(idpiframe_initialization_failed, Not a valid origin for the client: http://localhost:60789 has not been registered for client ID *********. Please go to https://console.developers.google.com/ and register this origin for your project's client ID., https://developers.google.com/identity/sign-in/web/reference#error_codes, null)

    لم افهم صراحه ما يجب ان اقوم به هو يطلب مني تسجيل ولكن تسجيل ماذا ؟

    للعلم يمكن تشغيل الكود من خلال الكود التالي:

    flutter run -d chrome --web-hostname localhost --web-port 5000

    ولكن بعد ان يتم نشر الموقع لا يمكنني استعمل هذا الكود ما هو الحل ؟ وما هو المقصود من الخطاء اعلاه كيف يمكن حله؟

     

    شكرا لكم

  4. بتاريخ 3 دقائق مضت قال Ahmed Sadek:

    أظن أن المشكلة في الدالة onPageViewChange بحيث يتم اسناد قيمة بدون قيمة ابتدائية _page الى page من نوع int 

    قم بهذا التحقق 

    
    if (this.isNaN || this.isInfinite){
       // القيمة الإفتراضية
    }else{
      //الكود الخاص بك
    }

     

    كل الود لك اخي الكريم شاكر لك

    • أعجبني 1
  5. تحيه طيبه للجميع

    قمت بعمل تطبيق لعرض قائمة من الصور وقمت بإضافة مؤشر الصور الى هذا القائمة الحزمة التأليه:

    smooth_page_indicator 1.0.0+2

    ولكني أوجه مشكلة ورسالة خطاء كالتالي:

    Unsupported operation: Infinity or NaN toInt 

    صفحة الكود كامله كالتالي:

    class _WidgetImageState extends State<WidgetImage> {
      List<ImageTopicModel> _ListData = [];
      List<ImageTopicModel> _ListDataDisplay = [];
      @override
      void initState() {
        Api().then((value) {
          if (this.mounted) {
            setState(() {
              _ListData.addAll(value);
              _ListDataDisplay = _ListData;
            });
          }
        });
        super.initState();
      }
      
      PageController _pageController = PageController();
      int page = 0;
      void onPageViewChange(int _page) {
        page = _page;
        //  setState(() {});
      }
    
      @override
      Widget build(BuildContext context) {
        return  Container(
          width: double.infinity,
          height: 400,
          child: Stack(children: <Widget>[
            Stack(
              children: <Widget>[
                Container(
                  width: double.infinity,
                  height: 400,
                  child: PageView.builder(
                      physics: BouncingScrollPhysics(),
                      controller: _pageController,
                      onPageChanged: onPageViewChange,
                      itemCount: _ListDataDisplay.length,
                      itemBuilder: (BuildContext context, int index) {
                        return Container(
                          child: Column(children: <Widget>[
                            InkWell(
                                child: CachedNetworkImage(
                                  imageUrl:
                                  "${_ListDataDisplay[index].image}",
                                  width: double.infinity,
                                  height: 400,
                                  fit: BoxFit.cover,
                                  errorWidget:
                                      (context, url, error) =>
                                      Icon(Icons.error),
                                ),
                                onTap: () {
                                  Navigator.push(context,
                                      MaterialPageRoute(
                                          builder: (context) {
                                            return ShowImageOfAd(
                                                "${_ListDataDisplay[index].image}");
                                          }));
                                }),
                          ]),
                        );
                      }),
                ),
                Container(
                    child: Align(
                      alignment: Alignment.bottomCenter,
                      child: Container(
                        height: 40,
                        decoration: BoxDecoration(
                            gradient: LinearGradient(
                                begin: Alignment.topCenter,
                                end: Alignment.bottomCenter,
                                colors: [
                                  Colors.black.withOpacity(0.0),
                                  Colors.black.withOpacity(0.5)
                                ])),
                        child: Align(
                          alignment: Alignment.center,
                          child: SmoothPageIndicator(
    
                              controller: _pageController, // PageController
                              count: _ListDataDisplay.length,
                              axisDirection: Axis.horizontal,
                              effect: WormEffect(
                                dotWidth: 9.0,
                                dotHeight: 9.0,
                                dotColor: Colors.black26,
                                activeDotColor: Colors.white,
                              ),
                              onDotClicked: (index) {}),
                        ),
                      ),
                    )),
              ],
            ),
          ]),
        );
      }
    }

     

    فيه احد يعرف حل لهذا المشكلة وما هو سببها؟ حقيقه انني قمت بالبحث كثيرا ولكني لم اجد حل لها

     

    ======== Exception caught by rendering library =====================================================
    The following UnsupportedError was thrown during paint():
    Unsupported operation: Infinity or NaN toInt
    
    The relevant error-causing widget was: 
      SmoothPageIndicator SmoothPageIndicator:file:///C:/Users/**********/widgetImage.dart:96:30
    When the exception was thrown, this was the stack: 
    #0      double.toInt (dart:core-patch/double.dart)
    #1      WormPainter.paint (package:smooth_page_indicator/src/painters/worm_painter.dart:21:40)
    #2      RenderCustomPaint._paintWithPainter (package:flutter/src/rendering/custom_paint.dart:571:13)
    #3      RenderCustomPaint.paint (package:flutter/src/rendering/custom_paint.dart:613:7)
    #4      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2796:7)
    #5      PaintingContext.paintChild (package:flutter/src/rendering/object.dart:239:13)
    #6      RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:144:15)
    #7      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2796:7)

     

  6. تحيه طيبه للجميع

    قمت بعمل صفحة لعمل تصفية للبيانات لعرضها للمستخدم بعد التصفية الكود يعمل ولكن المشكلة استطيع فقط الان عمل تصفية او فلترة لمتغير واحد فقط شاهد الكود التالي:

    
    import 'dart:convert';
    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    
    
    Future main() async {runApp(testpage(),);
    }
    
    class testpage extends StatefulWidget {
    
      @override
      _testpageState createState() => _testpageState();
    }
    
    class _testpageState extends State<testpage> {
    
      @override
      void initState() {
        getData();
        super.initState();
      }
    
      List listsearch = [];
      List ? datas;
    
      Future<String> getData() async {
        var response = await http.get(
            Uri.parse("https://jsonplaceholder.typicode.com/comments"),
            headers: {
              "Accept": "application/json"
            }
        );
        this.setState(() {
          datas = json.decode(response.body);
        });
        for (int i = 0; i < datas!.length; i++) {
          listsearch.add(datas![i]['name'].toString()+ ':' + datas![i]['email'].toString() );
          print(listsearch.toString());
    
        }
    
        return "Success!";
      }
      @override
      Widget build(BuildContext context) {
        final _filteredList =
            listsearch.where((jsonList) => jsonList.startsWith('id')
    
            ).toList();
    
        return MaterialApp(
          home: Scaffold(
            body: ListView(children: [
              ListView.builder(
                  shrinkWrap: true,
                  itemCount: _filteredList.length,
                  itemBuilder: (context, i) {
                    return ListTile(
                      leading: Icon(Icons.search),
                      title: Text(_filteredList[i].toString()),
    
                    );
                  })
            ]),
          ),
        );
      }
    }

    في الصفحة أعلاه انا اجلب بيانات من الشبكة بتحديد متغير الاسم والايميل

    اما في السطر التالي انا أقوم بتصفية متغير الاسم:

      final _filteredList =
            listsearch.where((jsonList) => jsonList.startsWith('id') 
    
            ).toList();

    السؤال الان كيف استطيع تصفية او فلترة الايميل أيضا بجانب الاسم؟

    على سبيل المثال خانة الاسم لو قمت بكتابة الاسم احمد سوف احصل على عشر مستخدمين باسم احمد ولكن كل احمد لديه ايميل مختلف اذن اول خطوه قمت بتصفية الاسم احمد ثم قمت بتصفية الايميل أيضا للمستخدم احمد لتقيص المستخدمين الذين يمتلكون الاسم احمد 

     

    قمت بمحاولة التالية ولكن الكود لا يعمل بشكل هذا:

        final _filteredList =
            listsearch.where((jsonList) => jsonList.startsWith('id') && jsonList.startsWith('Eliseo')
            ).toList();

    كيف يمكن فعل ذلك هل يمكن احد فكره لحل هذا المشكلة؟

    شكرا لكم

    • أعجبني 1
  7. بتاريخ 1 ساعة قال Ahmed Sadek:

    يرجى شرح الخطأ جيدا ، مثلا أين بالضبط يظهر الخطأ ، وأرجو أخذ لقطة للشاشة 

    مرحبا اخي الكريم

    هذا خطاء يظهر بسبب الاتصال مع الاستضافه لا يوجد خطاء كتابي في الكود الكود عادي شغال 100%

    ولكن ك مثال عادي اجي اعمل اعادة تشغيل او اتنقل من خلال التطبيق وفجاه يفصل الانترنت عنه هذا الذي فهمته ولو فصل تظهر هذا الرساله

    المشكله حتى لو قمت باعادة تشغيل التطبيق تستمر في الظهور فتره من الوقت قبل ان يعود يعمل طبيعي

     

     

    ولكن انا حاب اعرف الخطاء هذا الى ماذا يرمز حتى استطيع معرفة المشكله

     

    ايضا لو كنت اقوم باكثر من اتصال مع السيرفر من صفحه واحده هل توجد طريقه لدمج هذا طلبات الاتصالا مع السيرفر؟ وهو افضل الدمج او القيام باكثر من طلب في نفس الوقت؟ 

     

    ك مثال في صفحة main توجد اكثر من ميثود تعمل مع دخول المستخدم لصفحه مثل التحقق من الهوية + جلب المواضيع+ التحقق من الدوله. .الخ

  8. تحيه طيبه للجميع

    انا استعمل مكتبة http من مكاتب فلاتر

    ويجئني كثير الفترة الأخيرة ال error  هذا :

    [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Connection reset by peer
    E/flutter ( 5594): #0      IOClient.send (package:http/src/io_client.dart:88:7)

    ما هو المقصود به وما هو الحل له؟

    مع العلم اني استعمل استضافة مدفوعة وقاعدة بيانات MySQL

  9. بتاريخ 2 دقائق مضت قال Ahmed Sadek:

    هذا هو جوهر استعمال state management وأنصحك باستعمال getX تمكنك من :

    • > إدارة المسار: لإنشاء أدوات مثل Snackbar و Bottomsheets ومربعات الحوار وما إلى ذلك. بعد ذلك ، في هذه المرحلة ، يمكننا إشراك GetX فيه لأن GetX يمكنه تجميع هذه الأدوات دون استخدام السياق.
    • > أداء عالٍ: تستخدم GetX أصولًا أقل كما هو متوقع. لا تعتمد على Streams أو ChangeNotifier. عند تساوي كل الأشياء ، فإنه يستخدم GetValue و GetStream المنخفضان للخمول لزيادة تطوير التنفيذ.
    • > كود أقل: قد تكون سئمت من تنفيذ نموذج الكتلة في نمط الكتلة وإهدار طاقة التطوير على أكواد غير ضرورية. الوقت هو المال ، أليس كذلك؟ في GetX ، لن تؤلف أي نموذج معياري. يمكنك إنجاز نفس الشيء بشكل أسرع بكثير ، باستخدام كود أقل في GetX. لا تكلف نفسك عناء إنشاء فصول للولاية والحدث ، لأن هذه النماذج المعيارية غير موجودة في GetX.
    • > لا يوجد توليد للكود: هناك سبب مقنع للحاجة إلى استخدام مولدات الكود بأي وسيلة. لذلك لن يضيع وقتك المهم في التطوير أكثر على تشغيل مولدات الأكواد (build_runner) كلما قمت بتغيير شفرتك.
    • > لا توجد عمليات إعادة بناء غير ضرورية: التعديلات غير المرغوب فيها هي مشكلة تخص مديري الدولة استنادًا إلى ChangeNotifier. عندما تقوم بإدخال تحسين في فئة ChangeNotifier الخاصة بك ، يتم إعادة بناء جميع عناصر واجهة المستخدم التي تعتمد على فئة ChangeNotifier هذه. قد تكون بعض عمليات إعادة البناء غير ضرورية ومكلفة. قد يقلل من أداء التطبيق أيضًا. لا تحتاج إلى التأكيد على هذا في GetX لأنه لا يستخدم ChangeNotifier بأي وسيلة.

    للمزيد تفحص هذا الرابط الرسمي https://pub.dev/packages/get

     

    اهلا بك اخي الكريم

    الا توجد طريقة مختلفة بدون استعمل هذا المكتبة اخي؟

  10. تحيه طيبه للجميع

    قمت بعمل تطبيق يحتوي على صفحتين وكل صفحة لديها function  بإضافة بيانات في قاعدة البيانات 

    الان مشكلتي انني ارغب بتحكم ب function  في الصفحة الثانية من الصفحة الأولى بحيث أقوم بالاتصال بها وجعلها تعمل 

    كيف يمكن فعل ذلك ؟

    كود مثال على ذلك: هذا الصفحة الاولى والتي ارغب ممن خلالها ان اتصل مع function  في الصفحة الثانية

    void main() {
      runApp(MainPage());
    }
    class MainPage extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MainPage> {
      TextEditingController NameController = TextEditingController();
      Future AddNewData() async {
        final response = await http.post(Uri.parse("**********", ),
            body: {
              "Name": NameController.text,
            }
        );
        if (response.statusCode == 200) {
        } else {
          throw Exception('Send Failed');
        }
      }
    
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
              body: Column(children: [
                TextFormField(
                  controller: NameController,
                  decoration: InputDecoration(
                      border: OutlineInputBorder(),
            
                     ),
    
                ),
    
                ElevatedButton(
                  child: Text('add new data'),
                  onPressed: () {
                    AddNewData();
                  },
                ),
              ],)
          ),
        );
      }
    }

     

     

    الصفحة الثانية الصفحة المستهدفة:

    class secondpage extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<secondpage> {
    
      TextEditingController ColorController = TextEditingController();
      Future AddNewColor() async {
        final response = await http.post(Uri.parse("**********", ),
            body: {
              "Color": ColorController.text,
            }
        );
        if (response.statusCode == 200) {
        } else {
          throw Exception('Send Failed');
        }
      }
    
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Column(children: [
              TextFormField(
                controller: ColorController,
                decoration: InputDecoration(
                    border: OutlineInputBorder(),
                 ),
    
              ),
    
              ElevatedButton(
                child: Text('add new color'),
                onPressed: () {
                  AddNewColor();
                },
              ),
            ],)
          ),
        );
      }
    }

     

     

    الان لتوضيح الفكرة اكثر احتاج ان اتصل ب AddNewColor في الزر الموجود في صفحة main page  او الصفحة الأولى مثل التالي:

     ElevatedButton(
                  child: Text('add new data'),
                  onPressed: () {
                    AddNewData();
          AddNewColor();
    
                  },
                ),

    كيف يمكن فعل ذلك؟ احد عنده فكره؟

    • أعجبني 1
  11. بتاريخ 2 ساعات قال Ahmed Sadek:

    للأسف لا يمكن ذلك إلا بحزمة أو serive تقدمها أحد الشركات مثل google recaptcha ، وأنا أنصحك ب f_grecaptcha

    يسمح هذا المكون الإضافي flutter البسيط باستخدام SafetyNet API على أجهزة Android للتحقق من أن المستخدم إنسان.

    • كيفية إستعمالها في تطبيقك 
    1. قم بتضمين المكون الإضافي في تبعيات مشروعك عن طريق تضمينه في القسم ذي الصلة من pubspec.yaml الخاص بك:
      
      dependencies:
        f_grecaptcha: ^1.0.0

       

    2. بعد ذلك ، ستحتاج إلى تسجيل تطبيقك في وحدة تحكم مسؤول reCAPTCHA. انتقل إلى https://www.google.com/recaptcha/admin#list وقم بالتسجيل عن طريق ملء النموذج. تأكد من تحديد "reCAPTCHA-Android" كنوع.

    3. بعد تسجيل تطبيقك في reCAPTCHA API ، يمكنك استدعاء الطريقة التالية في أي مكان في رمز dart الخاص بك ، والأكثر شيوعًا بعد الضغط على الزر. استبدل SITE_KEY بمفتاح الموقع الذي تعرضه واجهة المسؤول بعد تسجيل تطبيقك.

      
       FGrecaptcha.verifyWithRecaptcha(SITE_KEY).then((result) {
          // يمكنك إرسال رمز النتيجة ، مع بعض حقول النموذج ، إلى ملف
          // reCAPTCHA API for servers, see https://developers.google.com/recaptcha/docs/verify
          }, onError: (e, s) {
      	// لا يعني الخطأ أن المستخدم ليس بشريًا. أخطاء
           // يمكن أن يحدث أيضًا عندما يكون مفتاح الموقع غير صالح أو لا يتطابق مع
           // التطبيق ، عندما يكون الجهاز غير مدعوم أو عندما تكون الشبكة
           // يحدث خطأ.
           // يجب عليك إبلاغ المستخدم بالأخطاء ، وشرح سبب عدم تمكنه من ذلك
           // تخطي خطوة reCAPTCHA عندما يكون FGrecaptcha.isAvailable خاطئًا.
          print("لم نتمكن من التحقق:\n $e at $s");
          }
      );

       

    اهلا اخي الكريم

    شاكر لك ردك عزيزي

    يعني استعمال slide_to_confirm  لا يعمل او ما يفيد؟

  12. تحيه طيبه للجميع 

    ما هيا الأنواع التي يمكن استعمالها لتحقق من شخصية صاحب الحساب او من يحاول التسجيل في تطبيقي او ما يسمى (Human verification) ما هيا الطرق المتوفرة للعمل مع flutter?

    وهل طريقة slide_to_confirm فعالة لمثل هذا الامر ؟

    ياليت لو فيه طريقة بسيطة بدون استعمال مكتبة 

    • أعجبني 1
  13. بتاريخ 1 ساعة قال Ahmed Sadek:

    بصراحة هناك حزمة ممتازة لعمل search إحترافي مثل whatsapp search وغيرها .

    إسم الحزمة wp_search_bar ، وهذه طريقة عملها :

    1. تحميل الحزمة 
      
      $ dart pub add wp_search_bar

       تأكد من وجودها في dependencies 

      
      dependencies:
        wp_search_bar: ^0.0.5

       

    2.  تحديد البيانات التي تريد إظهارها في عرض القائمة 

      
      List<Map<String, String>> data = [
          {'name': "Mohammad", 'message': "message from mhammad"},
          {'name': "Kamel", 'message': "message from kamel"},
          {'name': "Nadine", 'message': "how are you ?"},
          {'name': "Joseph", 'message': "hello...!"},
          {'name': "71966691", 'message': "Hi"},
          {'name': "03405609", 'message': "hiiii...."},
          {'name': "Mohammad", 'message': "message from mhammad"},
          {'name': "Kamel", 'message': "message from kamel"},
          {'name': "Nadine", 'message': "how are you ?"},
          {'name': "Joseph", 'message': "hello...!"},
          {'name': "71966691", 'message': "Hi"},
          {'name': "03405609", 'message': "hiiii...."},
        ];

       

    3.  تحديد الأزرار التي يجب استخدامها في شريط البحث.

      
      var buttonFilters = {
                'name': {
                  'name': 'name',
                  'selected': false,
                  'title': 'Name',
                  'operation': 'CONTAINS',
                  'icon': Icons.supervised_user_circle_rounded,
                },
                'message': {
                  'name': 'message',
                  'selected': false,
                  'title': 'Message',
                  'operation': 'CONTAINS',
                  'icon': Icons.message,
                },
                'date': {
                  'name': 'Date',
                  'selected': false,
                  'title': 'Date',
                  'operation': 'CONTAINS',
                  'icon': Icons.date_range,
                },
                'other': {
                  'name': 'other',
                  'selected': false,
                  'title': 'Other',
                  'operation': 'CONTAINS',
                  'icon': Icons.more,
                },
              };

       

    4.  بناء شريط البحث 

      
      @override
        Widget build(BuildContext context) {
          return MaterialApp(
            home: WPSearchBar(
              listOfFilters: buttonFilters,
              materialDesign: const {
                'title': {'text': 'hsoub'},
              },
              onSearch: (filter, value, operation) {
              },
              body: Container(
                decoration: const BoxDecoration(color: Color(0xff121b22)),
                child: ListView.builder(
                    itemCount: filteredData.length,
                    itemBuilder: (context, index) {
                      var item = filteredData[index];
                      return ListTile(
                        title: Text(
                          item['name'].toString(),
                          style: const TextStyle(
                              color: Colors.white, fontWeight: FontWeight.bold),
                        ),
                      );
                    }),
                ),
            ),
          );
        }
      }

       

     

    اهلا اخي الكريم 

    شاكر لك الافاده اخوي ولكن افضل تجنب الحزم قدر الامكان في مشروعي تعرف مشاكل توافق وتحديثات وغيرها 

     

    الا تملك فكره عن سبب المشكله الذي تحدث لدي؟

  14. تحيه طيبه للجميع

    قمت بعمل برنامج صغير لعرض قائمة من البيانات ومن ثم يمكنني البحث او تصفية هذا البيانات من خلال البحث في هذا القائمة ولكن واجهتني مشكلة الكود كامل يعمل ولكن توجد مشكلة واحده. المشكلة الان عند الضغط على حقل TextField يتم اعادة تحميل القائمة من جديد ثم اخراج الموشر او المستخدم من TextField .

    شاهد الصورة التأليه لفهم المشكلة اكثر:

    Animation.thumb.gif.dd232c9064a91c93d0d6a55d06970b18.gif

     

    كما تشاهد أعلاه لا يمكنني الكتابة في TextFiled

    قمت بأعداد التطبيق من خلال صفحتين:

    الصفحة الأولى وهيا التي أقوم بأرسال القائمة من خلالها الى الصفحة الثانية لعرضها من FutureBuilder :

    class firstPage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<firstPage> {
    
     
      @override
      void initState() {
    
     
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            backgroundColor: kBackground,
            body: Center(
                child: Column(
                  children: [
                    Expanded(
                      child: FutureBuilder<List<AllProductModel>>(
                        future: fetchYourProduct(Uids, NameUserContry),
                        builder: (context, snapshot) {
                          final ListDataDisplay  = snapshot.data;
    
                          switch (snapshot.connectionState) {
                            case ConnectionState.waiting:
                              return Center(child: CircularProgressIndicator());
                            default:
                              if (snapshot.hasError) {
                                return Center(
                                    child: Text('Some error occurred!'));
                              } else {
                                return  UserPage(ListDataDisplay:ListDataDisplay);
                              }
                          }
                        },
                      ),
    
    
                    )
                  ],
                ))
    
            );
      }
    
    }
    

     

    اما الصفحة الثانية وهيا التي أقوم بعرض البيانات من خلالها بالإضافة الى انها تتضمن شريط البحث:

    class UserPage extends StatefulWidget {
      final  ListDataDisplay;
      UserPage({Key? key, required this.ListDataDisplay}) : super(key: key);
      @override
      State<UserPage> createState() => _UserPageState();
    }
    
    class _UserPageState extends State<UserPage> {
    
      TextEditingController editingController = TextEditingController();
      Widget appBarTitle =  Text('');
      Icon actionIcon =  Icon(
        Icons.search,
        color: CustomColors.firebaseNavy,
      );
    
      String searchString = "";
      TextEditingController searchController = TextEditingController();
    
    
      @override
      Widget build(BuildContext context) =>
          Scaffold(
              appBar:  AppBar(
                  centerTitle: true,
                  title:appBarTitle,
                  backgroundColor: CustomColors.firebaseGrey,
                  elevation: 1.5,
                  actions: <Widget>[
                    IconButton(onPressed: (){
                      setState(() {
                        if ( this.actionIcon.icon == Icons.search){
                          this.actionIcon =  Icon(Icons.close);
                          this.appBarTitle =  TextField(
                            onChanged: (value) {
                              setState((){
                                searchString = value;
                              });
    
                            },
                            controller: searchController,
                            style:  TextStyle(
                              color: Colors.black,
    
                            ),
                            decoration:  InputDecoration(
                                labelText: 'Name',
                                enabledBorder: UnderlineInputBorder(
                                  borderSide: BorderSide(color: Colors.black),
                                ),
    
                            ),
                          );
                        }
                        else {
                          this.actionIcon =  Icon(Icons.search);
                          this.appBarTitle =  Text("List");
                          searchController.clear();
                          searchString='';
                        }
    
                      }
                      );
    
                    },icon: actionIcon,
                    )
    
    
    
                    ,]
              ),
    
    
    
              body:
    
              ListView.builder(
    
                  physics: ScrollPhysics(),
                  scrollDirection: Axis.vertical,
                  shrinkWrap: true,
                  itemCount: widget.ListDataDisplay.length,
    
                  itemBuilder: (context, index) {
                    return
                      "${widget.ListDataDisplay[index]
                          .name}" ':' "${widget.ListDataDisplay[index].coponId}"
                          .contains(searchString) ?
                      Card(
                        elevation: 1.5,
                        child: Container(
                          padding: EdgeInsets.all(6),
                          child: Row(
                            children: <Widget>[
                           Text(widget.ListDataDisplay[index].name)
    
                            ],
                          ),
                        ),
                      ) : Container();
    
                  }
              )
    
          );
    }

     

    كيف يمكن حل هذا المشكلة؟ لتمكين المستخدم من إمكانية البحث

  15. بتاريخ منذ ساعة مضت قال علي محسن:

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

    
    	// imagesString لنفرض أن النص الذي يحتوي على روابط الصور لديك هو
    	let array= imagesString.split(",")
    	الأن كل عنصر من عناصر المصفوفة أعلاه هو رابط صورة. حيث يمكنك المرور على جميع العناصر في حلقة تكرار وتكوين عنصر قابل للضغط.
    	array.map( (img, index ) =>{
    	    ...
    	    //هي رابط صورة img هنا كل
    	    // <a href=`${img}` >...</a>
    	}
    	// يعتمد الأمر على ماذا تستعمل في الواجهة الأمامية لذا وضعنا حلاً عاماً لتاخذ منه الفكرة
    	

    اهلا اخي الكريم

    بالنسبة الى الصلاحيات لا توجد مشكله في ذلك 

    المشكله في تقسيم الصور هما 3 روابط الان ولكن بسبب انهم متصلين ببعض لا يمكن الانتقال لهم

    بالنسبة الى التقسيم نعم هو ما ابحث عنه ولكني لم اجد حل له 

    بالنسبة الى انا استعمل php and MySQL

    • أعجبني 1
  16. تحيه طيبه للجميع 

    قمت باستعمال GROUP_CONCAT  لدمج البيانات المتشابها بين جدولين مع استعمال LEFT JOIN لتوضيح الفكرة مرفق تصميم الجداول قبل وبعد كالتالي :

    قبل استعمال GROUP_CONCAT:

    Output:
    +-----------+--------+----------+-----------+
    |id| name   | Cmpany | POSTID   |ImageTopic |
    |1 | John   |  Js    |  1       |1png       |
    |1 | John   |  Js    |  1       |2png       |
    |1 | John   |  Js    |  1       |3png       |
    |1 | John   |  Js    |  1       |4png       |
    +-----------+--------+----------+-----------+

     

    بعد استعمال GROUP_CONCAT

    Output:
    +---+------+-----------+--------+------------------------+
    |id | name |    Cmpany | POSTID |   ImageTopic           |
    |1  | John |      Js   |  1     |   1png,2png,3png,4png  |
    +---+------+-----------+--------+------------------------+

     

    مشكلتي الان مع عمود (Image Topic) قمت بالحصول على الأربع صور المرتبطة بنفس الشخص ولكن لا يمكن قراءة الصور بشكل هذا او حتى الضغط عليهم 

    احصل عليهم كالتالي:

    ImageTopic: "https://png.pngtree.com/element_our/20200703/ourlarge/pngtree-butterfly-purple-red-wings-ink-transparent-png-bright-image_2300442.jpg,https://www.picng.com/upload/butterfly/png_butterfly_61701.png,https://www.picng.com/upload/butterfly/png_butterfly_61701.pnghttps://www.picng.com/upload/butterfly/png_butterfly_61700.png"

     

    أيضا صوره لتوضيح المشكلة اضافيه 

    GgOs2.thumb.png.035b4fd33e9d64c6221d2d64cb87478a.png

     

    ولو حاولت الضغط عليهم يتم الضغط بشكل مدموج واحصل على الخطاء التالي:

    This XML file does not appear to have any style information associated with it. The document tree is shown below.
    <Error>
    <Code>AccessDenied</Code>
    <Message>Access Denied</Message>
    <RequestId>JF8C24VHE7Z9NKAC</RequestId>
    <HostId>+yKClkshmm8kCqYydoRsaPDwjkkM+anF0vQI6nt0eTY6TvCuQ5QDv7hfq//eTxUJ9ApNMNWpPfc=</HostId>
    </Error>

     

    الكود المستعمل كالتالي:

    <?php
    require_once 'con.php';
    
    $id=$_GET['id'];
    
    
    $sql= "SELECT * FROM topics
    
    LEFT JOIN (SELECT POSTID, GROUP_CONCAT(DISTINCT ImageTopic  ) ImageTopic 
    FROM ImagePost GROUP BY POSTID
    ) ImageTopic ON topics.id = ImageTopic.POSTID
    
    
    where topics.id=? "
    ;
    
    $stmt = $con->prepare($sql); 
    
    $stmt->bind_param("s",$id);
    
    $stmt->execute();
    
    $result = $stmt->get_result();
    
    if ($result->num_rows >0) {
     
     
         while($row[] = $result->fetch_assoc()) {
         
         $item = $row;
         
         $json = json_encode($item, JSON_NUMERIC_CHECK);
         
         }
     
    } else {
    
        $json = json_encode(["result" => "No Data Foun"]);
    }
     echo $json;
    
     
    $con->close();
     
    
    
    
    ?>
    
    
    

     

     

    كيف يمكن حل هذا المشكلة؟ انا لا استطيع استعمال الصور بشكل هذا / احتاج لاحقا الى استعملهم في تطبيقي

  17. بتاريخ 2 دقائق مضت قال Ahmed Sadek:

    نعم  أنت بحاجة إلى مصدر بيانات لا يهم هل api او sqlite ..... على سبيل المثال ، قد يكون مصدر البيانات الخاص بك عبارة عن قائمة من الرسائل أو نتائج البحث أو المنتجات في متجر. في معظم الأحيان ، تأتي هذه البيانات من الإنترنت أو من قاعدة بيانات. 

     

     

    كل الشكر لك اخي الكريم 

    اذن لا توجد مشكلة لو لم استعمل نظام lazy loading  ؟

    • أعجبني 1
  18. بتاريخ 1 دقيقة مضت قال Ahmed Sadek:

    نعم ، Listview.builder في الفلاتر معمولة من أجل البيانات الكبيرة فهي تعمل على مبدأ العرض المناسب في كل مرة ، معناه أنو مثلا عملت إستعلام للبيانات حجمها 10000 أو أكثر فهنا Listview.builder تقوم ببناء عرض البيانات 50 الأولى لما المستخدم يعمل scroll مثلا أو اي event تختفي 50 البيانات الأولى ويتم بناء 50 البيانات الثانية وهكذا ..

    الفرق الرئيسي بين ListView و ListView.builder

    يتطلب مُنشئ ListView منا إنشاء جميع العناصر مرة واحدة. يعد هذا أمرًا جيدًا عندما تكون عناصر القائمة أقل وستظهر جميعها على الشاشة ، ولكن إذا لم يكن الأمر كذلك بالنسبة لعناصر القائمة الطويلة ، فهذا ليس ممارسة جيدة.

    بينما

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

    اهلا بك اخي الكريم

    شاكر لك ردك عزيزي

    طيب اخوي هذا بالنسبة اذا كانت البيانات تأتي من خلال api 

    ولكن لو كانت من خلال SharedPreferences على سبيل المثال هل يتم معاملتها أيضا مثل بيانات api?

  19. بتاريخ 2 دقائق مضت قال علي محسن:

    للتعامل مع كمية كبيرة من البيانات لا يمكن يحميلها دفعة واحدة من قاعدة البيانات لأن ذلك يتسبب بمشكلة في الأداء على طرف الواجهة الخلفية backend وكذلك أستهلاك الواجهة الأمامية frontend  للذاكرة وربما حصول crash. لحل هذه المشكلة تستطيع إستعمال مفهوم pagination أي تقسيم البيانات الى أجزاء محسوبة في الbackend يمكن إسقاطها الى صفحات في frontend تعرض جزء معين في كل مرة يغير فيها المستخدم رقم الصفحة وتتم البرمجة لهذه الخاصية في كلا الواجهتين لتعمل بتناغم.

    يمكنك أيضاً إستعمال شيء مشابه يدعى lazy loading وهي خاصية من النوع asynchronous أي لا تزامنية تتم عن طريق ajax وهي شائعة الإستخدام في تطبيقات الموبايل يتم فيها التحميل المزيد من البيانات في كل مرة يضغط في المستخدم مثلاً على جملة تحميل المزيد أو ماشابه. هذا الكلام ينطبق على تطبيقات flutter مثل غيره ويمكنك البحث على google عن كيفية تنفيذ أي من الطريقتين أعلاه.

    اهلا اخي الكريم

    اشكرك على افادتك اول شيء 

    حقيقه انا كنت ارغب باستعمال التحميل المتقطع ولكن مريت على هذا الصفحة ثم قريت ان listview.builder  لا تقوم بتحميل البيانات دفعة واحدة حتى لو كانت القائمة تحتوي على 10 الألاف منتج

     

    ياليت لو لديك وقت تمر على هذا الرابط قد أكون انا فهمت الامر بشكل خاطئ

    https://docs.flutter.dev/cookbook/lists/long-lists

     

    • أعجبني 1
  20. تحيه طيبه للجميع

    استخدم ListView.builder لعرض مجموعة من القوائم التي احصل عليها من قاعدة البيانات 

    لدي سؤال حول ListView.builder / لو صار عدد المنتجات في قاعدة بياناتي يتجاوز 1000 منتج او 10000 منتج هل ListView.builder قادرة على تحميل هذا البيانات بكل كفاه بشكل الطبيعي ؟ ام انا محتاج الى فعل امر ما؟

    هل سيتوقف التطبيق او يعمل كراش لو قمت بفتح صفحة يتم عرض ListView.builder فيها مع عدد منتجات كبير يتجاوز ال 1000 منتج ؟

     

    شكرا للجميع

    • أعجبني 1
  21. بتاريخ 14 ساعات قال Wael Aljamal:

    سيكون لديك قائمة من أغراض، أي عند المرور على القائمة، كل عنصر سيكون له عدة خواص يمكن عمل فلترة منهم

    
    _filteredArray = allItems.where((i) => i.price > 500 && i.color == "red").toList();
    ^^^^^^^^^^^^^^   ^^^^^^^^              ^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^  ^^^^^^^^

    بدل 500 وكلمة red يمكنك وضع متغيرات حالة يمكن للمستخدم إدخالهم وبذلك عند تعديلهم يتم الفترة عند تغيير الحالة

    ويمكنك وضع شرط مركب بأي عدد من المتغيرات.

    في حال أردت عمل فلترة لبعض الخواص، يمكن تطبيق أكثر من فلتر متتالي لأن وضع شرط مركب لن يعمل

    
    if (color !== "")
     _filteredArrayByColor = allItems.where((i) =>  i.color == color).toList();
    
    ^^^^^^^^^^^^^^^^^^^^^^
    
    if (price != 0)
     _filteredArrayByPrice = _filteredArrayByColor.where((i) =>  i.price > 500).toList();
    
                             ^^^^^^^^^^^^^^^^^^^^^
    
    ...

     

    مرحبا اخي الكريم

    شاكر لك ردك عزيزي

    استفسار بس لو تكرمت

    من اين احصل على هذا المتغير i.color كلمة color من اين اتي بها

    وضعها بشكل هذا يعطيني الخطاء التالي:

    Class 'String' has no instance method 'name'.

    طبعا انا قمت بتغيرها الى كلمة name  بحكم الحق لدي كذا اسمه name  

    من اين اتي بها؟

    مع العلم اني لو قمت باستبدالها بشكل التالي تعمل :

    p.startsWith('The name here')

    ولكني لا استطيع بشكل هذا لنني سوف ارتبط بحقل واحد فقط

     

    قمت بتطبيق ميثود الاستعلام بشكل هذا :

      List listsearch = [];
      Future Searchgetdata() async {
        apiURL =
        'https://*******************}';
    
        var response = await http.post(Uri.parse(apiURL));
        setState(() {
          List jsonList = jsonDecode(response.body);
       
          for (int i = 0; i < jsonList.length; i++) {
          
           listsearch.add(jsonList[i]['name'] + ':' + jsonList[i]['Price'].toString());
          }
        });
      }

     

     

    اما السطر الذي ذكرته انت اصبح بشكل التالي:

        var seachlist = listsearch.where((p) => p.name== ('Ahmad')).toList();

     

  22. تحيه طيبه للجميع

    كيف يمكن عمل filters للبيانات فيListView.builder يتم جلبهم من خلال FutureBuilder? 

    اقصد filters المتعدد بمعنى القائمة الان تحتوي على  السعر + لون+  المقاس+الموقع

    ارغب بتمكين المستخدم من القيام باختيارات اختيارات مختلفة لتصفية هذا القائمة حسب اختياره 

    الكود المستعمل كالتالي:

    
    class FilterPage extends StatefulWidget {
      const FilterPage({Key? key}) : super(key: key);
    
      @override
      _FilterPageState createState() => _FilterPageState();
    }
    
    class _FilterPageState extends State<FilterPage> {
      
      
      Future APIFood() async {
        var apiURL = '***************?id=' +
            ID.toString();
        var response = await http.post(Uri.parse(apiURL));
    
        var responsebody = jsonDecode(response.body);
        if (responsebody.length > 0) {
          return responsebody;
        } else {}
      }
      @override
      Widget build(BuildContext context) {
    
        return
    
          Column(
            children: [
    
    
    
    
              FutureBuilder(
    
                future:APIFood(),
                builder: (context, AsyncSnapshot snapshot) {
    
                  if (snapshot.connectionState == ConnectionState.done) {
    
                    if (snapshot.hasData) {
                      return
    
                        ListView.separated(
                            separatorBuilder: (BuildContext context, int index) {
                              return Divider(
                                thickness: 1,
                              );
                            },
                            shrinkWrap: true,
                            itemCount: snapshot.data.length,
                            scrollDirection: Axis.vertical,
                            physics: ScrollPhysics(),
                            itemBuilder: (BuildContext context, int index) {
    
                              return Column(
                                children: [
    
                                  Text(
                                    snapshot.data[index]['price'].toString(),
    
                                  ),
                                  Text(
                                    snapshot.data[index]['color'].toString(),
    
                                  ),
                                  Text(
                                    snapshot.data[index]['size'].toString(),
    
                                  ),
                                  Text(
                                    snapshot.data[index]['location'].toString(),
    
                                  ),
    
                                ],
                              );
    
                            }
                        );
    
    
                    } else if (snapshot.hasError) {
                      return Center(
                        child: Text(
                          '${snapshot.error} occurred',
                          style: TextStyle(fontSize: 18),
                        ),
                      );
    
    
                    }
                  }
    
                  // Displaying LoadingSpinner to indicate waiting state
                  return SizedBox(
                    height: MediaQuery.of(context).size.height / 1.3,
                    child: Center(
                      child: CircularProgressIndicator(
                        color: Colors.black,
                        valueColor:
                        AlwaysStoppedAnimation<Color>(Colors.black),
                      ),
                    ),
    
    
    
                  );
                },
    
    
              ),
            ],
          );
      }
    }

    ارغب بإضافة قائمة لتصفية البيانات منفصله

  23. بتاريخ منذ ساعة مضت قال علي محسن:

    يمكنك إستعمال الدوال isAfter, isBefore,  isAtSameMomentAs المرتبطة بالنوع DateTime لمقارنة الوقت و ترجع كل من هذا الدوال true أو false وكما يلي

    
    	
    snapshot.data[index]['LastDate'].isAfter(DateFormat('dd-MM-yyy').format(DateTime.now()))
    
    snapshot.data[index]['LastDate'].isBefore(DateFormat('dd-MM-yyy').format(DateTime.now()))
    
    snapshot.data[index]['LastDate'].isAtSameMomentAs(DateFormat('dd-MM-yyy').format(DateTime.now()))
    
    //compareTo كما يمكنك إستخدام
    
    // لكن هذه الدالة ترجع لك 1 أو 0 أو -1 بنفس الدلالة السابقة
    
    snapshot.data[index]['LastDate'].compareTo(DateFormat('dd-MM-yyy').format(DateTime.now()))
    
    // DateTime ‌لاحظ أننا نقارن النوع
    
    //String إذا الوقت لديك من النوع
    //كما يلي DateTime يمكنك تحويله الى
    
    dt= DateTime.parse('2020-01-02T07:12:50+07:00') // مثال
    
    // ثم تجري المقارنة كما سبق

    الحل المطروح هنا يحل الإشكالية الموجودة في المثال في سؤالك أي المقارنة بين قيم الوقت كما يفهم من الكود الذي تطرحه. إذا كنت تريد مقارنة قيم أخرى فلا بد من تحديد نوع هذه القيم لتحديد طريق المقارنة ذات العلاقة.

    جزاك الله الف خير اخي الكريم

    • أعجبني 1
×
×
  • أضف...