یکی از قابلیت های جذابی که به اندروید تی وی اضافه شده (در قالب leanBack) کلاس BackgroundManager هست.

به کمک این کلاس شما قادر هستید با انتخاب هر یک از آیتم های لیست، عکس بک گراند صفحه رو عوض کنید.

البته شاید خیلی ساده بنظر برسه این موضوع پیاده سازیش (داخل اپلیکیشن اندروید موبایل) ولی به کمک این کلاس Android Tv این کار به افکتی که برای خود این دیوایس طراحی شده انجام میشه، و فضا رو تلطیف میکنه  😊

وقتی عکس رو بخواید از روی یک لینک وب بگیرید، این تغییر می تونه به کمک Glide یا Picasso  یا هر روش دیگه ای صورت بگیره، برای اینکه احتمال زیاد عکس های یک اپلیکیشن اندروید تی وی، از وب خوانده میشوند، دقیقا مثل عکس های لیست ما که یک سری عکس از فیلم هایی بودند که لینکش رو لود میکردیم، پس من ترجیح میدم همینجا داخل آموزش یک راست از Glide استفاده کنم.

کلاس زیر رو می سازیم:

class TvBackgroundManager(private val activity: Activity){
    var backgroundManager: BackgroundManager = BackgroundManager.getInstance(activity).apply {
        attach(activity.window)
    }
    var defaultDrawable: Drawable = ContextCompat.getDrawable(activity, R.drawable.iodroid_main_bg)!!

    fun updateBackground(drawable: Drawable){
         }

    fun updateBackground(imageUrl: String){
    }

    fun clearBackground(){
       }
}

من یک عکس پیشفرش گذاشتم به اسم defaultDrawable، که وقتی آیتمی از لیست لود نشده قرار هست این عکس نمایش داده بشه.

همینطور یک نمونه از BackgrounManager که داخل پکیج leanBack هست رو هم قرار دادم. حالا هرکدوم از متدها رو کامل میکنیم:


fun updateBackground(drawable: Drawable){
    backgroundManager.drawable = drawable
}

نوع عکسی که backgroundManager قبول میکنه، از جنس drawable یا bitmap هست. پس خیلی راحت داخل این متد ورودی رو به backgroundManager میدم تا نمایشش بده. این متد فعلا داخل کد اپلیکیشن استفاده نخواهد شد.

fun updateBackground(imageUrl: String){
     Glide.with(activity)
         .asBitmap()
         .load(imageUrl)
         .into(object : CustomTarget<Bitmap>(){
             override fun onLoadCleared(placeholder: Drawable?) {            }
 
             override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                 backgroundManager.setBitmap(resource)
             }
         })
 }

همونطور که در بالا گفتم، backgroundManager قرار هست فقط drawable یا bitmap بگیره. داخل این متد ما لینک عکس رو داریم که با Glide قرار هست لود بشه. به کمک فانکشن .asBitmap() کتابخانه Glide این امکان رو میده که عکس رو بعنوان یک bitmap دریافت کنیم. از اونجایی که خروجی Glide رو لازم داریم تا به backgroundManager بدیم (و قرار نیست اون رو بعنوان عکس به یک imageView ست کنیم) پس داخل تابع into به جای دادن id یک imageView، با پیاده سازی abstract class CustomTarget  که داخل پکیج Glide هست، و داخل تابع onResourceReady خروجی کار Glide رو دریافت میکنم. در مرحله آخر اون رو به backgroundManager میدم:

backgroundManager.setBitmap(resource)

آخرین تابعی که پیاده میکنم، برای ست کردن عکس دیفالت به backgroundManager هست:

fun clearBackground(){
    backgroundManager.drawable = defaultDrawable
}

استفاده از این کلاس خیلی راحت تر از چیزی که فکر کنید هست. کافیه روی یک listener که متوجه بشه آیتمی از لیست رو انتخاب کردم، این متد ها رو صدا بزنم تا عکس اون آیتم رو روی بک گراند صفحه ست کنم.

داخل MainFragment با استفاده از setOnItemViewSelectedListener (که داخل کاتلین می توان آن را onItemViewSelectedListener صدا زد) من با پیاده سازی interface OnItemViewSelectedListener، نوع آیتم لیست رو گرفته و عکسش رو به backgroundManager میدهم:

onItemViewSelectedListener =
    OnItemViewSelectedListener { viewHolder, item, rowViewHolder, row ->
        if (item is Movie){
            tvBackgroundManager.updateBackground(item.coverUrl)
        }else{
            tvBackgroundManager.clearBackground()
        }
    }

پس اگر آیتم انتخاب شده از جنس کلاس Movie بود، عکس کاور فیلم بعنوان بک گراند صفحه قرار داده میشه، و اگر آیتم انتخاب شده از این جنس نبود(یا آیتمی انتخاب نشده بود) عکس دیفالت نمایش داده خواهد شد.

که البته tvBackgroundManager باید مقدار دهی بشه، پس بالای کلاس MainFragment این مقدار رو تعریف میکنم:

private val tvBackgroundManager: TvBackgroundManager by lazy {
    TvBackgroundManager(activity as MainActivity).apply {
        clearBackground()
    }
}

(احتمالا می دانید که در کاتلین، by lazy کمک می کند که متغیری را تعریف کنیم و هر هنگام که صدا زده شد آن را مقدار دهی کنیم)

و خروجی:

استفاده از BackgroundManager برای لیست در AndroidTv

طبق قول کدها قرار هست داخل گیت قرار بگیرند. پس من داخل ریپوزیتوری گیتهابی که به این پروژه تخصیص دادم، روی برنچ iodroid_tv/add_background_manager کد این بخش از آموزش رو قرار دادم. (طبیعتا کد نهایی هم روی برنج master موجود هست)
برای دسترسی به این شاخه از پروژه گیتهاب کلیک کنید 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *
You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>