مكتبه : Joda - Time ( للتاريخ الهجرى ) في الاندرويد

مكتبه : Joda-Time (للتاريخ الهجرى)


التاريخ الهجرى له اهميه كبيره لدى المسلين لانه التاريخ المعتمد لديهم وهو بدايه هجره المصطفى صلى الله عليه وسلم.،


اغلب لغات البرمجه لها مكتبات تدعم التاريخ الهجرى لكن منذ فتره ليست بالقريبه لم تكن لغه الجافا تدعم التاريخ الهجرى وكنت تحتاج لبذل مجهود مضاعف لعمل التاريخ الهجرى بالجافا وايضا فى تطبيقات الاندرويد.، لكن بعد هذه المكتبه ستتعامل مع التاريخ الهجرى بكل يسر وسهوله.


من خلال هذه التدويته، سنبدء عمل مشروع بسيط يعرض التاريخ الهجرى والتاريخ الميلادى معا

وستكون واجهه التطبيق النهائيه كما بالشكل التالى

Joda Time

ملاحظه : الشرح مبسط جدا ولا نعطى اهميه فى الشرح للكود ديزاين (Design Code) ولا كتابه الاسماء فى ملف الاسترنج (Strings.xml)


اولا : سيتم عمل مشروع جديد باسم (Jado_Time_Hgre)

سنستخدم فى هذا المشروع مكتبه ( androidx ) وسنختاج اضافة السطر التالي لكي نستخدم ال (CardView) فى المشروع من خلال الذهاب الى ملف الجرادل ونضيف السطر التالي داخل ال (dependencies) 

      //card view library
          implementation 'androidx.cardview:cardview:1.0.0' 
    

بعد ذلك سنحتاج عمل مجموعه من ( TextView ) لعرض البيانات مثل التاريخ واليوم والشهر الخ، لذلك تم عمل التصميم البسيط التالى. فقط قم بنسخه داخل ملف ال ( activity_main.xml ) الخاص بالاكتفتى الرئيسي. وقم بتحميل الصوره من هذا اللينك  ووضعها داخل مجلد ( Drawable )


