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

واجهة المستخدم في أندرويد وأساسيات التعامل مع عناصرها المختلفة


أحمد النوبي

بعد أن أنشأنا أول مشروع في Android Studio وقمنا بتجربة التطبيق على المحاكي سنتعلم الآن أساسيات التعامل مع واجهة المستخدم وكيفية إنشاء العناصر المختلفة بداخلها.

android-interface.png

طرق إنشاء واجهة المستخدم لتطبيق أندرويد

في نظام تشغيل أندرويد هناك طريقتان لإنشاء واجهة المستخدم الخاصة بالتطبيق:

  1. التعريف في الملف الخاص بها layout باستخدام لغة XML: وتتميز هذه الطريقة بأنها تقوم بفصل عناصر الواجهة عن الشيفرات البرمجية بلغة الجافا والتي تحدد وظيفة التطبيق الأصلية مما يُسهل عملية تطوير التطبيقات واكتشاف الأخطاء وتصحيحها وتجعل التطبيق أكثر مرونة لدعم أحجام الشاشات المختلفة واللغات المختلفة.
  2. تعريف عناصر واجهة المستخدم باستخدام الشيفرات البرمجية بلغة الجافا حيث تتكون الواجهة وقت تشغيل التطبيق وعمله لدى المستخدم.

كما يمكنك استخدام هاتين الطريقتين معًا عن طريق تعريف العناصر في ملف layout وباستخدام الشيفرة البرمجية تقوم بتغيير خصائصها بناءً على تفاعل المستخدم مع هذه العناصر، وتلك هي الطريقة التي سنقوم باستخدامها.

عناصر واجهة المستخدم

تنقسم عناصر واجهة المستخدم إلى نوعين View و ViewGroup:

  • View هو عنصر يقوم برسم شيء ما على الشاشة حيث يستطيع المستخدم التفاعل مع هذا الشيء.
  • ViewGroup هو حاوية غير مرئية تستطيع أن تحمل بداخلها العناصر المكوَنة للواجهة. ويتميز كل نوع من ViewGroup بطريقة فريدة ومختلفة لعرض العناصر الأخرى بداخله وتُسمى العناصر المتواجدة داخل ViewGroup بالأبناء.

يمكن أن يحتوي عنصر ViewGroup على عناصر من النوع ViewGroup أيضًا أو من النوع View وذلك للوصول إلى التصميم المنشود لواجهة المستخدم كما توضح الصورة التالية:

img1.png

يوفر أندرويد للمطورين مجموعة من Views و ViewGroup الجاهزة والتي تقوم بالوظائف الشائعة في التطبيقات.

أمثلة على ViewGroup

  • Linear Layout: ويتم ترتيب العناصر بداخله في اتجاه واحد إما بشكل أفقي أو رأسي.
  • Relative Layout: ويتم ترتيب العناصر بداخله نسبة إلى عنصر أخر ويتم استخدامه عند صنع واجهة أكثر تعقيدا يصعُب معها استخدام Linear Layout.

أمثلة على View

  • Button
  • TextView
  • ImageView

أساسيات تصميم الواجهات باستخدام XML

توفر لغة XML طريقة سهلة وسريعة لصنع واجهة المستخدم وتتشابه مع طريقة صناعة صفحات الويب باستخدام HTML.

كما ذكرنا سابقًا تتواجد الملفات الخاصة بالواجهة في مجلد res/layout بامتداد XML.

يجب أن تحتوي ملفات XML على عنصر يسمى root ويعتبر هذا العنصر الحاوية الرئيسية لباقي العناصر ويكون هذا العنصر إما ViewGroup أوView، كما يجب أن يحتوي على XML namespace وهو من المعايير القياسية الخاصة بـ XML. تعريف الـ namespace بسيط وثابت لكل الـ root elements ويكون على النحو التالي

xmlns:android="http://schemas.android.com/apk/res/android"

وبعد تعريف الـ root element يمكنك بعدها إضافة عناصر أخرى لاستكمال واجهة المستخدم. وفي أغلب التطبيقات يكون الـ root من النوع ViewGroup لقدرته على إضافة أبناء له، على عكس View والذي لا يمكن أن يحتوي على أبناء.

يتكون كل عنصر من عناصر XML من وسم الفتح <ElementName>، ووسم الغلق <ElementName/>. وبين وسم الفتح والغلق يتم وضع العناصر الأخرى والتي تعتبر أبناء ViewGroup، وبما أنه لا يوجد للعنصر View لأبناء فيمكن الاستغناء فيه عن وسم الغلق واستخدام وسم الغلق الذاتي </ElementName>.

