سلسلة تعلم الأندرويد – الحلقة العاشرة: واجهة القائمة الرسومية (متطّور)

السلام عليكم
شرحت في الحلقة السابقة كيفية وجود طريقتين لإنشاء الواجة الرسومية للقائمة، وقمت بشرح الطريق الأبسط في تلك الحلقة. كانت تلك الطريقة تعتمد أن العناصر الموجود في القائمة تحتوي محتوىً من نوع واحد متشابه. فمثلاً، قائمة جهات الاتصال تحتوي على أسماء الأشخاص، وقائمة الدول تحتوي على أسماء الدول في كل عنصر من القائمة. كما لاحظنا في الطريقة السابقة أيضاً أن المثال يستعمل واجهة نصية واحدة ويتم استعمالها من قبل الأندرويد لكل عنصر في القائمة. هذا يفيد الأندرويد بالقيام بعملية تكرير “Recycle” للواجهة النصية حتى يتم الاستفادة منها بالشكل الأقصى. ولكن ماذا لو أردنا إضافة عنصر مختلفة عن بقية عناصر القائمة؟ كأن نضع اسم القارة لمجموعة من الدول أو الحروف الهجائية قبل مجموعة من جهات الاتصال. هذا ما سوف أقوم بشرحه في هذه الحلقة.

النتيجة النهائية للحلقة سوف تكون بهذا الشكل (سوف نقوم بالبناء على المثال السابق):

الواجهة الرسومية للقائمة

كما في الدرس السابق، سوف نحتاج إلى كلاس النشاط Activity لعرض القائمة، كلاس محوّل Adapter لربط الواجهة الرسومية للقائمة بالمعلومات. سوف نقوم بإنشاء كلاس فرعي subcalss من كلاس ArrayAdapter والذي يقوم بإخذ مصفوفة وربطها بالقائمة.

ملاحظة: لمعرفة كيفية إنشاء مشروع على برنامج الـ Eclipse يمكنك مراجعة الدروس الأولى في هذه السلسلة.

في البداية نقوم بإنشاء كلاس النشاط:

public class HelloAndroidActivity extends ListActivity {
    /** Called when the activity is first created. */
    @Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		/* على عكس المثال السابق، نقوم هنا بتحويل الدالة إلى كلاس المحوّل بدلاً أن ننشأه مباشرة من هنا*/
		setListAdapter(new HelloArrayAdapter(this, COUNTRIES));

		ListView lv = getListView();
		lv.setTextFilterEnabled(true);

		lv.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				// When clicked, show a toast with the TextView text
				Toast.makeText(getApplicationContext(),
						((TextView) view).getText(), Toast.LENGTH_SHORT).show();
			}
		});
    }
}

ومن ثم نقوم بإنشاء كلاس فرعي من ArrayAdapter:

/**
 * يقوم هذا الكلاس بعملية ربط المعلومات في المصفوفة الخاصة بالدول إلى الواجهة
 * الرسومية الخاصة بالقائمة
 */
public class HelloArrayAdapter extends ArrayAdapter<String> {
	Context context;
	private LayoutInflater inflater;
	String[] values;

	/* هذه متغيرات ساكنة سوف نحتاجها في الدوال لاحقاً */
	private static final int TYPE_MAX_COUNT = 2;
	private static final int TYPE_DIVISION = 0;
	private static final int TYPE_TEXT = 1;

	/**
	 * المشيدّدة الخاصة بالكلاس، تقوم بأخذ السياق والمصفوفة كمتغيرات في الدالة
	 * نقوم فيها أيضاً بالقيام بالعمليات الرئيسية كإنشاء كائن الـ infalter والذي
	 * يقوم بعملية إنشاء الواجهات الرسومية ومن ثم السماح لك بالتعديل عليها كما
	 * تشاء
	 *
	 * @param mContext
	 *            the m context
	 * @param mValues
	 *            the m values
	 */
	public HelloArrayAdapter(Context mContext, String[] mValues) {
		super(mContext, R.layout.list_item, mValues);
		inflater = (LayoutInflater) mContext
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		context = mContext;
		values = mValues;
	}

	/*
	 * في هذه الدالة المتفرعة عن الكلاس الأصلي نقوم بتحديد نوع الصف، في هذا
	 * المثال نقوم بالتأكد من أنه من مضاعفات العدد خمسة حتى نستطيع وضع فاصل بعد
	 * كل أربعة صفوف
	 */
	@Override
	public int getItemViewType(int position) {
		if ((position % 5) == 0) {
			return TYPE_DIVISION;
		} else {
			return TYPE_TEXT;
		}

	}

	/*
	 * هنا نحدد عدد الأنواع الموجودة عندنا من الصفوف في هذا المثال يوجد لدينا
	 * نوعين من الصفوف: النص والفاصل تسهل هذه العملية على المحوّل القيام بعمله
	 * بطريقة أفضل
	 */

	@Override
	public int getViewTypeCount() {
		return TYPE_MAX_COUNT;
	}

	/*
	 * هذه الدالة هي الدالة الأساسية التي تقوم بعملية التعديل على الواجهة
	 * list_item الرسومية الخاصة بكل صف. أي.
	 */
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {

		View rowView;
		int type = getItemViewType(position);

		// هنا نتأكد من نوع الصف ومن ثم نقوم بإخبار المحوّل عن
		// الواجهة الرسومية التي يجب أن يستعملها لعرض الصف والمحتويات
		// التي بداخله
		if (type == TYPE_TEXT) {
			rowView = inflater.inflate(R.layout.list_item, parent, false);
			TextView textView = (TextView) rowView.findViewById(R.id.list_text);
			textView.setText(values[position]);
		} else {
			rowView = inflater.inflate(R.layout.list_division, parent, false);
		}
		return rowView;
	}
}

وأخيراً الواجهات الرسومية النصية التي استخدمت لعرض الفاصل والنص العادي:
ملف list_division.xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="35dp"
    android:background="#C2C2C2"
    android:gravity="center"
    android:padding="2dp"
    android:text="فاصل"
    android:textSize="16sp" >

</TextView>

ملف list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_text"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp"
    android:textSize="16sp" >
</TextView>

لتحميل المشروع جاهزاً:

تعليق

  1. ياقوت

    بارك الله فيكم و في هذا المجهود الرائع
    مصدر عربي مميز في تعلم الاندرويد .. و سيكون محطة متابعتي من الان فأنا مبتدئة في هذا المجال

    لدي سؤال بخصوص دعم اللغة العربية في نصوص البرامج كيف يتم ذلك ؟
    تقبلوا تحياتي و شكري الجزيل

    • عبد القهار الحسني

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

      • ياقوت

        شكرا جزيلا و جزاك الله كل خير
        فقط اود التنبيه بأنني اقصد العربية في عرض بيانات من الداتابيس sql إلى البرنامج الذي قمت ببرمجته
        انتظر دروسك و متابعة معك ..بارك الله فيك

        • عبد القهار الحسني

          بالنسبة لقواعد البيانات فهي تدعم العربية تلقائياً .. كل ما عليك هو استعمال ترميز UTF-8.

          أهلاً وسهلاً بك هنا.

اترك تعليقاً

الحقول المطلوبة موسومة بالعلامة *.