ListView هو طريقة نستخدمهة علمود نسوي لست بيانات علا شكل لستة طبعا لستة بدون بيانات ما تسوة اي شي نحتاج ادابتر هذه ادابتر نستخدمة علمود نربط المصفوفة بل لست فيو يعني ال ادابتر ياخذ البيانات وا يحولهة الا لست فيو طريقة ستخدام لست فيو اول شي نضيفهة بكود اكس ام ل var arrayoflist:Array<String>=arrayOf("a") var adabter:ArrayAdapter<String> = ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,arrayoflist)//هنا مررنة كونتيكس اول باراميتر اما ثاني باراميتر ستخدمنة مكتبة اندرويد حتة نوصل لملف اكس ام ل هذه ملف بي نصوص ال اتيم اما ثالث باراميتر هو مصفوفة رح يتبدل بي القيم لل ايتم listview.adapter = adabterlist //هنا ربطنة لست فيو بل ادابتر ----------------- RecyclerView هو عبارة عن طريقة لعرض البينات علا شكل قائمة سواء كانت عامودية ام افقية او علا شكل شبكية كراد يعتبر ريساكل فيو اخف وا اسرع علا ذاكرة من لستفيو حيث يتم عمل ريسايكلر او اعادة تدوير لل عناصر كلما قمنا بعمل سكرول لل لست بل ريسايكل فيو العناصر من تختفي يعني من نسوي سكرول العناصر ماراح تدمر بل رح تبقة ونكدر هم نستخدمهن من جديد يعني اعادة ستخدام العناصر هذه الخاصية رح توفر مزيد من طاقة وا توفر مزيد من الاستجابة لل تطبيق - نكدر نستخدمة حتة نزل بل عناصر يعني نسوي سكرول فيو اول شي رح نضيف ال ريسايكلر فيو بل اكتفتي اكس ام ال ثاني شي نسوي لست رو بعدين رح نسوي كومباين مع ريسايكلر فيو يعني نسوي ملف اكس م ل بي صفوف يعني التصميم مو احنة من نستخدم ريساكلر فيو حتة نعرض تصميم علا شكل قائمة بعدين نسوي كلاس هذه كلاس بي معلومات ال صفوف يعني بيانات الي رح نضيفهة بل ريسايكلر فيو بعدين نسوي كلاس ادابتر هذه ال ادابتر رح يربط البيانات بل ريسايكلر فيو - متطلبات add the implementation("androidx.recyclerview:recyclerview:") // For control over item selection of both touch and mouse driven selection implementation("androidx.recyclerview:recyclerview-selection:1.1.0") to the build graidl moudel app xml file contain recycleview xml file contain the design data model class hold our data we want to show to the recycleview adapter class that well bind the data to the recycleview the adapter class code class TodoAdapter (var todos:List<Todo>): RecyclerView.Adapter<TodoAdapter.TodoViewHolder>() {//هنا نرثث ال ادابتر وا نحدد ال فيوهولدر الي نريد نتعامل ويا override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {//هذه الدالة تستخدم لي انشاء نسخة لل فيوهولدر لكل عنصر val binding: ItemTodoBinding = ItemTodoBinding.inflate(LayoutInflater.from(parent.context), parent, false)//هنا وسينة انفليت لل عناصر ال باراميتر الي بل دالة فروم هوة يمثل الحاوي الي رح يحتوي العناصر الي سوينالهة انفليت لذالك استخدمنة الكونتيكست ماتة حتة نعطي معلومات حوله لل دالة انفليت return TodoViewHolder(binding)//هنا ارجعنة نسخة من فيوهولدر يحتوي علا العنصر الي سوينالة انفليت } override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {// هذه الدالة تستخدم لي ربط البيانات في العناصر باراميتر الاول هولدر يستخدم لل وصول لل عناصر باراميتر الثاني يشير الا اماكن العناصر الموجودة في ريسايكلفيو وا هذه الدالة ايضا تستدعا لكل عنصر مرة واحدة holder.binding.apply {//هنا عبر هولدر الي هوة كائن من فيو هولدر وا عبر البايندانك نوصل لل عناصر tvtext.text = todos[position].title//now we use the position like in index to accsice the data in the todos class and call the title to get the value of it and make it for the text same for the second item checkdone.isChecked = todos[position].ischecked//hair we see for the position 1 make the value ischeked }//the binding function well called one for each item in recycle view } override fun getItemCount(): Int {//هذه دالة ترجع عدد العناصر الموجودة في ريسايكلفيو return todos.size } inner class TodoViewHolder(val binding: ItemTodoBinding) ://view holder هذه انر كلاس نستخدمة علمود نخلي مرجع لل عناصر وا نستخدمة حتا نتحكم في العناصر ياخذ باراميتر هذه الباراميتر يمثل العناصر الي رح تضهر بل ريسايكلفيو RecyclerView.ViewHolder(binding.root) { } } ------ هسة نجي لل كود ال مين اكتفتي var todolist = mutableListOf(//هنا سوينة لستة نخلي بيهة البيانات الي نريدهة تضهر بل ريسايكلفيو Todo("learn hacking",true) ,Todo("learn hacking a+",true) ) val adapter = TodoAdapter(todolist)//هنا انشئنة كائن من ادابتر وا مهدنة قيمتة بل لستة الي ناشئناها binding.reco.adapter = adapter//هنا خلينة ال ادابتر مال ريسايكلفيو بل ادابتر الي انشئنا binding.reco.layoutManager = LinearLayoutManager(this)//هذه لياوت مانجر يستخدم للتحكم في طريقة عرض العناصر في ريسايكلفيو -- viewholder نستخدمة علمود نعطي مرجع لل عنصر الي نريدة يضهر بل ريسايكلفيو وا نستخدمة علمود نتحكم في ضهور العناصر في الريسايكل فيو ال باراميتر الدالخ ال فيوهولدر يمثل جميع العناصر الي بل تصميم يعني ال باراميتر يحتوي علا جميع العناصر adapter هوة المسئول علا ربط البيانات في الريسايكلفيو عبر فيوهولدر onCreateViewHolder() هذه الدالة المسئولة علا انشاء نسخة فيوهولدر لكل عنصر في ريسايكلفيو تستدعا كلما عنصر اراد الضهور في الريسايكلفيو الفائدة من انشاء نسخة من فيوهولدر حتة كل ما اراد اعادة استخدام ريسايكل يعني كل ما نسوي سكرول ما ننشء نسخة جديدة بل نعيد استخدامها لذالك النسخ مجرد لل عناصر الي تريد تضهر داخل هذه الدالة نسوي انفليت لل ملف التصميم الي بي العناصر الي نريدها تضهر لل ريسايكلفيو وراهة ننشئ نسخة من الفيوهولدر وا نمررلة ال فيو ال سوينالة انفليت ك باراميتر وراهة نرجع الكلاس الي ستخدمنا يعني الدالة تستدعا كلما المستخدم قام بعمل سكرول وا الدالة مسئولة علا انشائ نسخة من فيوهولدر لكل عنصر ال باراميتر الاول الي هوة ال parent يمثل ال حاوي الي رح يحتوي علا العناصر الي نسويلهة انفليت بحالتنة هوة ال ريسايكلفيو ال دالة فورم تاخذ كونتيكست لذالك رح نستخدم ال parent.context انو نعطي معلومات لل دالة انفليت حول الفيوكروب onBindViewHolder() تستخدم هذه الدالة حتة تربط بيانات بل عناصر يعني تستتقبل بيانات مثلا مصفوفة نربط هذه المصفوفة بل عناصر ال فيو نوصل لل عناصر عبر ال فيو هولدر وا نخليلهم البيانات يعني تستقبل هذه الدالة بيانات عبر هذه الدالة رح نوصل لل فيوهولدر وا عبر فيوهولدر نوصلل لل فيوز ونمرر الهم البيانات ----------------- cheack box اول شي ننشء دالة اونكلك نخليهة نفس الاسم لكل ال شيك بوكس بعدين نسوي كاستنج لل فيو وراهة نسوي متغير بوليان قيمتة تكون فيو من رح ينضغط عل شيك بوكس هية القيمة تلقائيا رح تصير ترو وذا شال الضغط رح تصير فالس مثال لنفترض انو سوينة الدالة بملف ال اكس ام ل وا جهزنة التصميم هسة رح نسوي المثال بل كود fun onclicknamefunction(view:View) { view as CheckBox var x:Boolean = view.isChecked //isChecked هاي نستخدمهة من المستخدم يضغط عل زر رح تحدد اذا جان ترو او فالس when(view.id)//هل قيمة بداخل الاقواس هو ال معرف مال الفيو رح نسوي عليه حتمالات { R.id.idofcheckbox -> if(x){log.d("idis","true"}else{log.d("idis","false"} } } ----- TextUtils هو كلاس يجي وية الاندرويد يسمحنة ان نتئكد من عنصر معين فارغا ام لا هناك دالة موجودة داخل الكلاس تستخدم لل تئكد من اذا كان العنصر فارا ام لا مثال TextUtils.isEmpty(هنا نكتب العنصر مثلا حقل ادخال ) --------- الوان بل اندرويد عبارة عن انتجر ------- style.xml رح نستهخدم الملف علمود نصمم العناصر مالتنة اول شي نبدي <style name="هنا نكتب اسم ال ستايل حتة نوصلة "> <item name="android:textSize">value</item>//ال ايتم نستخدمهة علمود نكتب التصميم مالتنة يعني نحدد تصميم العناصر نكتب android: حتة نختار قيم التصميم </style> مثال حول ستدعاء في ملف اكتفتي xml نكتب style="name the file" اسم ملف الستايل ------------------- colorprimary هو الي رح نغير لون ال بار colorprimary اما هوة الي يغير لون الشريط الفوك الي نزل منة البردة coloraccent نستخدمة حتة نغيري الوان العناصر من داخل مثلا شيك بوكس نريد من واحد يضغط عليه يصير لون المربع داخلي احمر او اصفر الخ ------ تكدر تغير الثيم بملف ال ستايل يعني تكدر تغير لون ال بار لون ال توب بار هم تكدر تحدد نص معين حجمة يكون مثلا 10 هسة اي نص رح ينضاف رح يكون حجمة 10 بس اذا جان اكو نص محدد احنة مسويلة ستايل خاص بي ماراح يتئثر بل 10 ------- break point هي نقطة تتخلة يم الارقام هاي نقط تخلي ال ديباغ يوكف من يوصللهة //Todo:عبارة عن تعليق يضهر اثناء عمل ديباغ لل تطبيق ---------------- android life cykile onCreate(), onStart(), onResume(), onPause(), onStop(), and onDestroy() النضام يعتبر كل وحدة من ذني عبارة عن حالة جديدة من اكتفتي يعني كل ما يدخل وحدة النضام يعتبرة رح يدخل في اكتفتي جديدة او مرحلة جديدة من الاكتفتي onCreat():هذه الدالة تشتغل من النضام ينشء الاكتفتي يعني هي اول دالة تشتغل بين دورة حيات الاكتفتي نستخدمهة علمود نخلي بداية التطبيق بيهة يعني مثلا من يدخل عل تطبيق يطلع مثلا ايقونة تطبيق او اشعار تطبيق او تسجيل دخول startup يعني ال داخل دالة اون كريت باراميتر اسمة سيف انستانس هذه ال باراميتر من كلاس بندل فايدة ال باراميتر انو يقوم بتخزين حالة الاكتفتي السابقة وذا الاكتفتي ما شتغلت رح تكون قيمتة null لما تنتهي مرحلة تنفيذ دالة اون كريت الاكنتفتي رح تدخل بمرحلة ثانية يدخل بدالة اون ستارت وا دالة اون رسيوم onStart(), onResume() ---- Intent كلاس يستخدم لل انتقال بين الاكتفتي مثال var intent = Intent(this,actvtyname::class.java) startActivty(intent) اول باراميتر ياخذ كونتكست الكونتكست رح يكون الكلاس الحالي وثاني باراميتر رح يكون اسم الاكتفتي الي نريد ننتقل الهة ولازم نحدد نوع انو يكون جافا كلاس وراهة جالة ستارت اكتفتي الي رح تشغل الاكتفتي الي رح ننتقل الهة اكو طريقة مختصرة startActivity(Intent(this,actvitynameclass::class.java)) اكو نوعين من الانتينت implicit intent and explicit intent ال explicit intent نخلي التطبيق مالتنة ينتقل من اكتفتي ال اكتفتي داخل التطبيق اما implicit intent تسمح النة نتنقل بين الاكتفتي الخاصة بتطبيقات خارجية مثلا انتنت يفتح الكامرة وا يتلقط صورة انو ستخدمنة تطبيقات خارجية ماكاتبيهة احنة طبعا نعرف انو ال انتنت يكدر يحمل بيانات ويا نكدر نرسل بيانات عبر اكسترا لاكن اكسترا من اصل 4 اشياء ال 3 البقية هنة action,data,category ال action هو عبارة عن فعل معين تريده ان يحصل مثلا كامرة اتصال ال data يستخدم لتحديد نوع البيانات الي رح يشتغل بي ال action مثلا رقم تلفون صورة الخ مثال لي استخدام انتنت امبلكت val m_intent = Intent() m_intent = setAction(Intent.ACTION._VIEW) m_intent - setDATA(Uri.parse("https://workingdev.net")) startActivity(m_intent) ---- تمرير بيانات بين الاكتفتي كلاس انتنت تكدر تخزن بي بيانات عبر كي فاليو نفس هاش ماب نستخدم دالة putExtra(key,valeu) - شلون نتسقبل البيانات نستدعي خاصية extras يعني يجيب المعلومات مال مفاتيح ول قيم مثال var intentsend = Intent(this,activityname::class.java) intentsend .putExtra("namekey","value") startActivty(intentsend) - secondactivity var data = intent.extras هسة data تخزن بيهة كل قيم المفاتيح شلون نوصل لل قيمة نوصلله عبر ستخدام المتغير وا ستخدام دالة كيت تاخذ باراميتر المفتاح عبر هذه المفتاح رح نوصل لل قيمة data.get("name")//نستخدمهة علمود نجيب قيمة نصية طبعا دوال تختلف علا حسب نوع القيمة مثلا اذا كان عندنة حرف رح تقول كيتشار getChar() ------- ستقبال بيانات من الاكتفتي الي نرسل الهة بيانات اذا نريج نستقبل بيانات من الاكتفتي رح نسوي اوفرايد الدالة onActivityResult(requestCode:Int,resultCode:Int,data:Intent?){//هذه الدالة تشتغل من نرجع من الاكتفتي super.onAcctivityResult(requestCode,ResultCode,data) } requestCode ال اركيمنت الاول هو عبارة عن كود انتجر نستخدمة علمود نميز بين الاكتفتي الي نستقبل منهة بيانات resultCode هذه نخليهة حتة نتئكد انو الانتقال رح يصير يعني البيانات رح تستقبل 3 اركيمنت ال data هذه نستخدمة علمود نحدد ال ال انتنت الي رح يستقبل البيانات يعني ال رح تتخزن بي ال اوفرايد لل دالة نسوي داخل الكلاس الي رح ييستقبل البيانات - هسة رح يجي دور الاكتفتي الي رح يرجع بيانات مثال نرجع نص gobackval.setOnClickListener { var x = this.intent x.putExtra("return","hello from second activity") setResult(Activity.RESULT_OK,x)//هذه الدالة رح نستخدمهة علمود نكول لنضام الاندرويد انو الانتقال جاهز وما بي شي طبعا الباراميترات الي تاخذهة تاخذ باراميتر لل تئكد من الانتقال ججاهز ام لا وا باراميتر الثامي نخلي بي الانتنت الي رح ينتقل الباراميتر الاول هوة resultCode finsh()//هذه الدالة تستخدم لل تخلص من الاكتفتيات الي فتحتهة مسبقا يعني المستخدم من يتنقل بين الاكتفتيات من تدخل علا اكتفتي جديدة رح تصير الاكتفتي القديمة جواهة فة يصير ثقل لذالك نستخدم هذه الدالة علمود تغلق جميع الاكتفتيات الجوة } - ملاحضة ال اكتفتي الي رح يستقبل بيانات بداخلة ال ستارت اكتفتي مايدري عن الانتقال رح يصير لذالك رح نستخدم دالة startActivityForResult(intent,Request_Code) باراميتر الاول هوة الانتنت الي رح يسقبل بيانات باراميتر الثاني هوة ال ريكوستكود الي نميز بين الاكتفتيات الي هي اي وحدة رح تستقبل بيانات ------------- اكو 3 طرق تخزين البيانات اكو انترنل سيف هو تخزين داخلي داخل الجهاز اكو اكسترنل سيف هو تخزين خارجي يعني تخزين برام اكو كلاس شيردبريفنسس هو كلاس نستخدمة علمود نخزن بيانات علا شكل كي و فاليو لاكن هذه ال كي فاليو يتهزن في ملقات اكس ام ل حخزنهة داخل الجاهز الاندرويد وكو طريقة نخزن عبر قاعدة بيانات sqlite نخزن بيانات عبر جداول وكو طريقة تخزن بيانات عبر الشبكة عبر ريموت داتابيس يعني تكدر تخزن بياناتك مثلا بسيرفر وتكدر تستعيدنهة من تتصل بل شبكة --- هسة رح اشرح طريقة ال شيردبريفنسس نضام الاندرويد يجهز فايل شيرد بريفنسس علمود يخزن بي البيانات بفورم او بملف اكس ام ل في مسار data/data/{application package}/share_prefs االبيانات تنحذف اذا الغينة تثبيت التطبيق او مسحنة البيانات من الضبط كود جافا class MainActivity : AppCompatActivity() { private val sherd_pre_file = "sherdprefances" private var sherpref : SharedPreferences? =null @SuppressLint("CommitPrefEdits") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) buid.setOnClickListener { sherpref = getSharedPreferences(sherd_pre_file, 0) var edit: SharedPreferences.Editor = sherpref!!.edit() if (!TextUtils.isEmpty(edid.text.toString())) { var message = edid.text.toString() edit.putString("message", message) edit.apply() edit.commit() } else { Toast.makeText(this, "enter somthing", Toast.LENGTH_LONG).show() } } var databack : SharedPreferences = getSharedPreferences(sherd_pre_file,0) if(databack.contains("message")) { var getmessage = databack.getString("message","not found!!") tuid.text = getmessage } } } - xml code <?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"> <EditText android:id="@+id/edid" android:layout_width="wrap_content" android:layout_height="48dp" android:ems="10" android:inputType="text" android:text="Name" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.497" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.341" /> <Button android:id="@+id/buid" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="72dp" android:text="Button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/edid" /> <TextView android:id="@+id/tuid" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="76dp" android:text="TextView" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/buid" app:layout_constraintVertical_bias="0.0" /> </androidx.constraintlayout.widget.ConstraintLayout> دالة apply تخزن البيانات asynchronously يعني خزن البيانات في الخلفية بين ما بعض العمليات تعمل اما دالة commit تخزب ابيانات synchronously يعني خزن البيانات اولا بعدها اكمل باقي العمليات -------------------------------------------ا ال كومبونينت content proviedr يستخدم لمشاركة البيانات بين التطبيقات عبر طريقة منضمة وا امنة --------------------------------------------------------------------------------------------------------------------------------------------------------------- قواعد البانات هو عبارة عن هيكل يسمح لنا بتخزين البيانات بطريقة اكثر ترتيب يعني يسمح لنا بتخزين البيانات علا شكل جداول الجدول يحتوي علا صفوف وا اعمدة ااول صف رح نخلي بي الملومات مال الجدول او التعريف لل بيانات الي رح نخليهة يعني مثلا نخلي اسم وا عمر وا رقم وراهة من نريد نضيف بينات تلقائيا رح ينضاف صف جديد ورح يتخلة الاسم جوة الاسم وا العمر جوة العمر وا الرقم حوة الرقم وا ايضا نكدر ننشئ علاقة بين الجداول علمود نسرع عملية نقل البيانات database handler يسمح لنا بل تعامل مع الداتا بيس في انشاء الجداول وا انشاء الدوال الي رح نستخدمعهة علمود نتعامل مع قاعدة لبيانات هذه الكلاس هوة ما موجود بس اجنة ننشئء ونسوي وراثة بستخدام SQLiteOpenHelper SQLiteOpenHelper class عبارة عن كلاس يستخدم حتة ننشء وا ندير اصدار قاعدة بيانات علمود نطبق هذه الخواص لازم نطبق الدالتين الي بداخلة onCreate() and onUpgrade() methods - SQLiteDatabase class هذه الكلاس بي دوال سنتخدمهة علمود نتعامل مع قواعد البيانات مثل ننشء نحدث نختار نحذف الخ داخل الدالة اون كريت رح ننشء الجدول مالتنة دالة اون كريت تستدعا مرة وحدة عند انشاء قاعدة البيانات قواعد البيانات مشتركين في مفهوم creat,read,update,dlete معروف اختصار CRUD -- writabledatabase يعني قابل لل قرائة وا الكتابة cursor يسمح النة بقرائة البيانات من الجدول يعني هذه الكلاس يعرف يسوي فيتش من التيبل ------------------ال ال BroadcastReceivers يسمح لبرنامجنا ان تستمع لرسالة محددة من النضام او من برنامج ونكدر نرسل رسائل هم مثلا نرسل ملاحضة البطارية وصلت 10% -------- ال contentprovuders يسمح النة ان ننشئ برنامج يشارك البيانات بين برامج ثانية يعني يسمح لل برامج الثانوية ان توصل لبيانات التطبيق مالتنة ---------- هذه الكود يعني <action android:name="android.intent.action.MAIN" /> ال اكتفتي هية ال انتري بوينت الي رح يبدي منهة التطبيق بختصار نستخدمة علمود نحدد اي اكتفتي رح تشتغل اول وحدة ------------------------ ال View هم عندة كلاس هذه الكلاس نستخدمة علمود نبرمج ال عناصر ال فيو يعني بي دوال وا خصائص حتة نتحكم بل عناصر ال فيو --------------- ال Snackbar نفس توست لاكن الاختلاف يضهر بار معين جوة شاشة يطلع بي شي مثلا رابط او اعلان او زر لخ مثال Snackbar.make(root_layout,"long cliced",Snackbar.LENGTH_LONG).show() ------------------------------ دالة button.setOnLongClickListener ترجع بوليان ترو او فالس اذا ارجعت ترو يعني الغي كل العمليات وشغل ال اونلونك لسنر يعني اذا جان عدنة اون كلك وا اون لونك لسنر وا ارجعنة ترو يعني من اضل ضاغط الغي ال اونكلك وشغل ال اونلونك لسنر وذا ارجعت فالس يعني شغل ال اونلونك لسنر بعدها شغل ال اون كلك --------------- مينيو تستخدم علمود نصل لل اشياء داخل التطبيق بسهولة يعني نتنقل بسهولة موجودة بل زاوية 3 نقاط او 3 خطوط علمون نتعامل مع المينيو نحتاج ننشء فولدر مينيو داخل مجلد ريسورس بعدها ننشء ملف داخل المجلد الي انشئنا بعدين نربط ال مينيو بل برنامج مالتنة لازم نسوي اوفرايد لدالة onCreatOptionsMenu داخل مين اكتفتي بعدين نستدعي دالة inflate fuction of menu object بعدين نضيف حدث لل مينيو حتة نتحكم بل مينيو من المستخدم يضغط نستخدم دالة onOptionsItemSelected كل ايتم داخل المينيو متكون من خاصيتين خاصية android:id="@+id/menufuile" و خاصية android:title="string/menufule" ال android:id هوة معرف ال ايتم الي رح نضيفة بل مينيو و ال android:title هوة الاسم الي رح يضهر بل مينيو لل ايتم مثال لي اضافة ايتم داخل مينيو <item android:id="@+id/menufile" android:title="@string/menufile"/> ----------------- ----------------------فراكمنت fragment هي عبارة عن قطعة من الاكتفتي نستخدمهة علمود نضيف محتوة معين بدون ما ننتقل لغير اكتفتي يعني تكدر تعتبرهة شاشة بداخل شاشة يعني مثلا نريد نضغط عل زر معين ماريدة ينتقل لغير اكتفتي بل تبديل المحتوة الموجود عل شاشة ال فراكمنت الهة كلاس بحد وا الهة ملف تصميم بحد وا الهة لايف سايكل بحد وا دوال التفاعل ويهة هم بحد - لما تغير توجيه الجهاز يعني تسوي لاندسكيب رح يتم اعادة بناء التطبيق من جديد لذالك لازم تحفض الحالة من تسوي اورنتيشن هذه الحالة تشمل اكتفتي وا فراكمنت رح نستخدم supportFragmentManager.beginTransaction().apply { replace(R.id.flfragment,firtfragment) commit() } علمود نحول بين ال فراكمنت بداخلهة نكتب replace(R.id.flfragment,firtfragment) اول باراميتر هوة ال كونتينر الي نريد نبدلة ثاني باراميتر هوة ال تريد تبدل ال كونتينر بي اذا ما فهمت شوف فيديو https://www.youtube.com/watch?v=-vAI7RSPxOA الكونتينر افضل شي يكون فريم لياوت ونخليلة اي دي حتة نوصلة وا لازم نسوي كلاس وا نرث من Fragment() ونمرر لل كونستركتر ملف ال اكس ام ال الي يحتوي علا التصميم الي نريدة يضهر بل فراكمنت ------- ال ثريد وا بروسيس عند تشغيل التطبيق يتم تخصيص موارد لل تطبيق مثل الذاكرة وبعض الاشياء الاخرئ الي يحتاجه التطبيق حتة يوئدي وضيفته تسمة هذه العملية بروسيس ثريد هو سلسلة من التعليمات المسئولة علا تنفيذ الكود الخاص بنة اذناء ما البرنامج شغال رح ال ثريد يستخدم ال موارد الي حجزهة ال بروسس الموارد من المحتمل ان تكون قرائة او كتابة من الميموري او دسك وا قرائة من شبكة يعني ال ثريد هو المسئول علا تحديث النصوص الصور التعامل مع رسوميات بل شاشة ول تعامل مع ادخالات المستخدم هوة المسئول علا تنفيذ كل ذني المهام وا ايضا هوة ال يسوي انفليت لل اكس ام ل وا يحولهم الا فيو يحولهم الا جافا وبجكت مثل الازرار نصوص الخ يفضل ما نسوي حمل كبير علا مين ثريد لن رح يتسبب بثقل التطبيق لذالك اذا جان عدنة مهام كثيرة وا ثقيلة نستخدم ال back ground thread ال background thread يستخدم لل مهام الطويلة مثل قرائة ول كتابة من شبكات او التخزين يعني يستخدم علمود ما نسوي اي ثقل اعل مين ثريد يعني يكون مستقل عن مين ثريدد نستخدم ال AsyncTask class للتعامل وا ادارة ال background thread ال وقت الي ياخذ ال قريد حتة ينفذ مهمة ايطلق عليه threadhold وا ال guidline يعني ترشيحات يفضل اتباعها من اجل عمل سوفتوير او تصميم معين بجودة قوية ------- مثال حول background htread اول شي نقوم بي انشاء كلاس يطبق Runnable بعدها نقوم بعمل اوفرايد لل دالة run هذه الدالة نكتب بداخلهة الكود الي نريدة يشتغل بل background بعدها نقوم بي انشاء كائن ثريد وا نمرر له كئن من ruuable الكائن الي رح نمررة بداخلة نسوي اوفرايد لل دالة رن بعدها نقوم بي استدعاء دالة ستارت مالت ال ثريد ---- دالة runOnUiThread تاخذ هذه الدالة كائن من كلاس Runnabe وتنفذ الكود الخاص بل كلاس رونبل داخل ال مين ثريد -- كلاس handler يستخدم لي ادارة الثريد وا يستخدم ايضا لل تواصل بين main thread, background thread تذكر المثال من قلنة الكود ما يتنفذ كلة بوقت واحد انو يروح MessageQueue; وراهة ينتضر يتم ختيارة وراهة يتنفذ الهاندلر يسوي هيج انو يختار وراهة ينفذ ------ كلاس AsyncTask هو كلاس يستخدم لتشغيل الكود في الباكرواند هوة يشبه الهاندلر كلاس وا بي خصائص افضل لتحديث ال واجهة المستخدم اذا تريد تستخدمة لازم تورثة وا تورث الدوال ماتة حتة نستخدمة تورثة انر كلاس او بكلاس ثاني حسب الطريقة الي تريدهة ------ دالة doAsync هية دالة من مكتبة anko تستخدم هذه الدالة لتشغيل background_thread لاكن جميع الاشياء هذه الدالة تفعلاه تلقائيا يعني ما ننشء ثريد وهاي سوالف بل الدالة هية تسوي كلشي تلقائيا يعني مو مثل كلاس هاندلر او كلاس asynctask اول شي لازم نضيف المكتبة implementation 'org.jetbrains.anko:anko-common:0.10.8' بل dependencies اما عن طريقة ستخدام الدالة نكتب doAsync{hear write the code well run in the background activityUiThread { // make changes to the UI ❷ textView.text = "Hello" } } --------- انوعه الاخطاء في البرنامج -------- تعامل مع تخزين بيانات داخليا انترنل اول شي رح نستخدم طريقة الكتابة في ملف اول شي ننشئ كتغير يحوي علا اسم الملف بعدين ننشء كاءن من دالة openfileoutput هذه الدالة ترجع fileoutputstream تاخذ باراميترات 2 اول واحد اسم الملف ول ثاني ريقة تحديد الوصول لل ملف بعدها نستخدم الاضافة use هذه الاضافة تقوم بي اغلاق الملف تلقائيا بعد تنفيذ الكود بعدها رح نقوم بل كتابة بل ملف عبر ستخدام دالة write البيانات الي رح نكتبها بل ملف رح نحولها الا مصفوفة نوعها بايت val filename = "ourfile" val out = openFIleOutput(ourfile,Context.MODE_PRIVATE) out.use{ out.write(txtidexample.text.toString().toByteArray()) } هذه طريقة انشاء ملف وا الكتابة فيه اما لالن رح اشرح طريقة القرائة في ملف اول ننشء متغير يحتوي لا اسم الملف الي نريد نقرة منة بعدين ننشء كائن من openFileInput() هذه ترجع كائن نوعة fileinputstream تاخذ باراميتر نوعة ملف الي رح نقرة من البيانات بعدين نستخدم الاضافة use بداخلهة رح ننشء كائن نوعة StringBuilder() حتة نجمع النصوص الي رح نقرائه بداخلة وراهة نقوم بل قرائة من الملف بستخدام دالة read الي رح نستخدمهة من الكائن openFIleINput هذه دالة ترجع نوع انتجر رقم ال اسكي لل حرف لذالك الرقم لازم نخزنة في متغير وراهة رح نسوي لوب هذه الوب رح يكون بداخلهة شرط رح تلف علا الملف الي نقرة منة تقارن المتغير الي بداخلة مخزنين رقم الاسكي مال الحرف اذا جان لا يساوي =! ستمر بل لف عل ملف وقرة بيانات داخل الوب رح نضيف ال حرف الي قرينا لل كائن الي انشئنا من ش=stringbuilder ونحولة الا نوع بيانات ْchar وراهة رح نقرة من الملف اذا ما لكة شي اخرج من لوب وا طبعلنة الملف عبرة الكائن الي خنة بي البيانات مثال لل كود val filename = "ourfile.txt" val input = openFileInput(filename) ➊ input.use { var buffer = StringBuilder() ➋ var bytes_read = input.read() ➌ while(bytes_read != -1) { ➍ buffer.append(bytes_read.toChar()) ➎ bytes_read = input.read() ➏ } println(buffer.toString()) ➐ } ---------ؤ شرح هذه الكود class.java.name:: ال :: تستخدم حتة يعطيني مرحع لشيء معين مثلا دالة او خاصية كائن كلاس الخ ال class يعطينا معلومات حول الكلاس الي نستخدمة ال .java هو يرجع النة كائن هذه الكائن مرتبط بكائن كوتلن ليش لن المعلومات الي رح يعطينياها مثل دوال خصائص مكتوبة بجافا لذالك نريد مرجع مرتبط بكائن جافا حتة نكدر نستخدمة بكود الكولتن ال .name هية خاصية نستخدمهة علمود تعطينا اسم الكلاس ---------------------------- brodcastreciver هو عبارة عن كومبونت يستخدم لي ارسال وا ستقبال رسائل النضام مثلا المستخدم ضغط علا شعار او البطارية انخفضت او قام بي اتصال السماعة الخ هناك نوعين من هذه الكومبونت هو system brodcast هو رسائل من النضام custom brodcast هو رسائل ترسل بستخدام تطبيقنا او تطبيقات ثانية اذا تريد تتتعامل مع الرسالة يعني نردهة لازم نسجل reciver اكو طريقتين نسجل بيهة رسيفر عبر manifest / context مثال حول تسجيل رسيفر في ملف manifest <receiver ➊ // هذه النود نستخدمهة علمود نعرف ال رسيفر android:name=".MyReceiver" ➋//هذه اسم الكلاس الرسيفر الي رح يرث من كلاس برودكاست رسيفر android:enabled="true" android:exported="true"> <intent-filter> ➌// هنا نحدد النوع الرسائل الي رح يتعامل معها الرسيفر <action android:name="com.workingdev.DOSOMETHING"/> </intent-filter> </receiver> طريقة تسجيل ريسيفر في الكونتيكت val receiver = MyReceiver()//هنا انشئنا كائن من كلاس ما رسيفر الييرث من برودكاست رسيفر هذه الكائن رح يكون هوة المستلم لل رسالة val intentFilter = IntentFilter("com.example.MY_ACTION")هذه الكائن من انتنت فلتر هوة ال كائن الي يمسك الرسالة الي نريد نتعامل وياهة registerReceiver(receiver, intentFilter) هذه الدالة هية المستمع لل رسالة تاخذ باراميترين اول واحد هوة المستلم الرسيفر ول ثاني باراميتر هوة نوع الرسالة الي يتعامل بيهة الرسيفر يعني هذه الدالة رح نحدد بيهة الرسيفر الي رح يستلم الرسالة ول رسالة الي رح يتعامل وياهة يعني تسجل الرسيفر المحدد الي رح يتعامل وية الرسالة class MyReceiver : BroadcastReceiver() {//هذه الكلاس الي رح نرث منة حتة نستخدم الرسيفر override fun onReceive(context: Context?, intent: Intent?)//هذه الدالة يتم استدعائها عندما يستلم الرسيفر رسالة فايدة هذه الدالة انو نخلي الكود الي الي رح يتعامل وية النوع المحدد مال الرسالة { if (intent?.action == "com.example.MY_ACTION") {//هذه شرط نستخدمة لل تئكد من نوع الرسالة الي رح نتعامل ويا // handle the broadcast message here val message = intent.getStringExtra("message") Log.d("MyReceiver", "Received message: $message") } } } يمكن استلام برودكاست حتة لو كان التطبيق يعمل في الخلفية يعني اذا خلينا سجلنة رسيفر بل مينفيست فايل ال رسيفر رح يتسجل تلقائيا بواسطة نضام الاندرويد من يتثبت التطبيق يعني احنة بس نعرفة بل مينفيست فايل ول اندرويد رح يسجلة تلقائيبا من يتثبت التطبيق ويبقة يسجل رسايل حتة لو لغة من الخلفية طيب ليش لن ال مينفيست فايل مرتبط بل بكج مال تطبيق مالتنة اكو بعض التحفضات انو ال مينفيست مايكدر يستلم انو اذا النضام داخل بحالة sellp or procsses kiled by the system the fix is to restart the system or device wek up from the system - خطوات انشاء برودكاست ريسيفر اول شي تحدد البرودكاست الي تريد تتعامل ويا مثلا سستم برودكات وا كوستم برودكاست كوستم برودكاست هنة رسايل تطبيقك يرسلهة للتواصل معك او للتواصل مع تطبيقات ثانية تكدر انت تحدد نوع الرسالة الي رح يرسلهة اما سستم برودكاست هنة رسالة يرسلهة النضام ثاني شي نحدد طريقة تسجيل الرسيفر عبر كونتيكست او عبر مينفس فايل الفرق بين الكونتيكست وا مينفيست انو الكونتيكس يستلم برودكاست اثناء تشغيل التطبيق من التطبيق ينغلق بعد ما يستلم اما اذا عرفت بل مينفيست انو رح يتسجل تلقائيا بواسطة نضام الاندرويد وا يبقة يستلم برودكاست حتة لو التطبيق ما يشتغل ثالث شي ننشء كلاس يرث من برودكاست رسيفر رابع شي نسوي اوفرايد لل دالة اونرسيفر حتة نعالج الاكشن الي يجي اكو بعض ال برودكاست ما تكدر تتعامل معهم في المينفست فايل --- فرق بين امبلكت برودكاست وا يكسبلكت برودكاست explicit brodcast هو ارسال برودكاست لي اكتفتي معين او تطبيق معين implicit brodcast هو ارسال رسالة بشكل عام يعني اي تطبيق يستطيع ان يرد علا البرودكاست ----- view binding هي طريقة لل وصول لعناصر ال اكسامال بطريقة اسهل مثال class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) } } ال كلاس بداية اسمة لازم نفس اسم ملف ال اكس ام ال حتة نسويلة انفليت ال binding root هو يمثل جميع عناصر ال فيو يعني بختصار viewgroup Android Data Binding library هذه المكتبة هية الي رح تسويلنة الكلاس تلقائيا الكلاس رح يكون اسمة علا نفس اسم ملف ال اكس ام ل من رح نفعل ال data binding اندرويد ستوديو رح ينشء كلاس تلقائيا لكل ملف اكس ام ال يكون بنفس اسم ملف ال اكس ام ال لذالك من تريد تستخدم ال داتا بايدنك رح نكتبة نفس اسم الملف ال اكس ام ال ---------------------- service هي مجموعة من الكومبونت تشتغل بدون يوزر انترفيس او واجهة مستخدم هناك نوعين من الخدمات خدمات forground service and background service ---------------- support muiltpy screan تكدر تخلي التصميم عب كونسترينت لايوات او تكدر تخلي لكل ملف اكس ام ال لنوعية شاشة معينة مجرد تنسخ التصميم مثال -------------------------------- activity stack تكدر تتخيلة انو عبارة عن كوب وعندك 3 اكتفتيات اكتفتي a,b,c اذا انتقلت من اكتفتي a b الا اكتفتي b رح يكون اكتفتي a رح يكون فوق b وذا انتقلت من اكتفتي c الا اكتفتي c رح يكون ال اكتفتي b فوق اكتفتي c وذا رجعت من اكتفتي رح تنحذف ال اكتفتي يعني تنحذف من الكوب ورح تكون ال اكتفتي ال رجع الهة هية الحالية او الاكتفتي الاعلا finish() هذه الدالة رح تمسح الاكتفتي من الاكتفتي ستاك يعني تمسح الاكتفي الحالية -------------------- اذنوات تستخدمهة ملف ال مينفيست تكتب <uses-permission android:name=""/> نحتاج 3 دوال ثنين احنة ننشئهن وحدة نسويلهة اوفرايد الدالة الاولا نستخدمهة علمود نتئكد من البيرمشن الدالة الثاني نستخدمهة علمود نطلب بيرمشن من اليوزر الدالة الثالثة نسويلهة اوفرايد نستخدهة علمود نسوي هاندل لل بيرمشن اذا نقبل كود تعامل مع اذن الانترنت private fun permissiontest() = ActivityCompat.checkSelfPermission(this,Manifest.permission.INTERNET) == PackageManager.PERMISSION_GRANTED//هذه الدالة تشيك علا الاذن موجود ام لا اذا موجود ترجع ترو اذا لا ترجع فالس private fun requestpermission(){//هذه الدالة تستخدم لي طلب بيرمشن من الممستخدم وا تقوم بي اضافة الاذناوات في لست وا تشيك اذا كان الاذن موجود تطلبة وذا جان ما موجود تضيفة بل لستة var permissionarry=mutableListOf<String>() if(!permissiontest()){ permissionarry.add(Manifest.permission.INTERNET) } if(permissionarry.isNotEmpty()){ ActivityCompat.requestPermissions(this,permissionarry.toTypedArray(),0) } } override fun onRequestPermissionsResult(//هذه الدالة تستخدم لي تعامل البيرمشن اذا تم الموافقة عليه requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if(requestCode ==0 && grantResults.isNotEmpty()){ for(i in grantResults.indices){ if(grantResults[i] == PackageManager.PERMISSION_GRANTED){ Log.d("permissionsrequest","${permissions[i]}.granted") } } } } -------------------------------- impilicit intent يعني فتح اكتفتي جديدة لاكن خارجية يعني نستخدم اكتفتيات مال تطبيقات خارجية مثال لكي نختار صورة من الاستديو val imgpicker = registerForActivityResult(ActivityResultContracts.GetContent()){result :Uri?-> if(result!=null){ binding.img.setImageURI(result)//result يمثل النتائج ال راجعة من الاكتفتي } } binding.button.setOnClickListener { Intent(Intent.ACTION_GET_CONTENT).also { it.type = "image/*" imgpicker.launch(it.toString()) } } ----- uri هوة رابط او مسار ال بيانات يعني مقلا رابط الفيس رح يكون facebook.com اما uri هوة رابط البيانات الداخلية مثلا رابط المسار مال ملف معين مثلا c://foled/data/image ------- toolbar menus هي الايقونات الي تنضاف في لمربع طريقة لانشاء اول شي ننئش مجلد يحتوي علا ملف التصميم هذه الملف رح يحتوي علا المينيو داخله رح نخلي كل العناصر الي نريدهة تضهر بل مينيو وراهة نضيف ال يقونات بمجلد ال دراوبل الايقونات الي نريد نستخدمهة وراهة نروح علا مجلد دراوبل نضغط كلك ايمن ونختار image asset ونختار الايقونة هسة رح نضيفهم بل مينيو عبر تاغ الايتم <item android:id="@+id/imsetting"//هنا نحدد الايدي لل ايقونة حتة نبرمجهة android:title="setting"//هوة اسم او عنوان الايقونة android:icon="@drawable/ic_setting"//هنا مسار الايقونة app:showAsAction="ifRoom"/>//هنا طريقة ضهور الايقونة هنا نكلة خلي الايقونة تضهر وتكون قابلة لل ضغط وذا ماكو مساحة خلي الايقونة بل اوفر فلوة بعدها نروح عل اكتفتي ونروح نطبق المينيو الي نريدهة تضهر بل بار override fun onCreateOptionsMenu(menu: Menu?): Boolean {//هذه الدالة نستخدمهة علمود ننشئ المينيو وا نسويلهة انفليت لل عناصر menuInflater.inflate(R.menu.app_bar_menu,menu)//هنا سوينة انفليت لل مينيو return true//هنا ارجعنة ترو يعني ال مينيو تم انشائها بنجاح الباراميتر مينيو هذه يمثل المينيو الي انشئناها } override fun onOptionsItemSelected(item: MenuItem): Boolean {//هنا سوينة اوفرايد لهذه الدالة هذه نستخدمهة علمود نبرمج الايقونات when(item.itemId){ R.id.imsetting -> Toast.makeText(this,"you have clicked setting",Toast.LENGTH_SHORT).show() R.id.imfavorit -> Toast.makeText(this,"you have clicked favirot",Toast.LENGTH_SHORT).show() R.id.imaddcontact -> Toast.makeText(this,"you have clicked add contact",Toast.LENGTH_SHORT).show() R.id.imcloseapp->Toast.makeText(this,"you have be clicked closed app",Toast.LENGTH_SHORT).show() R.id.imfeesback->Toast.makeText(this,"you have be clicked feedback",Toast.LENGTH_SHORT).show() } return true } --------------- alert dailog نستخدمهة علمود نضهر لل مستخدم تنبيه معين نستخدم كلاس val addcontactdilog = AlertDialog.Builder(this).//هذه الكلاس رح نستخدمة علمود ننشء ال دايالوك setTitle("add persion cotact")//هذه الدالة تستخدم علمود تخلي تايتل لل دايالوك الي يضهر .setMessage("do you want to add persion contact")//هذه الدالة تستخدم علمود تضهر رسالة مال دايالوك .setIcon(R.drawable.ic_add_contact_foreground)//هذه الدالة تستخدم علمود تضهر ايقونة بل دايالوك .setPositiveButton("yes"){dialogInterface,i->//هذه دالة تنشء زر لل موافقة علا شيء معين بيهة لامبدة اكسبرشن تاخذ باراميترين اول واحد يمثل ال دايالوك الي رح يضهر لل مستخدم اما ثاني باراميتر يمثل الزر المضغوط Toast.makeText(this,"you better thin bad stuff add",Toast.LENGTH_SHORT).show() } .setNegativeButton("no"){dialogInterface,i->//هذه الدالة تنشء زر يستخدم لرفض الاشياء بيهة لامبدة اكسبرشن تاخذ باراميترين اول واحد يمثل ال دايالوك الي رح يضهر لل مستخدم اما ثاني باراميتر يمثل الزر المضغوط Toast.makeText(this,"no dont back regicted",Toast.LENGTH_SHORT).show() }.creat()//هذه الدالة رح تنشء ال دايالوك لن هسة هذه كلة الكتبنا يكون بولدر يعني من كلاس بولدر مجرد بنينا ما انشئنا لذالك نستخدم هذه الدالة حتة ننشئة هذه الدايالوك يستخدم علمود نضهر لل مستخدم موافقة علا شيء محدد مثلا اضافة المستخدم توافق ام ترفض هسة رح اشرح دايالوك يضهر اكثر من اختيار طبعا كلشي نفس الخطوات لاكن الاختلاف الدالة var options = arrayOf("stoic life","losser life","stoic and bain life") val singlechoicedialog = AlertDialog.Builder(this) .setTitle("choise option") .setSingleChoiceItems(options,0){dialogInterface,i-> Toast.makeText(this,"you have choice $options[i]",Toast.LENGTH_SHORT).show() } .setPositiveButton("accspted"){_,_-> Toast.makeText(this,"you better thin bad stuff add",Toast.LENGTH_SHORT).show() } .setNegativeButton("decline"){_,_-> Toast.makeText(this,"no dont back regicted",Toast.LENGTH_SHORT).show() }.create() اكو طريقة ثالثة علمود نضهر دايالوك انو نسوي اكثر من خيار يختار المستخدم نفس المثال الفوك لاكن اختلاف الدالة var options = arrayOf("stoic life","losser life","stoic and bain life") val multichoice= AlertDialog.Builder(this) .setTitle("choise option") .setMultiChoiceItems(options, booleanArrayOf(false,true,false)){ _, i, ischecked->//ischeked لام نختار ال شيك بوكس وا نسوي عليه صح رح يكون هذه الباراميتر ترو وذا شلنة الصح رح يكون فالس if (ischecked) Toast.makeText(this,"is cheked $options[i]",Toast.LENGTH_SHORT).show() else{ Toast.makeText(this,"unchecked $options[i]",Toast.LENGTH_SHORT).show() } .setPositiveButton("accspted"){_,_-> Toast.makeText(this,"you better thin bad stuff add",Toast.LENGTH_SHORT).show() } .setNegativeButton("decline"){_,_-> Toast.makeText(this,"no dont back regicted",Toast.LENGTH_SHORT).show() }.create() ---------------- spinner شايف من تريد تنشئ يميل ويطلعلك لستة بيهة مجموعة قيم مثلا اشهر السنة او البلاد او مفتاح الدول هوة هذه السبنر نستخدم عنصر سبنر اول شي نسوي نضيف القيم بمصفوفة نصية بملف النصوص بعدين نضيف القيم بل عنصر اكس ام ال بعدين نجي نبرمجة بل كود نكدر نخلي من يختار المستخدم قيمة معينة بل لستة نسوي شي معين <Spinner android:id="@+id/spmonths" android:layout_width="wrap_content" android:layout_height="48dp" android:layout_marginTop="72dp" android:entries="@array/months"//هذه مسار القيم app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/btndilog3" /> هسة رح نجي عل كود binding.spmonths.onItemSelectedListener = object: AdapterView.OnItemSelectedListener{ override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { } هنا نسوي فعل معين من المستخدم يختار احد القيم من لستة باراميتر الاول هوة يمثل السبنر باراميتر الثاني يمثل القيمة المختارة باراميتر الثالث يمثل مكان القيمة باراميتر ال رابع يمثل القيمة الرايعة override fun onNothingSelected(parent: AdapterView<*>?) { } } } ------------------- bottom nagigation هو عبارة عن ازرار تستخدم لل تنقل بين الفراكمنت مانكدر نستخدمة لازم نضيفة بل دبندسيز لنة مضيوف بل مكتبة مال ميتيريل ديزاين implementation 'com.google.android.material:material:1.5.0' وراهة ننشئ مينيو رح نخلي بيهة الايقونات الي نريدهة تضهر بل نافكيشن بوتوم هذه كود ال اكس ام ال <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/buttomnavifationbar" android:layout_width="wrap_content" android:layout_height="75dp" app:menu="@menu/buttom_nav_menu" />//هنا وصلنة لملف ال مينيو الي نريد نخلي بي الايقونات طبعا يستخدم لل تنقل بين ال فراكمنت شوف هذه الفيديو اذا ما فهمت https://www.youtube.com/watch?v=AL_1UDa9l3U&list=PLQkwcJG4YTCTq1raTb5iMuxnEB06J1VHX&index=23 --------- viewpager 2 تكدر تعتبرة هوة ريسايكل فيو لاكن بل عرض اول شي نضيف مكتبة implementation 'com.google.android.material:material:1.5.0' بعدين نضيف ال فيوبيجر بل اكس امل ال <androidx.viewpager2.widget.ViewPager2 android:layout_width="match_parent" android:layout_height="match_parent" /> بعدين ننشء ملف اكس ام ال يكون التصميم مال الا فيو بيجر ----- tab layout viewpager 2 يستخدم لل تنقل بين النوافذ اول شي لازم طبق مكتبة ال ميتيريال ديزاين ثاني شي تضيفة بل اكس ام ال <com.google.android.material.tabs.TabLayout android:id="@+id/tablayout" android:layout_width="match_parent" android:layout_height="wrap_content"/> وراهة نطبقة بل كود البقرمجي TabLayoutMediator(binding.tablayout,binding.viewpager){tab,position->//هنا ستدعينة هذه الكلاس حتة نربط التاب بل فيو بيجر اول باراميتر هوة التاب لياوت وا ثاني باراميتر هوة الفيوبيجر وا الباراميتر الاول يمثل التاب بل لمبدة اكسبرشن وثاني بااميتر يمثل مكان التاب tab.text = "tab${position +1}"//هنا خلينة النص لل تاب وا خلينة مكانة }.attach()//هذه الدالة تعني اربط التاب بل فيوبيجر binding.tablayout.addOnTabSelectedListener(object:TabLayout.OnTabSelectedListener{//هنا رح نستخدم انونيموس كلاس يطبق انترفيس اونتاب سيليكتيد لستنير حتة نبرمج التاب اذا شخص ضغط عليهن override fun onTabSelected(tab: TabLayout.Tab?) { Toast.makeText(this@MainActivity,"you have selected tab",Toast.LENGTH_SHORT).show()//هذه الدالة تستخدمه اذا تريد تبرمج الزر عند ضغط عليه } override fun onTabUnselected(tab: TabLayout.Tab?) { Toast.makeText(this@MainActivity,"you have unselected ${tab?.position.toString()}",Toast.LENGTH_SHORT).show()هذه الدالة تستخدم ختة تبرمج الزر اذا ضغطت علا غير زر } override fun onTabReselected(tab: TabLayout.Tab?) { Toast.makeText(this@MainActivity,"you have resalcted ${tab?.position.toString()}",Toast.LENGTH_SHORT).show()هذه الدالة تستخدم لتبرمج زر اذا انضغط عليه مرة ثانية } }) ------- slidable menu هية مينيو من تضغط عليهة تطلع بل زاوية كود اكس ام ال <?xml version="1.0" encoding="utf-8"?> <androidx.drawerlayout.widget.DrawerLayout 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" android:id="@+id/drawer" android:orientation="vertical" tools:context=".MainActivity"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tvtext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text view" android:textSize="40sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.5" /> </androidx.constraintlayout.widget.ConstraintLayout> <com.google.android.material.navigation.NavigationView android:id="@+id/navid" android:layout_width="wrap_content" android:layout_height="wrap_content" app:headerLayout="@layout/header" app:menu="@menu/buttom_nav_menu" android:layout_gravity="start" android:fitsSystemWindows="true"/> </androidx.drawerlayout.widget.DrawerLayout> كود برمجي lateinit var toggel :ActionBarDrawerToggle//هنا عرفنة ال توكل بتن الي هوة ال 3 نقاط الي تكون بل زاوية مال مينيو toggel = ActionBarDrawerToggle(this,binding.drawer,R.string.open,R.string.closed)//هنا مهدنة قيمتة نطينا ال كونتيكست وا نطينا ال نافكيشن دراور الي رح يطلع بي وا عطينا نصين هذني النصوص يطلعن لل اشناص العميان binding.drawer.addDrawerListener(toggel)//هنا ضفنة ال 3 نقاط بل نافكيشن دراور toggel.syncState()//هنا كنكنة ال 3 نقاط بل نافكيشن دراور supportActionBar?.setDisplayHomeAsUpEnabled(true) //هذه الكود رح يسمحلنة بل وصول لل اكشن بار مال الاكتفتي الحالية وا يفعل زر الرجوع binding.navid.setNavigationItemSelectedListener {//هنا نبرمج الازرار الي رح تنضغط بل مينيو when(it.itemId){ R.id.imhome -> Toast.makeText(applicationContext,"you clicked1",Toast.LENGTH_SHORT).show() R.id.improfile -> Toast.makeText(applicationContext,"you clicked2",Toast.LENGTH_SHORT).show() } true } fun onOptionsItemSelected(item: MenuItem): Boolean { if(toggel.onOptionsItemSelected(item)){ return true } return super.onOptionsItemSelected(item) } }} ------- notifacdtion ارسال اشعارات لل مستخدمين حول شيء معين first thing we nead to open NOTIFICATIONS channel that used to hold NOTIFICATIONS confugration val channel_id = "channelid"//هذه اي دي قناة الاشعارات val channel_name = "channelname"//هذه اسم قناة الاشعارات val notfi_id = 0 creatNotificationChannel() val notification = NotificationCompat.Builder(this, channel_id) .setContentTitle("am the title") .setContentText("am text") .setSmallIcon(R.drawable.ic_add_contact_foreground) .setPriority(NotificationCompat.PRIORITY_LOW) .build() val notificationmanager = NotificationManagerCompat.from(this) binding.showbtn.setOnClickListener { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { } notificationmanager.notify(notfi_id,notification) } } fun creatNotificationChannel(){//هذه دالة احنة نسويهة حتة ننشئ قناة if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){//هنا نتئكد اذا اصدار اس دي كي اعلة او يساوي اصدار اوريو val channel = NotificationChannel(channel_id, channel_name,NotificationManager. IMPORTANCE_DEFAULT).apply { lightColor = Color.GREEN enableLights(true) }//هنا مهدنة القناة يعني سوينة اعداداتهة وا اعطيناها اي دي القناة وا اسم القناة وا افضلية الاشعارات الي نريد نستخدمهة وا دالة ابلاي تستخدم لفعل شيء معين عند حدوث الاشعار val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager manager.createNotificationChannel(channel) } } ------------- intent service or jobintentservice هوة سب كلاس من كلاس يرفرس هذه الكلاس يوفر النة طرق تعامل مع عمليات اسايكروناز يعني نسوي اكثر من عملية بل خلفية بدون ما نسوي بلوك لل مين ثريد اول شي لازم لكل سيرفس ننشء كلاس class MyIntentServace : JobIntentService() { companion object{ fun enqueueWork(context: Context, intent:Intent){//هذه الدالة الي رح نستدعيهة نمرر الهة ال كونتيكست وا ال انتنت الي هوة يمثل السيرفس الي رح يشتغل بل باكراوند enqueueWork(context,MyIntentServace::class.java,0,intent)//هذه الدالة هية الي رح تخليلنة ال المهام بقائمة نمرر الهة الكونتيكست وا ال كلاس او الاكتفتي الي رح يشتغل بيهة المهمة وا نمرر الهة كود حتة نميز بين الخدمات وا نمرر الهة ال انتنت الي هوة المهمة } } override fun onHandleWork(intent: Intent) {//هذه الدالة رح تعالج السيرفس الي رح تجي من القائمة يعني تعالج ال مهمة الي نريدهة تشتغل بل خلفية } } من نستدعي الدالة enqueueWork(context,intent) وا نمرر الكونتيكس وا المهمة او الانتنت رح تلقائيا كلاس jobintentservice call the onhandlejob to handle the task and run start service ---------- services هو كومبونت يستخدم لتشغيل مهام في الخلفية لمدة طويلة حتة لو ما تحتاج تفاعل وا ايضا يستخدم لعمل مهام حتة لو التطبيق ما مشتغل وا ضاهر لل مستخدم اكو انواع من السيرفس 1:started service هي عبارة عن اتصال داخلي يبدء من دالة startservice() يستخدم هذه الاتصال لكي يقوم بعملية اما تكمل كلها او تتوقف من قبل المستخدم او عبر قطع الاتصال مثل تحميل او تشغيل اغاني او تشغيل فيديو الخ 2:bound service:يسمح لي كومبونت ثانوين مثل اكتفتيس بل ربط وا تواصل مع السيرفسس عبر انترفيس يعني يفتح علاقة بين الكلاينت وا الخدمات bindservice()هذه الدالة تاخذ انتنت ال انتنت هوة ال تفاصيل مال السيرفسس وا ترجع ترو او فالس اذا ارجعت ترو رح ترجع كائن serviceconnection هذه الكائن يستخدم لل تحكم بل اتصال بين الكومبونت وا السيرفسس بي دالتين دالة الاولا تستخدم لمعالجة الاتصال onserviceconnected() وا دالة الثانية لمعالجة الاتصال اذا توقف اسم الدالة onservicedisconnected() - onStartCommand()