لتوضيح الأمر أكثر سنقوم بصنع واجهة مستخدم مشابهة لتطبيق أهلًا بالعالم Hello World.

  • قم بفتح الملف content_main.xml المتواجد بداخل المجلد res/layout، ثم قم بمسح كافة الشيفرة المكتوبة.
  • بعد عنصر root الخاص بالواجهة أضف عنصر ViewGroup من نوع LinearLayout كالتالي:
<LinearLayout>
  • قم بتحديد XML namespace الخاص بالعنصر LinearLayout:
<LinearLayout
xmlns:android=http://schemas.android.com/apk/res/android
>

لكل عنصر من عناصر واجهة المستخدم سواء كان View أو ViewGroup العديد من الخصائص والتي يمكن التحكم بها وتخصيصها عن طريق XML أو عن طريق شيفرة الجافا وقد تكون هذه الخصائص خاصة بهذا العنصر فقط أو خصائص مشتركة لدى أكثر من عنصر.

ومن الخصائص الهامة تحديد العرض والارتفاع الخاصين بالعنصر، ولتحديد العرض للعنصر نستخدم الخاصية layout_width:

android:layout_width="Value"

ونستبدل Value بقيمة العرض، وهناك عدة طرق لتحديد قيمة العرض، فيمكن تحديدها عن طريق قيم معرَفة مسبقًا للنظام مثل "match_parent" وتعني أن يكون عرض العنصر نفس عرض العنصر الأب، وإذا كان العنصر الأب هو root فالأب هنا المقصود به شاشة الهاتف.

وباستخدام نفس الطريقة يتم تحديد الارتفاع الخاص بالعنصر عن طريق خاصية layout_height:

android:layout_height ="Value"

ليصبح الشكل النهائي للعنصر:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

</LinearLayout>

لاحظ أنه يتم تحديد كافة الخصائص الخاصة بالعنصر داخل وسم الفتح ويتم أيضًا وضع XML namespace معهم.

  • سنقوم بإضافة عنصر أخر للواجهة من نوع View وهو TextView والذي يستطيع أن يحمل بداخله نصًا ويمكن للمستخدم قراءته ولا يمكنه تغييره:
<TextView />
  • سنقوم بتحديد الخصائص الخاصة بهذا العنصر وكما ذكرنا أن خاصتيَ العرض والارتفاع من الخصائص الهامة التي ينبغي تحديدها لكافة العناصر.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

كان من الممكن استخدام قيمة "match_parent" ولكننا قمنا باستخدام "wrap_content" والتي تعني أن يكون العرض أو الارتفاع يشغل القدر المطلوب للنص فقط، أما إذا استخدمنا "match_parent" فسيشغل العنصر كل المساحة الخاصة بالأب والذي هو LinearLayout والذي يشغل مساحة الشاشة كلها كما حددنا ذلك سابقًا.

  • لتحديد النص المطلوب كتابته داخل العنصر، نقوم بإضافة السطر التالي:
android:text="Hello World!"
  • هذا هو الشكل الكلي لملف XML:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

  <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Hello World!" />
</LinearLayout>

الآن قم بتشغيل التطبيق على المحاكي وستجده يعمل بالشكل المطلوب.

img2.png

ملاحظات

  1. العنصر TextView متواجد بين وسميَ الفتح والغلق الخاصين بـ LinearLayout ويُعتبر TextView ابنًا لـ LinearLayout.
  2. يستخدم العنصر TextView وسم الغلق الذاتي.
  3. يتم تحديد الخصائص للعنصر داخل وسم الفتح الخاص به فقط.

التطبيق الثاني

سنقوم بتطوير المثال السابق واستخدام عناصر أخرى في التطبيق لصنع واجهة مثل الصورة التالية:

img3.png

الاختلاف هنا في إضافة عنصر جديد للواجهة وهو Button.

  • لإضافة هذا العنصر يتم استخدام العنصر </ Button> وإضافته داخل LinearLayout.
  • نقوم بتحديد الطول، الارتفاع والنص الخاص بالزر كالتالي:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me"/>

سيظهر الزر بجانب النص السابق:

img4.png

ولتغيير موضع الزر يجب تغيير اتجاه العناصر داخل عنصر LinearLayout، ولتغيير الاتجاه للرأسي بدلًا من الأفقي نستخدم الخاصية orientation:

