سنتعلم في هذا الجزء أساسيات تصميم الواجهات في الاندرويد حيث يتم ذلك بلغة التوصيف xml حيث يتم وضع العناصر وترتيبها على الشاشة كما ذكرنا في الدروس السابقة أنه يتم إضافة العناصر بطريقتين :
1- عن طريق السحب والافلات إلى الواجهة الرسومية.
2- عن طريق إضافة كود xml .
وسنركز في هذا الجزء على كيفية تصميم واجهات الاندرويد وكيفية وضع العناصر على الشاشة وطريقة ترتيبها.
وسنتعلم في هذا الجزء بعض المفاهيم وهي كمايلي:
1-ماهو الـ View وماهو الـ ViewGroup؟
1- ماهو الـ View وماهو الـ ViewGroup؟
2- تعرف على View structure In ِAndroid.
ولننظر بشكل أعمق إلى الشكل أعلاه حيث سيكون ملف xml للتصميم أعلاه كما في الكود ادناه:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:oriention="virtical"
>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="send"
/>
</LinearLayout>
في الجزاء الأول من الدرس كيفية وضع الـ views على الشاشة والتحكم في مواقعها على الشاشة , اما في هذا الجزاء سنتعلم كيفية التحكم في احجامها بالاعتماد على حجم شاشة الجهاز الذي يشتغل عليه التطبيق كما سنتعلم في هذا الدرس كيفية تصميم واحهة UI لتطبيق اندرويد تتلائم مع جميع احجام الشاشات المحتلفة .
كماهو معروف ان نظام الاندرويد مفتوح المصدر وهذا مايعني إن بإمكان الجميع استخدامه وتخصيصه وهكذا نجد الكثير من الشركات المصنعة للهواتف تتخذ من نظام الاندرويد كنظام تشغيل للهواتف التي تقوم بانتاجها كمثال على تلك الشركات Samsung و HTC و LG وغيرها من الشركات. وهذا يعني اننا سنجد احجام شاشات مختلفة ودقات مختلفة للشاشات .
ويبقى التحدي لمبرمج تطبيقات اندرويد كيف يقوم انتاج تطبيق يتلائم مع جميع مقاسات ودقات الشاشات وسنتعلم في هذا الدرس كيفية ذلك .
4- وحدات قياس أحجام المكونات Views في الاندرويد
1- ماهو حجم الشاشة Screen Size؟
2- ماهي كثافة الشاشة screen density ؟
وهو ما ستلاحظه فعليا عند انشاء أي مشروع اندرويد يكون هناك مجلد خاص بالصور وايقونات التطبيق كمافي الصورة ادناه:
الدائرة 1 : تمثل الكثافة العالية حيث تحتوي النقطة الواحدة من الشاشة على 9 بكسل.
الدائرة 2 : تمثل الكثافة المتوسطة حيث تحتوي النقطة الواحدة من الشاشة على 4 بكسل.
3- ماهو دقة الشاشة screen resoiution ؟
4- وحدات قياس أحجام المكونات Views في الاندرويد
5- ماهي الكثافة المعتمدة على البكسل density indenepdent pixle
6- ماهو scaled pixels
ماهي UI Controls
يوفر لنا الاندرويد مكتبية كبيرة من الـ Ui Controls التي نقوم باضافتها في واجهات تطبيقات الاندرويد Ui android وذلك للسماح للمستخدم بالتعامل مع تطبيقك وادخال البيانات والقيام بالوضائف المختلفة . شرح مفصل لعمل بعض من تلك العناصر UI Controls.
و سنتعرف في هذا الجزاء مايلي:-
1- ماهي عناصر التحكم UI Controls؟
2- شرح وضائف بعض من عناصر التحكم UI Controls.
3- كيفية الوصول إلى UI Controls.
1- ماهي عناصر التحكم UI Controls
2-EditText
يتم الوصول إلى العنصر بتحديد الرقم الفريد له كمايلي:-
1- تحديد الرقم الفريد له ID في الملف الخاص بالتصميم
android:id="@+id/text_id"
2- الوصول إلى الرقم الفريد برمجيا وذلك باستخدام دالة findViewById كما في الكود ادناه:-
TextView myText = (TextView) findViewById(R.id.text_id);
من الكود اعلاه حصلنا على اوبجكت من نوع TextView ويمكننا الان التحكم في خصائصه.
يتطرق هذا التمرين إلى عناصر واجهة متنوعة مثل زر اإلنتقاء (RadioButton ) , خانة الأختيار (CheckBox)
,القائمة المنسدلة (Spinner ) والشريط المنزلق (SeekBar)
وكيفية معالجة ألاحداث لهذه
العناصر برمجيا وانواع المستمعات (Listeners )المختلفة لهذا الغرض . الواجهة الخاصة بهذا التطبيق وأنواع ً العناصر المضافة موضحة في الشكل .
لتحديد مصفوفة النصوص (Array Stirng (التي يجب تعبئتها في القائمة المنزلقة (Spinner ,(أضف المصفوفة array_countries إلى ملف strings كما هو موضح باألسفل:
<resources> <string name="app_name">example_ul_control</string> <string name="action_settings">Settings</string> <!--هنا توضع المصفوفه --> <string-array name="countries_array"> <item>Palestine</item> <item>Egypt</item> <item>Algeria</item> <item>Syria</item> <item>Jordan</item> <item>Saudi Arabia</item> <item>Iraq</item> </string-array> </resources>
ملف تصميم الواجهة Layout الخاصة بهذا التمرين موضح باألسفل:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/studyTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="Where do you study?" /> <RadioGroup android:id="@+id/radioGroup" android:layout_width="wrap_content" android:layout_height="wrap_content" > <RadioButton android:id="@+id/ucasRadio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="UCAS" /> <RadioButton android:id="@+id/iugRadio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="IUGAZA" /> </RadioGroup> <TextView android:id="@+id/languageTextView" android:layout_marginTop="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="What languages can you speak?" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <CheckBox android:id="@+id/englishCheckBox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="English" /> <CheckBox android:id="@+id/arabicCheckBox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Arabic" /> </LinearLayout> <TextView android:id="@+id/CountryTextView" android:layout_marginTop="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Where are you from?" /> <Spinner android:id="@+id/countiresSpinner" android:layout_width="match_parent" android:layout_height="wrap_content" android:entries="@array/countries_array" /> <TextView android:id="@+id/happienessTextView" android:layout_marginTop="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Rate your level of happieness" /> <SeekBar android:id="@+id/happienessSeekBar" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/HappienessValue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="" /> </LinearLayout>
نلاحظ أن أزراء االنتقاء Buttons Radio تم جمعها في مجموعة واحدة RadioGroup وذلك حتى يتم اختيار القائمة في المصادر ً ً عنصر واحد منها فقط. الحظ أيضا spinner وكيف تم تعبئتها بالمصفوفة المحددة مسبقا يمكن )android:entries="@array/countries_array" الخاصية باستخدام وذلك ) strings.xml ملف) برمجيا Adapter في هذا الفصل(. في ً تعبئة القائمة spinner باستخدام المحولِ ً والذي سيتم الحديث عنه الحقا أسفل الواجهة تم استخدام عنصر عرض TextView وذلك لعرض القيمة الراجعة من العنصر SeekBar .بعد برمجيا )MainActivity )كما هو موضح: ً تجهيز الواجهة, سيتم اآلن معالجة أحداثها داخل الفعالية
//package com.alawirisaddam.example_ul_control;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.app.*;
import android.widget.*;
import android.widget.CompoundButton.*;
import android.widget.AdapterView.*;
import android.view.*;
import android.widget.SeekBar.*;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
// RadioGroup radioGroup = (RadioGroup) this.findViewById(R.id.radioGroup);
RadioGroup radioGroup = (RadioGroup) findViewById(R.id.radioGroup);
radioGroup.setOnCheckedChangeListener(new android.widget.RadioGroup.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if(checkedId == R.id.ucasRadio)
Toast.makeText(getApplicationContext(),
"Choice : UCAS", Toast.LENGTH_SHORT).show();
else if(checkedId == R.id.iugRadio)
Toast.makeText(getApplicationContext(),
"Choice : IUG", Toast.LENGTH_SHORT).show();
}
});
CheckBox englishCheckBox = (CheckBox) this.findViewById(R.id.englishCheckBox);
englishCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Toast.makeText(getApplicationContext(), buttonView.getText()+" is "+ isChecked, Toast.LENGTH_SHORT).show();
}
});
CheckBox arabicCheckBox = (CheckBox)this.findViewById(R.id.arabicCheckBox);
arabicCheckBox.setOnCheckedChangeListener(new
OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Toast.makeText(getApplicationContext(), buttonView.getText()+" is "+ isChecked, Toast.LENGTH_SHORT).show();
}
});
Spinner spinner = (Spinner) this.findViewById(R.id.countiresSpinner);
spinner.setOnItemSelectedListener(new OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView parent, View view, int position, long id) {
Toast.makeText(getApplicationContext(), parent.getItemAtPosition(position).toString(), Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView parent){}
});
final TextView happienessValue = (TextView) this.findViewById(R.id.HappienessValue);
SeekBar seekBar = (SeekBar) this.findViewById(R.id.happienessSeekBar); seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
happienessValue.setText(String.valueOf(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar){}
@Override
public void onStopTrackingTouch(SeekBar seekBar){}
});
}
}
يتم معالجة الاحداث لكل عنصر كما يلي: Buttons Radio :لتحديد أي زر إنتقاء (Button Radio )تم اختياره, نقوم باستخدام المستمع OnCheckedChangeListener.RadioGroup وإضافته إلى مجموعة األزرار (RadioGroup) أنظر سطر رقم 14.)عند حصول الحدث يتم تنفيذ الدالة ()onCheckedChanged والتي يمرر إليها رقم المعرف ID الخاص بالزر الذي تم اختياره حيث يتم طباعة رسالة تبين اإلختيار )أنظر الكود من سطر 08 إلى 36.) Boxes Check :لالستماع لحدث اختيار مربع اإلختيار (CheckBox ) نستخدم المستمع OnCheckedChangeListener.CompoundButton( أنظر سطور رقم 21 و 42 ,)وعند حصول الحدث يتم تنفيذ الدالة ()onCheckedChanged والتي يمرر إليها الكائن الخاص بمربع اإلختيارباإلضافة إلى قيمته )false-true )حيث يتم طباعة اسم مربع االختيار وقيمته )أنظر الكود من سطر 22 إلى 28 ,ومن سطر 45 إلى 51.) Spinner :نستخدم مستمع من نوع OnItemSelectedListener.AdapterView لمعالجة الحدث الخاص بهذا العنصر )أنظر سطر رقم 56 .)عند حصول الحدث يتم تنفيذ الدالة ()onItemSelected والتي من ضمن ما يمرر لها موقع العنصر الذي تم اختياره من القائمة. بمعرفة موقع العنصر يمكن الوصول له من القائمة عن طريق الدالة ()getItemAtPosition( أنظر الكود من سطر 60 إلى 65.) Bar Seek :يتم معالجة الغيرات على الشريط المنزلق (SeekBar (عن طريق إضافة مستمع من نوع OnSeekBarChangeListener( أنظر سطر رقم 74 .)عند حصول الحدث يتم تنفيذ الدالة ()onProgressChanged والتي يمرر لها القيمة الحالية للشريط )1-011 مثالً( باإلضافة إلى القيمة المنطقية ً fromUser والتي تحدد ما إذا كان تغير الشريط تم من المستخدم )true=fromUser ( أو برمجيا )false=fromUser .)في المثال الموضح يتم طباعة قيمة الشريط الممررة في عنصر من نوع TextView أنظر الكود من سطر 77 إلى 81. قائمة العرض (ListView) عرض العناصر في قائمة هو أحد التصاميم الشائعة بكثرة في تطبيقات الهواتف النقالة. يشاهد المستخدم عدد من العناصر ويستطيع االنتقال ألعلى القائمة وأسفلها down/up scroll كما هو موضح بشكل 3-3 . عند إختيار أحد عناصر القائمة يتم عادة تنفيذ إجراء مثل فتح فعالية جديدة. إضافة بيانات للقائمة (ListView) إلضافة بيانات للقائمة (ListView ) يتم عادةً استخدام المحول (Adapter) وهو كائن وسيط بين عنصر العرض وهو القائمة )ListView ) أو أي عنصر واجهة يتفرع من الفئة (class AdaperView ) وبين البيانات المعروضة. يتحكم المحول (Adapter ) في الوصول لبيانات القائمة, كما أنه مسؤول عن تحويل الب يانات المدخلة يمكن تضمينه داخل القائمة. فمثالً (Array ) للقائمة إلى عنصر عرض (View) , عند إداخل مصفوفة من النصوص String (لعرضها في القائمة, يقوم المحول (Adapter ) بتحويل كل عبارة نصية في المصفوفة إلى كائن من نوع (TextView ) والذي يتم إدراجه في القائمة, أي أن مصفوفة النصوص تتحول باستخدام المحول (Adapter (إلى مجموعة من عناصر العرض (TextView) المجمعة في قائمة من نوع )ListView
نهايه










