أحتاج إلى عرض المعلومات التقنية حول حالته على شاشة الهاتف ، وبشكل أكثر دقة حول حالته في مجموعة الاختبارات. أريد دائمًا رؤية هذه المعلومات ، أي على الشاشة الرئيسية ، وبدون حركات جسم إضافية.
هناك طريقتان فقط لن يؤثران على تنفيذ التطبيقات الأخرى: القطعة أو خلفية الشاشة. لقد اخترت Live Wallpaper ، كما أنها "خلفيات حية" ، لأنها تصل تلقائيًا إلى جميع صفحات الشاشة الرئيسية ، وحتى إلى Lock lock. تقدم هذه المقالة نصائح عملية حول كيفية إنشاء خلفيات حية.
بحثا عن الحقيقة
وثائق حول القط "خلفية حية" بكى. منذ الإعلان الأول (والوحيد) على المدونة الذي حدث قبل أكثر من 9 سنوات ، لم تقدم Google مثالًا أو كودلًا واحدًا واضحًا حول هذا الموضوع. كان علي أن أفهم.
أساسيات الأولى. إن الآليات الداخلية لنظام Android هي التي يمكننا من خلالها تثبيت التطبيق فقط على الجهاز ، وجهاز جميع التطبيقات هو نفسه. نظرًا لأن "خلفية حية" هي أيضًا تطبيق ، فإن اختيار عنصر التحكم ليس جيدًا ، ويجب أن نتوقع أن يكون "خدمة". العثور عليه سهل: إنه WallpaperService .
يمكن أن يكون هناك عدة مثيلات لـ "خلفية حية" ، وستختلف دورة حياتها عن دورة النشاط أو العرض. وفقًا لذلك ، يجب أن يكون هناك طبقة أساسية أخرى. هذا هو WallpaperService.Engine (وهو بالضرورة داخلي لـ WallpaperService !). إذا نظرت عن كثب ، فستتحول إلى أن تكون المزود الأول لأحداث دورة الحياة مثل النشاط والخدمة وغيرها مثلها.
تبدو دورة حياة "خلفية حية" كما يلي:
onCreate (SurfaceHolder surfaceHolder)
onSurfaceCreated (حامل SurfaceHolder)
onSurfaceChanged (حامل SurfaceHolder ، تنسيق int ، عرض كثافة العمليات ، ارتفاع كثافة العمليات)
onVisibilityChanged (مرئية منطقية)
onSurfaceRedrawNeeded (حامل SurfaceHolder)
onSurfaceDestroyed (حامل SurfaceHolder)
onDestroy ()
من هذه القائمة ، يصبح من الواضح متى يمكنك / تحتاج إلى إعادة رسم الصورة (أو البدء في إعادة الرسم إذا كان لديك رسم متحرك) ، وعندما حان الوقت لإيقاف كل الأنشطة وليس إهدار البطارية.
تبرز طريقة onSurfaceRedrawNeeded () من الباقي ، اقرأ أدناه. هناك أيضًا طريقة isVisible () للمساعدة (والتي تتحول في Kotlin إلى خاصية isVisible
).
الآن يمكنك بناء هذا المنشئ. سأبدأ من النهاية.
رسم
سيتعين علينا أن نرسم أنفسنا على Canvas ، ولن يكون لدينا أي تخطيط ونفخ. كيفية الحصول على Canvas من SurfaceHolder وكيفية الاعتماد عليه خارج نطاق هذه المقالة ، يوجد مثال بسيط أدناه.
fun dummyDraw(c: Canvas) { c.save() c.drawColor(Color.CYAN) c.restore() }
أساليب دورة حياة المحرك
جميع أساليب دورة الحياة باستثناء onSurfaceRedrawNeeded
لا تتطلب إعادة رسم فورية. لذلك ، سيكون لهجة جيدة لإعادة رسم قائمة الانتظار.
override fun onSurfaceCreated(holder: SurfaceHolder?) { super.onSurfaceCreated(holder) redrawHandler.planRedraw() } override fun onSurfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) { super.onSurfaceChanged(holder, format, width, height) redrawHandler.planRedraw() } override fun onVisibilityChanged(visible: Boolean) { super.onVisibilityChanged(visible) redrawHandler.planRedraw() } override fun onSurfaceDestroyed(holder: SurfaceHolder?) { super.onSurfaceDestroyed(holder) redrawHandler.omitRedraw() } override fun onDestroy() { super.onDestroy() redrawHandler.omitRedraw() } override fun onSurfaceRedrawNeeded(holder: SurfaceHolder) { super.onSurfaceRedrawNeeded(holder) redrawHandler.omitRedraw() drawSynchronously(holder)
انتبه إلى onSurfaceRedrawNeeded ، والذي يعطينا مكالمة إلى رد الاتصال SurfaceHolder الذي يحمل نفس الاسم ، والذي يحدث عند تغيير الحجم والأحداث المشابهة. يتيح لك رد الاتصال هذا إعادة الرسم على الفور ، دون السماح للمستخدم بعرض الصورة القديمة (وغير الصحيحة بالفعل). يضمن النظام أنه حتى حدوث عودة من هذه الطريقة ، سيتم إيقاف الإخراج إلى الشاشة مؤقتًا.
جدولة
أحب إعادة تعريف Handler ، وليس لتشغيل Runnable فيه. في رأيي ، أنيقة جدا.
في حال كان لديك رسوم متحركة أو تحديثات منتظمة ، ستحتاج إلى عمل قائمة انتظار منتظمة للرسالة ( postAtTime () و postDelayed () لمساعدتك). إذا تم تحديث البيانات بشكل متقطع ، ما planRedraw()
سوى الاتصال بـ planRedraw()
لتحديثها.
val redrawHandler = RedrawHandler() inner class RedrawHandler : Handler(Looper.getMainLooper()) { private val redraw = 1 fun omitRedraw() { removeMessages(redraw) } fun planRedraw() { omitRedraw() sendEmptyMessage(redraw) } override fun handleMessage(msg: Message) { when (msg.what) { redraw -> drawSynchronously() else -> super.handleMessage(msg) } } }
الخدمة والمحرك
يتم تجميع mareshka من الخدمة والمحرك مثل هذا:
class FooBarWallpaperService : WallpaperService() { override fun onCreateEngine() = FooBarEngine() inner class FooBarEngine : Engine() { .... } }
AndroidManifest ونوبات أخرى
أدعو نوبات في تطوير البرمجيات أنه من المستحيل فهمها ، ولكن من الضروري تكرارها تمامًا.
في .../app/src/main/res/xml
يجب أن يكون هناك ملف XML مع وصف "خلفية حية". يجب تحديد اسم هذا الملف في AndroidManifest (ابحث عن كلمة foobarwallpaper
في المثال أدناه)
<?xml version="1.0" encoding="UTF-8"?> <wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:thumbnail="@drawable/some_drawable_preview" android:description="@string/wallpaper_description" />
لا تفقد permission
meta-data
intent-filter
في وصف الخدمة:
<service android:name=".FooBarWallpaperService" android:enabled="true" android:label="Wallpaper Example" android:permission="android.permission.BIND_WALLPAPER"> <meta-data android:name="android.service.wallpaper" android:resource="@xml/foobarwallpaper" > </meta-data> <intent-filter> <action android:name="android.service.wallpaper.WallpaperService"> </action> </intent-filter> </service>
كيف تضيف
"خلفيات حية" يختبئون ، وبالتالي تلميحا. أصف كيف يبدو على جهاز Samsung الخاص بي.
للبدء ، اضغط لفترة طويلة في مكان ما على الشاشة الرئيسية ، سينتقل الهاتف إلى وضع إعدادات سطح المكتب ، وسوف يظهر رمز خلفيات .
نقر على أيقونة " خلفيات" ، عدة أقسام ، نحتاج إلى "خلفياتي" ، انقر على "نقش" عرض الكل في الزاوية اليمنى العليا من القسم ، يتم فتح القائمة في وضع ملء الشاشة.
نضغط على "النقاط الثلاث" في قائمة المكالمات ، وفيها يظهر عنصر LIve wallpapers (لدي واحدة) ، تظهر قائمة "بالخلفيات الحية" المتوفرة.
حدد ورق الحائط الخاص بنا ، وحدد "الشاشة الرئيسية والقفل".
ستظهر "معاينة" ، والتي يتم رسمها بالفعل بواسطة تطبيقنا (للتعرف على هذه اللحظة ، هناك طريقة isPreview () ) ، انقر فوق تعيين كخلفية ... ولا نرى أي شيء ، لأننا نعود إلى قائمة الخلفيات المتوفرة.
انقر فوق "الصفحة الرئيسية" والتمتع بها.
ثم Android Watch؟!
ملاحظة مثيرة للاهتمام على طول الطريق هي أن الوجوه في Android Watch مصنوعة بالطريقة نفسها تمامًا (مع دقة أن لديهم فصولهم الأساسية مع تنفيذهم الخاص): نفس الخدمة + المحرك ، ونفس البيانات الوصفية ومرشح النية للخدمة في البيان (في الذي تحدث فيه خلفية الكلمة أربع مرات :) ، ستحتاج أيضًا إلى كتابة sheduler الخاص بك استنادًا إلى Handler .
في الفصول الأساسية لـ Watch Faces ، يوجد onDraw()
جاهز ، حيث يتم تمرير Canvas ، وهناك invalidate()
لاستدعائه. لكن هذا ليس فرقًا جوهريًا ، ولكن الجزء الذي تم تنفيذه من النمطي.
على عكس Live Wallpaper ، هناك أمثلة لـ Watch Faces ، يمكنك البحث فيها (روابط هنا ، في البداية).
ماذا حدث
لقطات الشاشة لتطبيق يرسم شاشة خضراء لا معنى لها. لكن تبين أن بعض الصور التي تستند إلى ذلك تم تنفيذها للحامل القتالي ، تحت المفسد.
زوجان من الصور

الملصقات هي نظام الكشف عن المشاكل المتبقية من الجيل السابق.
شكر
إن لم يكن لهاتين المادتين ، لكنت تجولت في الظلام لفترة أطول. لا أستطيع أن أتخيل كيف كان من الممكن أن تكون قد كتبت بالفعل في عام 2010 مع وثائق الجودة هذه؟!
كيريل غروشنيكوف ، خلفيات حية
Vogella ، Android Live Wallpaper - البرنامج التعليمي
شفرة المصدر
→ جيثب