كود ملف ال xml
      <?xml version="1.0" encoding="utf-8"?>
      <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          tools:context=".MainActivity">

          <LinearLayout
              android:id="@+id/linearLayout"
              android:layout_width="match_parent"
              android:layout_height="0dp"
              android:orientation="horizontal"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toTopOf="parent">

              <androidx.cardview.widget.CardView
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_marginLeft="10dp"
                  android:layout_marginTop="20dp"
                  android:layout_weight="1">

                  <LinearLayout
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"
                      android:layout_weight="1"
                      android:orientation="vertical">

                      <TextView
                          android:id="@+id/tv_hgry_day_xml"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_marginTop="30dp"
                          android:layout_weight="1"
                          android:gravity="center_horizontal"
                          android:padding="10dp"
                          android:text="8"
                          android:textAlignment="center"
                          android:textSize="20dp"
                          android:textStyle="bold" />

                      <TextView
                          android:id="@+id/tv_hgry_month_xml"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_weight="1"
                          android:gravity="center_horizontal"
                          android:padding="10dp"
                          android:text="محرم"
                          android:textAlignment="center"
                          android:textSize="20dp"
                          android:textStyle="bold" />

                      <TextView
                          android:id="@+id/tv_hgry_year_xml"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_weight="1"
                          android:gravity="center_horizontal"
                          android:padding="10dp"
                          android:text="1442"
                          android:textAlignment="center"
                          android:textSize="20dp"
                          android:textStyle="bold" />
                  </LinearLayout>
              </androidx.cardview.widget.CardView>

              <androidx.cardview.widget.CardView
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_marginLeft="10dp"
                  android:layout_marginTop="20dp"
                  android:layout_weight="1">

                  <LinearLayout
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"
                      android:layout_weight="1"
                      android:orientation="vertical">

                      <TextView
                          android:id="@+id/tv_ar_name_day_xml"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_marginTop="30dp"
                          android:layout_weight="1"
                          android:gravity="center_horizontal"
                          android:padding="10dp"
                          android:text="الخميس"
                          android:textAlignment="center"
                          android:textSize="20dp"
                          android:textStyle="bold" />

                      <TextView
                          android:id="@+id/tv_en_name_day_xml"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_weight="1"
                          android:gravity="center_horizontal"
                          android:padding="2dp"
                          android:text="THURSDAY"
                          android:textAlignment="center"
                          android:textSize="14sp"
                          android:textStyle="bold" />

                      <TextView
                          android:id="@+id/tv_en_num_day_xml"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_weight="1"
                          android:gravity="center_horizontal"
                          android:padding="10dp"
                          android:text="27"
                          android:textAlignment="center"
                          android:textSize="20dp"
                          android:textStyle="bold" />

                      <TextView
                          android:id="@+id/tv_all_num_data_xml"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_weight="1"
                          android:gravity="center_horizontal"
                          android:padding="2dp"
                          android:text="2020/10/08"
                          android:textAlignment="center"
                          android:textSize="14sp"
                          android:textStyle="bold" />
                  </LinearLayout>
              </androidx.cardview.widget.CardView>

              <androidx.cardview.widget.CardView
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_marginLeft="10dp"
                  android:layout_marginTop="20dp"
                  android:layout_marginRight="10dp"
                  android:layout_weight="1">

                  <LinearLayout
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"
                      android:layout_weight="1"
                      android:orientation="vertical">

                      <TextView
                          android:id="@+id/tv_ar_num_day_xml"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_marginTop="30dp"
                          android:layout_weight="1"
                          android:gravity="center_horizontal"
                          android:padding="10dp"
                          android:text="27"
                          android:textAlignment="center"
                          android:textSize="20dp"




       

                          android:textStyle="bold" />

                      <TextView
                          android:id="@+id/tv_ar_name_month_xml"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_weight="1"
                          android:gravity="center_horizontal"
                          android:padding="10dp"
                          android:text="اغسطس"
                          android:textAlignment="center"
                          android:textSize="20dp"
                          android:textStyle="bold" />

                      <TextView
                          android:id="@+id/tv_ar_num_year_xml"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_weight="1"
                          android:gravity="center_horizontal"
                          android:padding="10dp"
                          android:text="2020"
                          android:textAlignment="center"
                          android:textSize="20dp"
                          android:textStyle="bold" />
                  </LinearLayout>
              </androidx.cardview.widget.CardView>

          </LinearLayout>

          <LinearLayout
              android:id="@+id/linearLayout3"
              android:layout_width="match_parent"
              android:layout_height="0dp"
              android:layout_marginStart="8dp"
              android:layout_marginEnd="8dp"
              android:orientation="vertical"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toBottomOf="@+id/linearLayout">

              <androidx.cardview.widget.CardView
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:layout_marginTop="10dp">

                  <TextView
                      android:id="@+id/textView11"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:gravity="center_horizontal"
                      android:padding="10dp"
                      android:text="نشر العلم وتعليمة صدقة جارية "
                      android:textAlignment="center"
                      android:textSize="18sp"
                      android:textStyle="bold" />
              </androidx.cardview.widget.CardView>

          </LinearLayout>

          <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="0dp"
              android:orientation="vertical"
              app:layout_constraintBottom_toBottomOf="parent"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toBottomOf="@+id/linearLayout3">

              <androidx.cardview.widget.CardView
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:layout_marginTop="5dp"
                  android:layout_marginBottom="5dp"
                  android:layout_weight="1">

                  <ImageView
                      android:id="@+id/imageView"
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"
                      android:contentDescription="TODO"
                      android:paddingLeft="5dp"
                      android:paddingRight="5dp"
                      app:srcCompat="@drawable/clock" />
              </androidx.cardview.widget.CardView>
          </LinearLayout>
      </androidx.constraintlayout.widget.ConstraintLayout>
    