android:orientation="vertical"

حيث أن الاتجاه يكون أفقيًا بشكل افتراضي.

ليصبح ملف XML على النحو التالي:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

  <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Hello World!" />

  <Button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Click me"/>
  
</LinearLayout>

ملاحظات

  1. أي عنصر من النوع View يستخدم وسم الغلق الذاتي لأنه لا يستطيع أن يحتوي على أبناء أو عناصر أخرى بداخله.
  2. إذا قمت بكتابة العنصر Button أولًا بداخل LinearLayout ثم العنصر TextView سيتم تغيير الترتيب في الواجهة أيضًا.

img5.png

التطبيق الثالث

يحتوي هذا التطبيق على نص "Android Image" وصورة للأندرويد وزر يتم ترتيبها بشكل رأسي.

img6.png

  • لصنع واجهة المستخدم سنختار LinearLayout كعنصر root وتغيير الاتجاه الخاص به للرأسي.
  • نقوم بعدها بإضافة عنصر TextView وكتابة النص الخاص به، ولكن يمكن ملاحظة أن حجم الخط الخاص بالنص أكبر من الأمثلة السابقة لذا يجب تغيير حجم الخط عن طريق الخاصية textSize:
android:textSize="40sp"

ويتم تحديد الخط بوحدة "sp" وهي وحدة خاصة في نظام أندرويد لتحديد حجم الخط دون الاعتماد على كثافة البكسل المكوَنة للشاشة ليظهر النص دائمًا بنفس الحجم باختلاف أحجام شاشات الهواتف.

  • لتغيير موضع النص ليكون في منتصف الواجهة نقوم باستخدام خاصية الجاذبية layout_gravity:
android:layout_gravity="center"
  • نقوم بإضافة العنصر ImageView لعرض الصور وتحديد الطول والارتفاع كالسابق، ولتحديد الصورة المعروضة بداخله نقوم بوضع الصورة في الملف res/drawable وعرضها داخل العنصر باستخدام الخاصية src:
android:src="@drawable/andimg"

تستخدم @ للإشارة إلى عنصر داخل الملف وبعدها يتم كتابة اسم الملف وهو drawable ثم تحديد اسم الصورة المتواجدة بداخله.

  • نضيف بعدها العنصر Button ونقوم بتحديد النص الخاص به مع ملاحظة أن العرض الخاص به يستغل كافة مساحة الشاشة وليس على قدر المحتوى فقط.

ليصبح ملف XML على النحو التالي:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

  <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Android Image"
  android:textSize="40sp"
  android:layout_gravity="center" />

  <ImageView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:src="@drawable/andimg"/>

  <Button
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="Say Hi"/>

</LinearLayout>

التطبيق الرابع

نريد في هذا التطبيق صُنع واجهة مركبة كما في الصورة التالية:

img7.png

  • سيكون الـ root مثل الأمثلة السابقة من النوع LinearLayout ولكن هل اتجاه العناصر بداخله أفقي أم رأسي؟ ستجد العناصر متواجدة في الاتجاهين.
  • لصنع هذه الواجهة سنستخدم أكثر من ViewGroup من النوع LinearLayout ونغير اتجاهاتها لصنع الشكل المطلوب كما في الصورة التالية:

img8.png

سيكون العنصر  root من النوع LinearLayout والاتجاه بداخله رأسي، ويحتوي على LinearLayout آخر الاتجاه بداخله أفقي ونضع بداخله العنصرين المتجاورين كما في الصورة السابقة.

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

  <LinearLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="horizontal">

  </LinearLayout>

</LinearLayout>
  • نضع العنصرين ImageView و EditText داخل العنصر LinearLayout الثاني.
  • نقوم بتحديد العرض والارتفاع واختيار الصورة من ملف drawable للعنصر ImageView مثل ما فعلنا في التطبيق السابق،
  • وبالنسبة للعنصر الآخر EditText والذي يٌستخدم لإدخال نص من المستخدم، نقوم بتحديد عرضه وارتفاعه، بالإضافة إلى عرض نص يعبر عن المحتوى الذي يجب على المستخدم إدخاله باستخدام الخاصية hint:
android:hint="Write your name here"
  • نُضيف العنصر الأخير من النوع Button داخل LinearLayout الأول ولوضعه جهة اليمين نستخدم الخاصية layout_gravity:
android:layout_gravity="right"

