إنشاء عملية تنفيذ باستخدام واجهات برمجة التطبيقات القديمة
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
يناقش هذا الدرس كيفية إنشاء تطبيق يعكس واجهات برمجة التطبيقات الأحدث التي تتوافق مع الأجهزة القديمة.
تحديد الحل البديل
تتمثل المهمة الأكثر صعوبة في استخدام ميزات واجهة المستخدم الجديدة بطريقة متوافقة مع الإصدارات القديمة في اتخاذ قرار بشأن وتنفيذ حل (احتياطي) قديم لإصدارات النظام الأساسي القديمة. في كثير من الحالات، من الممكن تحقيق الغرض من هذه المكونات الأحدث لواجهة المستخدم باستخدام الميزات القديمة لإطار عمل واجهة المستخدم. مثلاً:
بشكل عام، لا يوجد حل واحد يناسب الجميع لنقل مكونات واجهة المستخدم الأحدث إلى الأجهزة القديمة. ضع في اعتبارك تجربة المستخدم: على الأجهزة القديمة، قد لا يكون المستخدمون على دراية بأنماط التصميم الجديدة ومكونات واجهة المستخدم. فكر في كيفية تقديم نفس الوظائف باستخدام عناصر مألوفة. وفي كثير من الحالات، لا داعي للقلق بشأن ذلك، سواء كانت مكونات واجهة المستخدم الجديدة بارزة في المنظومة المتكاملة للتطبيقات (مثل شريط الإجراءات) أو عندما يكون نموذج التفاعل بسيطًا للغاية (مثل طرق العرض بالتمرير السريع باستخدام ViewPager
).
تنفيذ علامات التبويب باستخدام واجهات برمجة تطبيقات قديمة
لإنشاء تنفيذ قديم لعلامات تبويب شريط الإجراءات، يمكنك استخدام TabWidget
وTabHost
(مع أنّه يمكن لأي منهما استخدام أداتَي Button
ذات التخطيط الأفقي بدلاً من ذلك). يمكنك تنفيذ ذلك في فئة تُسمى TabHelperEclair
وCompatTabEclair
، لأنّ هذا التنفيذ يستخدم واجهات برمجة التطبيقات التي تم طرحها بعد إصدار Android 2.0 (Eclair).
الشكل 1. رسم تخطيطي لفئة تنفيذ Eclair لعلامات التبويب
يخزِّن تنفيذ CompatTabEclair
سمات علامة التبويب، مثل نص علامة التبويب ورمزها في متغيّرات المثال، بسبب عدم توفُّر عنصر ActionBar.Tab
للتعامل مع مساحة التخزين هذه:
Kotlin
class CompatTabEclair internal constructor(val activity: FragmentActivity, tag: String) :
CompatTab(tag) {
// Store these properties in the instance,
// as there is no ActionBar.Tab object.
private var text: CharSequence? = null
...
override fun setText(resId: Int): CompatTab {
// Our older implementation simply stores this
// information in the object instance.
text = activity.resources.getText(resId)
return this
}
...
// Do the same for other properties (icon, callback, etc.)
}
Java
public class CompatTabEclair extends CompatTab {
// Store these properties in the instance,
// as there is no ActionBar.Tab object.
private CharSequence text;
...
public CompatTab setText(int resId) {
// Our older implementation simply stores this
// information in the object instance.
text = activity.getResources().getText(resId);
return this;
}
...
// Do the same for other properties (icon, callback, etc.)
}
يستفيد تنفيذ TabHelperEclair
من الطرق المتاحة في
التطبيق المصغَّر "TabHost
" لإنشاء "TabHost.TabSpec
"
ومؤشرات علامات التبويب:
Kotlin
class TabHelperEclair internal constructor(activity: FragmentActivity) : TabHelper(activity) {
private var tabHost: TabHost? = null
...
override fun setUp() {
// Our activity layout for pre-Honeycomb devices
// must contain a TabHost.
tabHost = tabHost ?: mActivity.findViewById<TabHost>(android.R.id.tabhost).apply {
setup()
}
}
override fun addTab(tab: CompatTab) {
...
tabHost?.newTabSpec(tab.tag)?.run {
setIndicator(tab.getText()) // And optional icon
...
tabHost?.addTab(this)
}
}
// The other important method, newTab() is part of
// the base implementation.
}
Java
public class TabHelperEclair extends TabHelper {
private TabHost tabHost;
...
protected void setUp() {
if (tabHost == null) {
// Our activity layout for pre-Honeycomb devices
// must contain a TabHost.
tabHost = (TabHost) mActivity.findViewById(
android.R.id.tabhost);
tabHost.setup();
}
}
public void addTab(CompatTab tab) {
...
TabSpec spec = tabHost
.newTabSpec(tag)
.setIndicator(tab.getText()); // And optional icon
...
tabHost.addTab(spec);
}
// The other important method, newTab() is part of
// the base implementation.
}
لديك الآن تطبيقان لـ CompatTab
وTabHelper
: إحداهما تعمل على الأجهزة التي تعمل بالإصدار 3.0 من نظام التشغيل Android أو الإصدارات الأحدث وتستخدم واجهات برمجة تطبيقات جديدة، والأخرى تعمل على الأجهزة التي تعمل بالإصدار 2.0 من نظام التشغيل Android أو الإصدارات الأحدث وتستخدم واجهات برمجة تطبيقات قديمة. سيناقش الدرس التالي استخدام طرق التنفيذ هذه في تطبيقك.
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["# Create an implementation with older APIs\n\nThis lesson discusses how to create an implementation that mirrors newer APIs yet supports older devices.\n\nDecide on a substitute solution\n-------------------------------\n\nThe most challenging task in using newer UI features in a backward-compatible way is deciding on and implementing an older (fallback) solution for older platform versions. In many cases, it's possible to fulfill the purpose of these newer UI components using older UI framework features. For example:\n\n- Action bars can be implemented using a horizontal [LinearLayout](/reference/android/widget/LinearLayout) containing image buttons, either as custom title bars or as views in your activity layout. Overflow actions can be presented under the device *Menu* button.\n\n- Action bar tabs can be implemented using a horizontal [LinearLayout](/reference/android/widget/LinearLayout) containing buttons, or using the [TabWidget](/reference/android/widget/TabWidget) UI element.\n\n- [NumberPicker](/reference/android/widget/NumberPicker) and [Switch](/reference/android/widget/Switch) widgets can be implemented using [Spinner](/reference/android/widget/Spinner) and [ToggleButton](/reference/android/widget/ToggleButton) widgets, respectively.\n\n- [ListPopupWindow](/reference/android/widget/ListPopupWindow) and [PopupMenu](/reference/android/widget/PopupMenu) widgets can be implemented using [PopupWindow](/reference/android/widget/PopupWindow) widgets.\n\nThere generally isn't a one-size-fits-all solution for backporting newer UI components to older devices. Be mindful of the user experience: on older devices, users may not be familiar with newer design patterns and UI components. Give some thought as to how the same functionality can be delivered using familiar elements. In many cases this is less of a concern---if newer UI components are prominent in the application ecosystem (such as the action bar), or where the interaction model is extremely simple and intuitive (such as swipe views using a [ViewPager](/reference/androidx/viewpager/widget/ViewPager)).\n\nImplement tabs using older APIs\n-------------------------------\n\nTo create an older implementation of action bar tabs, you can use a [TabWidget](/reference/android/widget/TabWidget) and [TabHost](/reference/android/widget/TabHost) (although one can alternatively use horizontally laid-out [Button](/reference/android/widget/Button) widgets). Implement this in classes called `TabHelperEclair` and `CompatTabEclair`, since this implementation uses APIs introduced no later than Android 2.0 (Eclair).\n\n**Figure 1.** Class diagram for the Eclair implementation of tabs.\n\nThe `CompatTabEclair` implementation stores tab properties such as the tab text and icon in instance variables, since there isn't an [ActionBar.Tab](/reference/android/app/ActionBar.Tab) object available to handle this storage: \n\n### Kotlin\n\n```kotlin\nclass CompatTabEclair internal constructor(val activity: FragmentActivity, tag: String) :\n CompatTab(tag) {\n\n // Store these properties in the instance,\n // as there is no ActionBar.Tab object.\n private var text: CharSequence? = null\n ...\n\n override fun setText(resId: Int): CompatTab {\n // Our older implementation simply stores this\n // information in the object instance.\n text = activity.resources.getText(resId)\n return this\n }\n\n ...\n // Do the same for other properties (icon, callback, etc.)\n}\n```\n\n### Java\n\n```java\npublic class CompatTabEclair extends CompatTab {\n // Store these properties in the instance,\n // as there is no ActionBar.Tab object.\n private CharSequence text;\n ...\n\n public CompatTab setText(int resId) {\n // Our older implementation simply stores this\n // information in the object instance.\n text = activity.getResources().getText(resId);\n return this;\n }\n\n ...\n // Do the same for other properties (icon, callback, etc.)\n}\n```\n\nThe `TabHelperEclair` implementation makes use of methods on the\n[TabHost](/reference/android/widget/TabHost) widget for creating [TabHost.TabSpec](/reference/android/widget/TabHost.TabSpec)\nobjects and tab indicators: \n\n### Kotlin\n\n```kotlin\nclass TabHelperEclair internal constructor(activity: FragmentActivity) : TabHelper(activity) {\n\n private var tabHost: TabHost? = null\n ...\n\n override fun setUp() {\n // Our activity layout for pre-Honeycomb devices\n // must contain a TabHost.\n tabHost = tabHost ?: mActivity.findViewById\u003cTabHost\u003e(android.R.id.tabhost).apply {\n setup()\n }\n }\n\n override fun addTab(tab: CompatTab) {\n ...\n tabHost?.newTabSpec(tab.tag)?.run {\n setIndicator(tab.getText()) // And optional icon\n ...\n tabHost?.addTab(this)\n }\n }\n // The other important method, newTab() is part of\n // the base implementation.\n}\n```\n\n### Java\n\n```java\npublic class TabHelperEclair extends TabHelper {\n private TabHost tabHost;\n ...\n\n protected void setUp() {\n if (tabHost == null) {\n // Our activity layout for pre-Honeycomb devices\n // must contain a TabHost.\n tabHost = (TabHost) mActivity.findViewById(\n android.R.id.tabhost);\n tabHost.setup();\n }\n }\n\n public void addTab(CompatTab tab) {\n ...\n TabSpec spec = tabHost\n .newTabSpec(tag)\n .setIndicator(tab.getText()); // And optional icon\n ...\n tabHost.addTab(spec);\n }\n\n // The other important method, newTab() is part of\n // the base implementation.\n}\n```\n\nYou now have two implementations of `CompatTab` and `TabHelper`: one that works on devices running Android 3.0 or later and uses new APIs, and another that works on devices running Android 2.0 or later and uses older APIs. The next lesson discusses using these implementations in your application."]]