ثانيا : نبدء اضافة مكتبه "joda time" للمشروع

نذهب للجرادل "Gradle" ونضيف الكود التالى
      //joda time library
          implementation 'joda-time:joda-time:2.10.6'
    

بعد اضافه المكتبه نضغط على كلمه "Sync Now" فى اعلى يمين الشاشة ونذهب الى كلاس "MainActivity" لاضافه الاكواد البرمجية

ملاحظه : يمكن استخدام مكتبه "Butter Knife " لتقليل الاسطر البرمجيه وتوفير الوقت وذلك افضل ولكن هنا سنتعامل بابسط الاساليب فى هذا المروع حتى لا نعقد الامور ،


نبدء باخذ "object" من العناصر التى نحتاجها وذلك من خلال الكواد التالى

تنبيه : الكود يوضع فوق داله ال "onCreate" واسفل الكلاس 
كود : (1)
      //Start CODE : 1
      TextView tv_hgry_day_java ,tv_hgry_month_java ,
                      tv_hgry_year_java,tv_ar_name_day_java,
                               tv_en_name_day_java,tv_en_num_day_java,
                                      tv_all_num_data_java,tv_ar_num_day_java,
                                          tv_ar_name_month_java,tv_ar_num_year_java;
      //object from Datetime class
      DateTime dataTime;
      //End CODE : 1
    

بعد ذلك نقوم بعمل "initialization" للعناصر وذلك من خلال الكود التالى

تنبيه : الكود يوضع داخل ال "" واسفل "End CODE : 1"
كود : (2)
      //Start CODE : 2
           tv_hgry_day_java = findViewById(R.id.tv_hgry_day_xml);
               tv_hgry_month_java = findViewById(R.id.tv_hgry_month_xml);
                   tv_hgry_year_java = findViewById(R.id.tv_hgry_year_xml);
                       tv_ar_name_day_java = findViewById(R.id.tv_ar_name_day_xml);
                           tv_en_name_day_java = findViewById(R.id.tv_en_name_day_xml);
                           tv_en_num_day_java = findViewById(R.id.tv_en_num_day_xml);
                       tv_all_num_data_java = findViewById(R.id.tv_all_num_data_xml);
                   tv_ar_num_day_java = findViewById(R.id.tv_ar_num_day_xml);
               tv_ar_name_month_java = findViewById(R.id.tv_ar_name_month_xml);
           tv_ar_num_year_java = findViewById(R.id.tv_ar_num_year_xml);
       
      //initialization object
      dataTime = new DateTime();

      // convert Gregorian date to hijri
      DateTime islamDate = dataTime.withChronology(IslamicChronology.getInstance());
       //End CODE : 2
        

الان بعد ان اخذنا اوبجكت من كلاس ( DataTime ) وتم عمل ( initialization ) لها ناتى لاهم نقطه وهي طباعه التاريخ الميلادى ، لان اساس عمل المكتبه مبنى على التاريخ الميلادى عن طريق تحويله للتاريخ الهجرى.


لطباعه اليوم مثلا يكون باستدعاء الداله (getDayOfMonth) من خلال الاوبجكت الذى قما بعمله وهو ( dataTime )
فيكون الكود بالشكل التالى
dataTime.getDayOfMonth();
او من خلال استخدام رموز(حروف) معرفه مسبقا ومحدده مثل طباعه اليوم سيكون باستخدام (dd)
مثل الكود التالى
dataTime.toString("dd");
مثال اخر لطباعه السنه نقوم باستدعاء الداله (dataTime.getYear) كما بالكود التالى
dataTime.getYear();
او من خلال استخدام الرموز يكون باستخدام (YYYY) كما بالكود التالى
dataTime.toString("YYYY");


