طرق التنفيذ
نقدّم لك Cahier: نموذج جديد لتطبيق Android على GitHub يتيح الإنتاجية والإبداع على الشاشات الكبيرة
قراءة لمدة 11 دقيقة
أصبحت Ink API متاحة الآن في الإصدار التجريبي وهي جاهزة للدمج في تطبيقك. وقد تحقّق هذا الإنجاز بفضل الملاحظات القيّمة التي قدّمها المطوّرون، ما أدّى إلى تحسينات مستمرة في أداء واجهة برمجة التطبيقات واستقرارها وجودتها المرئية.
تستخدم تطبيقات Google، مثل مستندات Google وPixel Studio وصور Google وملف PDF في Chrome وأداة إنشاء التأثيرات في YouTube والميزات الفريدة على Android، مثل دائرة البحث، أحدث واجهات برمجة التطبيقات.
للاحتفال بهذا الإنجاز، يسرّنا الإعلان عن إطلاق Cahier، وهو نموذج لتطبيق شامل لتدوين الملاحظات تم تحسينه لأجهزة Android بجميع أحجامها، وخاصةً الأجهزة اللوحية والهواتف القابلة للطي.
ما هو تطبيق Cahier؟
Cahier (تعني "دفتر" بالفرنسية) هو نموذج تطبيق مصمَّم لتوضيح كيفية إنشاء تطبيق يتيح للمستخدمين تسجيل أفكارهم وتنظيمها من خلال الجمع بين النصوص والرسومات والصور.
يمكن أن يكون النموذج المرجعية الأساسية لتحسين إنتاجية المستخدمين وإبداعهم على الشاشات الكبيرة. ويعرض هذا التطبيق أفضل الممارسات لإنشاء مثل هذه التجارب، ما يسرّع من فهم المطوّرين لواجهات برمجة التطبيقات والتقنيات الفعّالة ذات الصلة واستخدامها. توضّح لك هذه المشاركة الميزات الأساسية في Cahier وواجهات برمجة التطبيقات الرئيسية وقرارات التصميم التي تجعل العيّنة مرجعًا رائعًا لتطبيقاتك.
تشمل الميزات الرئيسية المعروضة في النموذج ما يلي:
- إنشاء ملاحظات متعددة الاستخدامات: يوضّح هذا القسم كيفية تنفيذ نظام مرن لإنشاء المحتوى يتيح استخدام تنسيقات متعددة ضمن ملاحظة واحدة، بما في ذلك النصوص والرسومات الحرة والمرفقات المصوّرة.
- أدوات الكتابة بالحبر الإبداعية: تنفِّذ تجربة رسم عالية الأداء ومنخفضة وقت الاستجابة باستخدام Ink API. يقدّم النموذج مثالاً عمليًا على دمج فُرش مختلفة وأداة اختيار الألوان ووظيفة التراجع/الإعادة وأداة الممحاة.
- دمج المحتوى المرن باستخدام ميزة السحب والإفلات: يوضّح هذا المثال كيفية التعامل مع المحتوى الوارد والصادر باستخدام ميزة السحب والإفلات. ويشمل ذلك قبول الصور التي يتم إسقاطها من تطبيقات أخرى والسماح للمستخدمين بسحب المحتوى من تطبيقك لمشاركته بسلاسة.
- تنظيم الملاحظات: يمكنك وضع علامة "مفضّلة" على الملاحظات للوصول إليها بسرعة. فلتر العرض للحفاظ على التنظيم
- بنية تعمل بلا إنترنت أولاً: تم تصميم التطبيق ببنية تعمل بلا إنترنت أولاً باستخدام Room، ما يضمن حفظ جميع البيانات على الجهاز وإبقاء التطبيق يعمل بكامل وظائفه بدون اتصال بالإنترنت.
- إمكانات قوية لدعم النوافذ المتعددة وفتح نسختين من التطبيق: توضّح هذه الميزة كيفية دعم فتح نسختين من التطبيق، ما يسمح بتشغيل تطبيقك في نوافذ متعددة ليتمكّن المستخدمون من العمل على ملاحظات مختلفة جنبًا إلى جنب، ما يعزّز الإنتاجية والإبداع على الشاشات الكبيرة.
- واجهة مستخدم متكيّفة لجميع الشاشات: تتكيّف واجهة المستخدم بسلاسة مع أحجام الشاشات واتجاهاتها المختلفة باستخدام ListDetailPaneScaffold وNavigationSuiteScaffold لتوفير تجربة مستخدم محسّنة على الهواتف والأجهزة اللوحية والهواتف القابلة للطي.
- التكامل العميق مع النظام: يقدّم هذا المستند دليلاً حول كيفية جعل تطبيقك هو تطبيق تدوين الملاحظات التلقائي على Android 14 والإصدارات الأحدث من خلال الاستجابة لطلبات intent الملاحظات على مستوى النظام، ما يتيح إمكانية تسجيل المحتوى بسرعة من نقاط دخول مختلفة في النظام.
مصمّم لزيادة الإنتاجية والإبداع على الشاشات الكبيرة
في الإصدار الأوّلي، سنركّز الإعلان على بعض الميزات الأساسية التي تجعل Cahier مصدرًا رئيسيًا للتعلم في حالات استخدام الإنتاجية والإبداع.
أساس التكيّف
تم تصميم Cahier ليكون قابلاً للتكيّف من البداية. يستخدم النموذج مكتبة material3-adaptive، وتحديدًا ListDetailPaneScaffold وNavigationSuiteScaffold، لتكييف تصميم التطبيق بسلاسة مع أحجام الشاشات واتجاهاتها المختلفة. هذه ميزة أساسية لأي تطبيق Android حديث، ويقدّم تطبيق Cahier مثالاً واضحًا على كيفية تنفيذها بفعالية.
واجهة مستخدم Cahier التكيُّفية المستندة إلى مكتبة Material 3 Adaptive
عرض واجهات برمجة التطبيقات وعمليات الدمج الرئيسية
يركّز النموذج على عرض واجهات برمجة تطبيقات إنتاجية فعّالة يمكنك الاستفادة منها في تطبيقاتك، بما في ذلك:
نظرة عن كثب على واجهات برمجة التطبيقات الرئيسية
لنتعرّف بالتفصيل على اثنتين من واجهات برمجة التطبيقات الأساسية التي يدمجها تطبيق Cahier لتقديم تجربة تدوين ملاحظات من الدرجة الأولى.
إنشاء تجارب كتابة بالحبر بسلاسة باستخدام Ink API
تتيح إمكانية استخدام القلم تحويل الأجهزة ذات الشاشات الكبيرة إلى دفاتر رقمية ودفاتر رسم. لمساعدتك في إنشاء تجارب كتابة بالحبر بسلاسة وبشكل طبيعي، جعلنا واجهة برمجة التطبيقات Ink API حجر الزاوية في النموذج. تسهّل واجهة برمجة التطبيقات Ink API إنشاء خطوط حبر جميلة وعرضها وتعديلها مع توفير أفضل وقت استجابة في فئتها.
توفّر Ink API بنية معيارية، ما يتيح لك تخصيصها لتناسب حزمة تطبيقك واحتياجاته المحدّدة. تتضمّن وحدات واجهة برمجة التطبيقات ما يلي:
-
وحدات الإنشاء (إنشاء - طرق العرض): تعالج هذه الوحدات إدخال الحبر في الوقت الفعلي لإنشاء ضربات سلسة بأقل وقت استجابة يمكن أن يوفّره الجهاز.
- في DrawingSurface، يستخدم تطبيق Cahier العنصر القابل للإنشاء InProgressStrokes الذي تم تقديمه حديثًا للتعامل مع إدخال القلم أو اللمس في الوقت الفعلي. هذه الوحدة مسؤولة عن تسجيل أحداث المؤشر وعرض ضربات الحبر الرطب بأقل وقت استجابة ممكن.
- وحدة الضربات: تمثّل الإدخال بالحبر وتمثيله المرئي. عندما ينتهي المستخدم من رسم خط، تقدّم الدالة onStrokesFinished المتصلة كائن Stroke نهائيًا/جافًا إلى التطبيق. تتم بعد ذلك إدارة هذا الكائن غير القابل للتغيير، الذي يمثّل ضربة الحبر المكتملة، في DrawingCanvasViewModel.
-
وحدة العرض: تعرض ضربات الحبر بكفاءة، ما يتيح دمجها مع Jetpack Compose أو طرق العرض في Android.
- لعرض كل من اللمسات الحالية واللمسات التي تم تجفيفها حديثًا، يستخدم Cahier CanvasStrokeRenderer في DrawingSurface للرسم النشط وفي DrawingDetailPanePreview لعرض معاينة ثابتة للملاحظة. تعمل هذه الوحدة بكفاءة على رسم عناصر Stroke على Canvas.
- وحدات الفرشاة (إنشاء - طرق العرض): توفّر طريقة تعريفية لتحديد النمط المرئي للضربات. تشمل التحديثات الأخيرة (منذ الإصدار alpha03) فرشاة خط متقطّع جديدة، وهي مفيدة بشكل خاص لميزات مثل تحديد المساحة باستخدام أداة التحديد الحر. يحتوي DrawingCanvasViewModel على حالة currentBrush. تتيح مجموعة الأدوات في DrawingCanvas للمستخدمين اختيار مجموعات مختلفة من الفرش (مثل StockBrushes.pressurePen() أو StockBrushes.highlighter()) وتغيير الألوان. تعدِّل ViewModel عنصر Brush الذي يستخدمه بعد ذلك العنصر القابل للإنشاء InProgressStrokes للضربات الجديدة.
-
وحدات الأشكال الهندسية (Compose - طرق العرض): تتيح هذه الوحدات معالجة وتحليل ضربات القلم لاستخدامها في ميزات مثل المحو والاختيار.
- تعتمد أداة الممحاة ضمن صندوق الأدوات والوظائف في DrawingCanvasViewModel على وحدة الأشكال الهندسية. عندما تكون الممحاة نشطة، تنشئ MutableParallelogram حول مسار إيماءة المستخدم. بعد ذلك، تتحقّق الممحاة من التقاطعات بين الشكل والمربّعات المحيطة بالضربات الحالية لتحديد الضربات التي يجب محوها، ما يجعل الممحاة سهلة الاستخدام ودقيقة.
- وحدة التخزين: توفّر إمكانات فعّالة لتسلسل بيانات الحبر وتحويلها إلى تنسيق آخر، ما يؤدي إلى توفير مساحة كبيرة على القرص وفي الشبكة. لحفظ الرسومات، يحتفظ تطبيق Cahier بكائنات Stroke في قاعدة بيانات Room. في المحوّلات، يستخدم النموذج الدالة encode الخاصة بوحدة التخزين لتسلسل StrokeInputBatch (بيانات النقاط الأولية) إلى ByteArray. يتم حفظ مصفوفة البايت، بالإضافة إلى خصائص الفرشاة، كسلسلة JSON. يتم استخدام الدالة decode لإعادة إنشاء ضربات القلم عند تحميل ملاحظة.
بالإضافة إلى هذه الوحدات الأساسية، وسّعت التحديثات الأخيرة إمكانات واجهة برمجة التطبيقات Ink API:
-
تتيح واجهات برمجة التطبيقات التجريبية الجديدة لعناصر
BrushFamilyالمخصّصة للمطوّرين إنشاء أنواع فرش إبداعية وفريدة، ما يوفّر إمكانات لأدوات مثل فرشاة القلم ومؤشر الليزر.
تستفيد Cahier من الفُرَش المخصّصة، بما في ذلك فرشة الموسيقى الفريدة المعروضة أدناه، لتوضيح الإمكانات الإبداعية المتقدّمة.
مؤشر ليزر بألوان قوس قزح تم إنشاؤه باستخدام فُرش مخصّصة في Ink API
فرشاة الموسيقى التي تم إنشاؤها باستخدام الفرش المخصّصة في Ink API
- تعمل وحدات التشغيل التفاعلي الأصلية في Jetpack Compose على تبسيط عملية دمج وظائف الكتابة بالحبر مباشرةً في واجهات Compose، ما يوفّر تجربة تطوير أكثر سلاسة وفعالية.
تقدّم Ink API العديد من المزايا التي تجعلها الخيار المثالي لتطبيقات الإنتاجية والإبداع بدلاً من التنفيذ المخصّص:
- سهولة الاستخدام: تجرِّد Ink API تعقيدات الرسومات والأشكال الهندسية، ما يتيح لك التركيز على الميزات الأساسية في Cahier.
- الأداء: يضمن توفُّر ميزة وقت الاستجابة المنخفض المُدمَجة وعملية العرض المحسَّنة تجربة سلسة ومتجاوبة عند الكتابة بالحبر.
- المرونة: يتيح لك التصميم المعياري اختيار المكوّنات المطلوبة، ما يتيح دمج Ink API بسلاسة في بنية Cahier.
تمّ اعتماد Ink API في العديد من تطبيقات Google، بما في ذلك إضافة التعليقات التوضيحية في "مستندات Google" واستخدام ميزة "دائرة البحث"، بالإضافة إلى تطبيقات الشركاء، مثل Orion Notes وPDF Scanner.
كانت Ink API خيارنا الأول لميزة "دائرة البحث" (CtS). بفضل مستنداتهم الشاملة، كانت عملية دمج Ink API سهلة للغاية، ما سمح لنا بالوصول إلى أول نموذج أولي يعمل في غضون أسبوع واحد فقط. لقد سمحت لنا ميزة "الكتابة بالحبر" بتكرار تصميم ضربات الفرشاة بسرعة بفضل إمكانية تخصيص ملمس الفرشاة ودعم الصور المتحركة". - "جوردان كومودا"، مهندس برمجيات في Google
أن يصبح تطبيق تدوين الملاحظات التلقائي مع دور الملاحظات
تدوين الملاحظات هو إحدى الإمكانات الأساسية التي تعزّز إنتاجية المستخدم على الأجهزة ذات الشاشات الكبيرة. باستخدام ميزة "دور الملاحظات"، يمكن للمستخدمين الوصول إلى تطبيقاتك المتوافقة من شاشة القفل أو أثناء تشغيل تطبيقات أخرى. تحدّد هذه الميزة تطبيقات تدوين الملاحظات التلقائية على مستوى النظام وتضبطها، وتمنحها الإذن بتشغيلها لالتقاط المحتوى.
التنفيذ في Cahier
يتضمّن تنفيذ دور الملاحظات بعض الخطوات الرئيسية، وكلّها موضّحة في النموذج:
-
بيان ملف البيان: يجب أولاً أن يعلن التطبيق عن إمكانية التعامل مع أغراض تدوين الملاحظات. في ملف AndroidManifest.xml، يتضمّن تطبيق Cahier
<intent-filter>للإجراء android.intent.action.CREATE_NOTE. تشير هذه العلامة إلى النظام بأنّ التطبيق هو مرشّح محتمل لدور تطبيق الملاحظات. - التحقّق من حالة الدور: يستخدم SettingsViewModel RoleManager في Android لتحديد الحالة الحالية. يتحقّق SettingsViewModel مما إذا كان دور الملاحظات متاحًا على الجهاز (isRoleAvailable) وما إذا كان تطبيق Cahier يؤدي هذا الدور حاليًا (isRoleHeld). يتم عرض هذه الحالة في واجهة المستخدم باستخدام تدفّقات Kotlin.
-
طلب الدور: في ملف Settings.kt، يتم عرض Button للمستخدم إذا كان الدور متاحًا ولكن لم يتم الحصول عليه. عند النقر على الزر، يتم استدعاء الدالة
requestNotesRoleفي ViewModel. تنشئ الدالة غرضًا لفتح شاشة إعدادات التطبيق التلقائي حيث يمكن للمستخدم اختيار Cahier. تتم إدارة العملية باستخدام واجهة برمجة التطبيقات rememberLauncherForActivityResult التي تتولّى إطلاق Intent وتلقّي النتيجة. - تعديل واجهة المستخدم: بعد أن يعود المستخدم من شاشة الإعدادات، يؤدي ردّ الاتصال ActivityResultLauncher إلى تشغيل دالة في ViewModel لتعديل حالة الدور، ما يضمن أنّ واجهة المستخدم تعكس بدقة ما إذا كان التطبيق هو التطبيق التلقائي الآن.
تعرَّف على كيفية دمج دور "الملاحظات" في تطبيقك من خلال دليل إنشاء تطبيق لتدوين الملاحظات.
تم إطلاق تطبيق Cahier في نافذة عائمة كتطبيق تدوين الملاحظات التلقائي على جهاز Lenovo اللوحي
خطوة كبيرة إلى الأمام: Lenovo تتيح دور "الملاحظات"
يسرّنا الإعلان عن خطوة كبيرة إلى الأمام في مجال الإنتاجية على أجهزة Android ذات الشاشات الكبيرة: أتاحت Lenovo دعم "دور الملاحظات" على الأجهزة اللوحية التي تعمل بالإصدار 15 من نظام التشغيل Android والإصدارات الأحدث. من خلال هذا التحديث، يمكنك الآن تحديث تطبيقات تدوين الملاحظات للسماح للمستخدمين الذين لديهم أجهزة Lenovo متوافقة بتعيينها كتطبيقات تلقائية، ما يتيح الوصول إليها بسلاسة من شاشة القفل واستخدام ميزات التقاط المحتوى على مستوى النظام.
ويؤكّد هذا الالتزام من إحدى الشركات الرائدة في تصنيع المعدات الأصلية على الأهمية المتزايدة لدور تطبيق "الملاحظات" في تقديم تجربة مستخدم متكاملة وفعّالة على Android.
فتح نسختين من التطبيق، واستخدام نوافذ متعددة، والعرض في نافذة
تتعلّق الإنتاجية على شاشة كبيرة بإدارة المعلومات وسير العمل بكفاءة. لهذا السبب، تم تصميم Cahier للاستفادة بشكل كامل من إمكانات النوافذ المتقدّمة في Android، ما يوفّر مساحة عمل مرنة تتكيّف مع احتياجات المستخدم. يتوافق التطبيق مع ما يلي:
- تعدّد النوافذ: هي الإمكانية الأساسية لتشغيل التطبيق إلى جانب تطبيق آخر في وضع تقسيم الشاشة أو وضع النوافذ المتعددة. هذا أمر ضروري لتنفيذ مهام مثل الرجوع إلى صفحة ويب أثناء تدوين الملاحظات في Cahier.
- فتح نسختين من التطبيق: هنا تظهر مزايا تنفيذ مهام متعددة. يتيح تطبيق Cahier للمستخدمين فتح نوافذ متعددة ومستقلة للتطبيق في الوقت نفسه. تخيَّل مقارنة ملاحظتَين مختلفتَين جنبًا إلى جنب أو الرجوع إلى ملاحظة نصية في إحدى النوافذ أثناء العمل على رسم في نافذة أخرى. يوضّح Cahier كيفية إدارة هذه المثيلات المنفصلة، ولكل منها حالته الخاصة، ما يحوّل تطبيقك إلى أداة قوية ومتعددة الأوجه.
- العرض في نافذة: عند توصيل جهاز لوحي أو جهاز قابل للطي بشاشة خارجية، يحوّل وضع الكمبيوتر المكتبي على Android الجهاز إلى محطة عمل. بما أنّ تطبيق Cahier مصمّم بواجهة مستخدم قابلة للتكيّف ويتيح فتح نسختين من التطبيق، يعمل التطبيق بشكل ممتاز في هذه البيئة. يمكن للمستخدمين فتح نوافذ Cahier متعددة وتغيير حجمها وموضعها تمامًا كما هو الحال على الكمبيوتر المكتبي التقليدي، ما يتيح إمكانية تنفيذ مهام معقّدة لم تكن متاحة من قبل على الأجهزة الجوّالة.
تطبيق Cahier يعمل في وضع نافذة سطح المكتب على جهاز Pixel Tablet
في ما يلي كيفية تنفيذ هذه الميزات في Cahier:
لتفعيل ميزة فتح نسختين من التطبيق، كان علينا أولاً إبلاغ النظام بأنّ التطبيق يتيح تشغيله عدة مرات من خلال إضافة السمة PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI إلى بيان MainActivity في AndroidManifest:
<activity android:name="com.example.cahier.MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.MyApplication" android:showWhenLocked="true" android:turnScreenOn="true" android:resizeableActivity="true" android:launchMode="singleInstancePerTask"> <property android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI" android:value="true"/> ... </activity>
بعد ذلك، نفّذنا منطقًا لإطلاق مثيل جديد من التطبيق. في CahierHomeScreen.kt، عندما يختار المستخدم فتح ملاحظة في نافذة جديدة، ننشئ Intent جديدًا يتضمّن علامات محدّدة توجّه النظام بشأن كيفية التعامل مع إطلاق النشاط الجديد. يضمن الجمع بين FLAG_ACTIVITY_NEW_TASK وFLAG_ACTIVITY_MULTIPLE_TASK وFLAG_ACTIVITY_LAUNCH_ADJACENT فتح الملاحظة في نافذة جديدة منفصلة بجانب النافذة الحالية.
fun openNewWindow(activity: Activity?, note: Note) {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra(AppArgs.NOTE_TYPE_KEY, note.type)
intent.putExtra(AppArgs.NOTE_ID_KEY, note.id)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
activity?.startActivity(intent)
}
لإتاحة وضع النوافذ المتعددة، كان علينا إعلام النظام بأنّ التطبيق يتيح تغيير الحجم من خلال ضبط العنصر <activity> أو <application> في ملف البيان.
<activity android:name="com.example.cahier.MainActivity" android:resizeableActivity="true" ...> </activity>
إنّ واجهة المستخدم نفسها التي تم إنشاؤها باستخدام مكتبة Material 3 التكيُّفية تتيح لها التكيّف بسلاسة في سيناريوهات النوافذ المتعددة، مثل وضع تقسيم الشاشة في Android.
لتحسين تجربة المستخدم، أتحنا إمكانية السحب والإفلات. يمكنك الاطّلاع أدناه على كيفية تنفيذ ذلك في Cahier.
السحب والإفلات
لا يعمل التطبيق الإنتاجي أو الإبداعي بشكل منفصل، بل يتفاعل بسلاسة مع بقية منظومة الجهاز المتكاملة. تُعدّ ميزة السحب والإفلات حجر الزاوية في هذا التفاعل، خاصةً على الشاشات الكبيرة حيث يعمل المستخدمون غالبًا على نوافذ تطبيقات متعددة. تستفيد Cahier من هذه الميزة بشكل كامل من خلال توفير وظيفة سحب وإفلات سهلة الاستخدام لإضافة المحتوى ومشاركته.
-
استيراد سهل: يمكن للمستخدمين سحب الصور من تطبيقات أخرى، مثل متصفّح الويب أو معرض الصور أو مدير الملفات، وإفلاتها مباشرةً على لوحة ملاحظات. لإجراء ذلك، تستخدم Cahier المعدِّل dragAndDropTarget لتحديد منطقة الإفلات، والتحقّق من المحتوى المتوافق (مثل
image/*)، ومعالجة معرّف الموارد الموحّد الوارد. - المشاركة البسيطة: يمكن مشاركة المحتوى داخل Cahier بسهولة كما هو الحال مع المحتوى من التطبيقات الأخرى. يمكن للمستخدمين الضغط مع الاستمرار على صورة داخل ملاحظة نصية، أو الضغط مع الاستمرار على لوحة الرسم بأكملها لملاحظة رسم وتركيب صورة، ثم سحبها إلى تطبيق آخر.
نظرة متعمّقة من الناحية الفنية: السحب من لوحة الرسم
يمثّل تنفيذ إيماءة السحب على لوحة الرسم تحديًا فريدًا. في DrawingSurface، تكون العناصر القابلة للإنشاء التي تعالج إدخال الرسم المباشر (InProgressStrokes في Ink API) وBox الذي يرصد إيماءة الضغط مع الاستمرار لبدء السحب عناصر قابلة للإنشاء متجاورة.
بشكلٍ تلقائي، تم تصميم نظام إدخال المؤشر في Jetpack Compose بحيث يتلقّى حدثًا واحدًا فقط من العناصر القابلة للإنشاء المتجاورة، وهو العنصر الأول في ترتيب التعريف الذي يتداخل مع موضع اللمس. في حالة Cahier، نريد أن تتاح فرصة لتنفيذ منطق معالجة الإدخال بالسحب والإفلات واستهلاك المدخلات المحتملة قبل أن تستخدم الدالة البرمجية القابلة للإنشاء InProgressStrokes جميع المدخلات غير المستهلكة للرسم ثم تستهلك هذه المدخلات. إذا لم نرتب العناصر بالترتيب الصحيح، لن يرصد Box الإيماءة بالضغط مع الاستمرار لبدء السحب، أو لن يتلقّى InProgressStrokes الإدخال للرسم.
لحلّ هذه المشكلة، أنشأنا معدِّلاً مخصّصًا pointerInputWithSiblingFallthrough، ووضعنا Box باستخدام هذا المعدِّل قبل InProgressStrokes في الرمز البرمجي القابل للإنشاء. هذه الأداة المساعدة هي برنامج تضمين بسيط حول نظام pointerInput العادي، ولكن مع تغيير مهم واحد: فهي تتجاوز الدالة sharePointerInputWithSiblings() لعرض true. يطلب ذلك من إطار عمل Compose السماح بتمرير أحداث المؤشر إلى العناصر القابلة للإنشاء المتجاورة، حتى بعد استخدامها.
internal fun Modifier.pointerInputWithSiblingFallthrough(
pointerInputEventHandler: PointerInputEventHandler
) = this then PointerInputSiblingFallthroughElement(pointerInputEventHandler)
private class PointerInputSiblingFallthroughModifierNode(
pointerInputEventHandler: PointerInputEventHandler
) : PointerInputModifierNode, DelegatingNode() {
var pointerInputEventHandler: PointerInputEventHandler
get() = delegateNode.pointerInputEventHandler
set(value) {
delegateNode.pointerInputEventHandler = value
}
val delegateNode = delegate(
SuspendingPointerInputModifierNode(pointerInputEventHandler)
)
override fun onPointerEvent(
pointerEvent: PointerEvent,
pass: PointerEventPass,
bounds: IntSize
) {
delegateNode.onPointerEvent(pointerEvent, pass, bounds)
}
override fun onCancelPointerInput() {
delegateNode.onCancelPointerInput()
}
override fun sharePointerInputWithSiblings() = true
}
private data class PointerInputSiblingFallthroughElement(
val pointerInputEventHandler: PointerInputEventHandler
) : ModifierNodeElement<PointerInputSiblingFallthroughModifierNode>() {
override fun create() = PointerInputSiblingFallthroughModifierNode(pointerInputEventHandler)
override fun update(node: PointerInputSiblingFallthroughModifierNode) {
node.pointerInputEventHandler = pointerInputEventHandler
}
override fun InspectorInfo.inspectableProperties() {
name = "pointerInputWithSiblingFallthrough"
properties["pointerInputEventHandler"] = pointerInputEventHandler
}
}
في ما يلي كيفية استخدامها في DrawingSurface:
Box(
modifier = Modifier
.fillMaxSize()
// Our custom modifier enables this gesture to coexist with the drawing input.
.pointerInputWithSiblingFallthrough {
detectDragGesturesAfterLongPress(
onDragStart = { onStartDrag() },
onDrag = { _, _ -> /* consume drag events */ },
onDragEnd = { /* No action needed */ }
)
}
)
// The Ink API's composable for live drawing sits here as a sibling.
InProgressStrokes(...)
وبعد تنفيذ ذلك، يرصد النظام بشكل صحيح كلاً من ضربات الرسم وإيماءة السحب مع الضغط لفترة طويلة في الوقت نفسه. بعد بدء عملية السحب، ننشئ معرّف موارد منتظم (URI) content:// قابلاً للمشاركة باستخدام FileProvider ونمرّر معرّف الموارد المنتظم (URI) إلى إطار عمل السحب والإفلات في النظام باستخدام view.startDragAndDrop(). يضمن هذا الحل تجربة مستخدم قوية وسهلة الاستخدام، ويوضّح كيفية التغلّب على تعارضات الإيماءات المعقّدة في واجهات المستخدم ذات الطبقات.
مبنى ذو تصميم معماري حديث
بالإضافة إلى واجهات برمجة التطبيقات المحدّدة، يوضّح Cahier أنماطًا معمارية مهمة لإنشاء تطبيقات عالية الجودة وقابلة للتكيّف.
طبقة العرض: Jetpack Compose والتكيّف
تم إنشاء طبقة العرض بالكامل باستخدام Jetpack Compose. كما ذكرنا، تستخدم Cahier مكتبة material3-adaptive لتكيُّف واجهة المستخدم. تتّبع إدارة الحالة نمطًا صارمًا لتدفّق البيانات في اتجاه واحد (UDF)، ويتم استخدام مثيلات ViewModel كحاويات بيانات تحتوي على معلومات الملاحظات وحالة واجهة المستخدم.
طبقة البيانات: المستودعات وRoom
بالنسبة إلى طبقة البيانات، يستخدم Cahier واجهة NoteRepository لتجريد جميع عمليات البيانات. يتيح خيار التصميم هذا للتطبيق التبديل بسهولة بين مصدر بيانات محلي (Room) وخادم خلفي بعيد محتمل في المستقبل. إنّ تدفق البيانات لإجراء مثل تعديل ملاحظة بسيط:
- تؤدي واجهة مستخدم Jetpack Compose إلى تشغيل طريقة في ViewModel.
- يجلب ViewModel الملاحظة من NoteRepository، ويتعامل مع المنطق، ويعيد الملاحظة المعدَّلة إلى المستودع.
- يحفظ NoteRepository التعديل في قاعدة بيانات Room.
التوافق الشامل مع أجهزة الإدخال
لكي يكون التطبيق أداة إنتاجية حقيقية، يجب أن يتعامل مع مجموعة متنوعة من طرق الإدخال بسلاسة. تم تصميم تطبيق Cahier ليتوافق مع إرشادات الإدخال على الشاشات الكبيرة ويتيح ما يلي:
- قلم الشاشة: يتضمّن هذا القسم معلومات حول الدمج مع Ink API، وميزة "منع لمس راحة اليد"، والتسجيل في دور "تدوين الملاحظات"، وإدخال البيانات باستخدام قلم الشاشة في الحقول النصية، والوضع الغامر.
- لوحة المفاتيح: إتاحة معظم اختصارات لوحة المفاتيح الشائعة ومجموعاتها (مثل ctrl+click وmeta+click) وإشارة واضحة إلى موضع التركيز على لوحة المفاتيح
- الماوس ولوحة اللمس: إتاحة النقر بزر الماوس الأيمن وحالات التمرير.
يُعد توفير إمكانية التفاعل المتقدّم مع لوحة المفاتيح والماوس ولوحة اللمس من أهم الجوانب التي نركّز عليها لإجراء المزيد من التحسينات.
ابدأ اليوم
نأمل أن يكون Cahier نقطة انطلاق لتطبيقك الرائع التالي، فقد صمّمناه ليكون مرجعًا شاملاً ومفتوح المصدر يوضّح كيفية الجمع بين واجهة مستخدم متكيّفة وواجهات برمجة تطبيقات قوية، مثل Ink ودور الملاحظات، وبنية حديثة ومتكيّفة.
هل أنت مستعد لخوض التجربة؟
- استكشاف الرمز: انتقِل إلى مستودع GitHub لاستكشاف قاعدة رموز Cahier والاطّلاع على مبادئ التصميم أثناء العمل.
- إنشاء تطبيقك الخاص: استخدِم Cahier كأساس لتطبيقك الخاص لتدوين الملاحظات أو ترميز المستندات أو التطبيقات الإبداعية.
- المساهمة: نرحّب بمساهماتك. ساعِدنا في جعل Cahier مرجعًا أفضل لمجتمع مطوّري تطبيقات Android.
يمكنك الاطّلاع على أدلة المطوّرين الرسمية والبدء في إنشاء الجيل التالي من تطبيقات الإنتاجية والإبداع اليوم. نحن متحمّسون لرؤية أعمالكم الإبداعية.
متابعة القراءة
-
طرق التنفيذ
سواء كنت تستخدم "Gemini في استوديو Android" أو Gemini CLI أو Antigravity أو وكلاء تابعين لجهات خارجية، مثل Claude Code أو Codex، تتمثّل مهمتنا في ضمان إمكانية تطوير تطبيقات Android عالية الجودة في كل مكان.
Adarsh Fernando, Esteban de la Canal • مدة القراءة: 4 دقائق
-
طرق التنفيذ
إدراكًا منّا أنّ استنزاف البطارية بشكل مفرط هو أوّل ما يخطر في بال مستخدمي Android، اتّخذت Google خطوات مهمة لمساعدة المطوّرين في إنشاء تطبيقات أكثر كفاءة في استهلاك الطاقة.
Alice Yuan • مدة القراءة: 8 دقائق
-
طرق التنفيذ
أردنا أن نقدّم لك أمثلة على الميزات المستندة إلى الذكاء الاصطناعي والتي تستخدم نماذج على الجهاز فقط ونماذج على السحابة الإلكترونية، وأن نلهمك لإنشاء تجارب رائعة للمستخدمين.
Thomas Ezan, Ivy Knight • مدة القراءة: دقيقتان
البقاء على اطّلاع على آخر التحديثات
يمكنك تلقّي أحدث الإحصاءات حول تطوير تطبيقات Android في بريدك الوارد أسبوعيًا.