ليُصبح ملف XML على الشكل التالي:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

  <LinearLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="horizontal">

    <ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_launcher"/>

    <EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Write your name here"/>
  </LinearLayout>

  <Button
  android:layout_width="wrap_content"
  android:layout_height="70dp"
  android:text="Done"
  android:layout_gravity="right"/>
  
</LinearLayout>

ملاحظات

  1. تم تحديد الارتفاع الخاص بـ LinearLayout الثاني بـ "wrap_content" حتى يشغل الارتفاع الخاص بالعناصر فقط ولا يشغل مساحة الشاشة كلها.
  2. تم استخدام طريقة مختلفة لتحديد الارتفاع الخاص بـالعنصر Button، وتستخدم هذه الطريقة في حالة لم نرد استخدام القيم المعرَفة داخل النظام مثل "match_parent" أو "wrap_content" واستخدام قيم مختلفة. وتُستخدم الوحدة "dp" كوحدة لتحديد الأبعاد دون الاعتماد على كثافة البكسل المكوَنة للشاشة ليظهر العنصر بنفس الأبعاد دائمًا باختلاف أحجام شاشات الهواتف.

التطبيق الخامس

هناك طريقة أخرى لإنشاء واجهة المستخدم كما في التطبيق السابق، حيث نقوم باختيار root من النوع RelativeLayout للوصول لنفس الشكل أيضًا كما في الصورة السابقة.

img9.png

في RelativeLayout يتم وضع العناصر نسبة إلى عناصر أخرى متواجدة لذلك ينبغي تحديد لكل عنصر ID مميز له لأن عند وضع عنصرين من نفس النوع (Button مثلا) سيكون اسم كل منهما Button ولا نستطيع عندها التفريق بين الزر الأول أو الثاني وللتفرقة بينهم يتم استخدام خاصية id:

android:id="@+id/btn1"

ويتم كتابة ID الخاص بالعنصر بعد كلمة /id+@ ويكون هذا ID مميز لهذا العنصر فقط ولا يتشابه معه عنصر آخر.

وهناك استخدام آخر لـ ID عند التحكم في العناصر باستخدام شيفرة الجافا.

وبهذا يصبح ملف XML على الشكل التالي:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

  <ImageView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:src="@drawable/ic_launcher"
  android:id="@+id/img" />

  <EditText
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:hint="Write your name here"
  android:id="@+id/edttxt"
  android:layout_toRightOf="@+id/img" />
  
  <Button
  android:layout_width="wrap_content"
  android:layout_height="70dp"
  android:text="Done"
  android:id="@+id/btn1"
  android:layout_below="@+id/edttxt"
  android:layout_alignParentRight="true"/>
  
</RelativeLayout>

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

ملاحظات

  1. تم تحديد ID خاص لكل العناصر.
  2. هناك بعض الخصائص التي تحدد موضع كل عنصر بالنسبة لعنصر آخر.

مثل الخاصية layout_toRightOf المستخدمة للعنصر EditText وذلك لوضعه بجانب العنصر ImageView جهة اليمين:

android:layout_toRightOf="@+id/img"

والخاصيتين layout_below و layout_alignParentRight المستخدمتين مع العنصر Button وذلك لوضعه أسفل العنصر EditText و بمحاذاة الشاشة من جهة اليمين:

android:layout_below="@+id/edttxt"
android:layout_alignParentRight="true"

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


تفاعل الأعضاء

أفضل التعليقات

السلام عليكم

يسعدني ان اكون اول الماريين على موضوعك القيم

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

رابط هذا التعليق
شارك على الشبكات الإجتماعية

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

#شكرا 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

شكرا على الدرس  الأكثر من رائع  ... لدي سؤال اتمنى أن تجيبني عليه !

يبدو ان http://schemas.android.com/apk/res/android  عبارة عن رابط  .. لكن لماذا عندما اقوم بوضعه في المتصفح لا يعطيني أي نتيجة . أي أن هذا الرابط غير موجود أصلا .. ما تعقيبك أخي حول هذا الأمر   !!! 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

السلام عليكم

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

 

  • شكرا جزيلا لك استاذ اذا اردت من تطبيق خدمة فأنا لها
  • المثال الخامس :
  • exempel 5.PNG
رابط هذا التعليق
شارك على الشبكات الإجتماعية



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

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

زائر
أضف تعليق

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

  Only 75 emoji are allowed.

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

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

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


×
×
  • أضف...