ناتى الان لتحويل التاريخ الميلادى الى تاريخ هجرى، ويكون ذلك باستدعاء الداله  (withChronology)  من خلال عمل ابجكت من كلاس (DateTime).  لنستدعى الداله ( withChronology ) ونمرر لها بارميتر من نوع ( Chronology ).

 فيصح الكود بالشكل التالى

        DateTime islamDate = dataTime.withChronology(IslamicChronology.getInstance());
      

ولطباعه التاريخ الهجرى نستخدم المتغير الذى قما بعمله باسم (islamDate) واستدعاء نفس الدوال السابق استدعائها فى التاريخ الميلادى

ولكن ستكون كما بالشكل التالى
        islamDate.getDayOfMonth();          لطباعة الشهر
        islamDate.toString("YYYY");         لطباعة السنة
      

الان يتبقى الجزء الاخير وهو الخاص بتمرير التاريخ للتكست فيو بعد تحويله لنص ليتم عرضه 

فنقول ان لدينا تكست معرف باسم (x) ولطباعه قيمه تكون باستدعاء الداله (setText) ونحول القيمه المدخله ل (String) عن طريق الداله (String.valueOf) ونمرر لها التاريخ كبارميتر ليصبح الكود كما بالشكل التالى

x.setText(String.valueOf(data))
او من خلال ادخال الداتا ثم تحويلها ل (String) كما يالى
x.setText(data.toString(""))
ليكون الكود النهائى كما بالشكل التالى
تنبيه : الكود يوضع داخل داله ال "onCreate" واستفل "End CODE : 2"
كود : (3)
        //Start CODE : 3
        //Gregorian date
         tv_ar_num_day_java.setText(String.valueOf(dataTime.getDayOfMonth()));//day number       //TODO translate to arabic
             tv_ar_name_month_java.setText(dataTime.toString("MMMM"));//month name       //TODO translate to arabic
                 tv_ar_num_year_java.setText(String.valueOf(dataTime.getYear()));//year number  //TODO translate to arabic

         tv_ar_name_day_java.setText(dataTime.toString("EE"));//day name     //TODO translate to arabic
             tv_en_name_day_java.setText(dataTime.toString("EEEE"));//day english name
                 tv_en_num_day_java.setText(String.valueOf(dataTime.getDayOfMonth()));//day english number
                     tv_all_num_data_java.setText(dataTime.toString("YYYY/MM/dd"));//all data number

        //hijri date
        tv_hgry_day_java.setText(String.valueOf(islamDate.getDayOfMonth()));//day hijri
             tv_hgry_month_java.setText(String.valueOf(islamDate.getMonthOfYear()));//month hijri //TODO display name Hijri month as a String
                  tv_hgry_year_java.setText(String.valueOf(islamDate.getYear()));//year hijri
         //End CODE : 3 
      

فقط يتبقى جزء تحويل التاريخ للغة العربية ولكن ذلك سيكون عليك  لمن يتابع الشرح
وللمساعده اكثر الرابط التالى هـنـا  فيه تجده ولكن باللغة الانجليزية وذلك ليس لتعقيد الامور ولكن لان المبرمج لابد ان يتعلم البحث عن ما يريد قبل ان يتعلم البرمجه فالبحث مهم جدا وايضا القليل من اللغه الانجليزية

للمزيد من الشرح والايضاح اضغط هنا عالم البرمجه



مكتبه:android butter knife

مكتبه باتر نايف او بالعربيه سكينه الذبده، هي مكتبه هامه لجميع مطورى اندرويد استوديو. فهى توفر الكثير من الوقت والمجهود. حيث ان اى مشروع تعمل عليه يحتاج الكتير من الاوجيكت او الفيوز (Views) مثل الزراير والصور والتكست والامبوت تكست، وهنا تاتى المشكله لان كل عنصر يحتاج الى عمل تهيئه (initialization) على حدى وعمل متغير له او اوبجكت من الكائن خارج الكلاس. وتعريفه داخل الداله (onCreate) وذلك ياخد وقت وجهد كبير وهنا تاتى اهمية هذه المكتبه


Butter Knife


مبرمج هذه المكتبه هو "Jake Wharton" 

جاك ورثون البالغ من العمر .. سنه عملاق البرمجه لما له من اسهامات كثيره

  • طور مكتبه butterknife عام 2013 ولاقت احسان  الكثير من المطورين   ..  للينك المكتبه على الجيت هاب اضغط github
  • وطور مكتبه RxAndroid عام 2015  ...  للمزيد من التفاصيل حول المكتبه اضغط   هــنــا  وللينك المكتبه على الجيت هاب اضغط github
  • وطور مكتبه Retrofit  عام 2013   ...  للمزيد من التفاصيل حول المكتبه اضغط   هــنــا   وللينك المكتبه على الجيت هاب اضغط  github

كيفيه إضافه المكتبه Butter Knife للبروجكت فى الاندرويد استوديو

ملحوظه : الشرح على احدث اصدار من برنامج اندرويد استوديو نسخه 4.0.1  مع العلم ان الفكره فى الاصدار انه يستخدم مكتبه android X وليس android support 

لذلك وجب التنبيه :  ويمكن استخدام android X  فى اصدار اقدم من البرنامج ولكن يجب تحديث الجرادل والتعديل على المشروع

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

لدينا مشروع بسيط يقوم بعمليه جمع رقمين يحتاج ل 2 EditText لادخال الرقمين  و Button لتنفيذ العمليه و 2 TextView واحد لاظهار ناتج عمليه الجمع والثانى لتعريف المستخدم ان العمليه التى يقوم بها التطبيق جمع فقط 

كما بالصوره التاليه
calculator
وربط العناصر والكود سيكون كما بالشكل التالى
butterknife

حسنا الان نبدء اضافه المكتبه ، نذهب لملف الجرادل ونضيف السطرين التاليين داخل اقواس كلمه اندرويد

        // Butterknife requires Java 8.
          compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
          }
      

كما بالصوره التاليه
butterknife


ونضيف فى نفس الملف (gradle) داخل اقواس (dependencies) السطرين التاليين


        dependencies {
          implementation 'com.jakewharton:butterknife:10.2.3'
          annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
        }
      

كما بالصوره التاليه
butterknife


بعد الضغط على  Sync Now  للمشروع ننتظر حتى الانتهاء ولابد ان يعمل بشكل صحيح بدون مشاكل او اخطاء اثناء الاضافه.

الان نبدء استخدام مكتبه Butter Knife

  بدل من اخد ابجكت من الكلاس نكتب كلمه  @BindView   وبعد ذلك نحدد الكائن الذى نريده بكتابه  بين قوسين 
(R.id.item_name_xml) و نقوم بعمل كاستج لنوع المتغير وليكن من نوع TextView  وبعد ذلك نعطى اسم للمتغيرمثل item_name_java

ليصبح السطر كامل كما بالشكل التالى
@BindView(R.id.item_name_xml) TextView item_name_java;
واذا كانت الكائن من نوع  Button سيكون الكود كما يلى

@BindView(R.id.item_name_xml) Button item_name_java;

ملاحظة : item_name_xml اسم الكائن فى ملف ال xml و item_name_java اسم المتغير للكائن الذى سنعطيه له فى كلاس الجافا


 ليصبح كما بالشكل التالى

butterknife


وهنا الفرق واضح جدا فى عدد سطور الكود وكلما كان المشروع ضخم كلما زادت اهميه المكتبه مع العلم تم صدور مكتبه خاصه بجوجل حديثا بديله عن تلك المكتبه تحمل اسم View binding 
 
تلك المكتبه بامكانك مشاهدتها من خلال الضغط هنا
تم بحمد لله
وبالتوفيق للجميع