สร้างเบราว์เซอร์แคตตาล็อก

สร้างได้ดียิ่งขึ้นด้วย Compose
สร้าง UI ที่สวยงามด้วยโค้ดแบบเรียบง่ายโดยใช้ Jetpack Compose สำหรับระบบปฏิบัติการ Android TV

แอปสื่อที่ทำงานบนทีวีจำเป็นต้องให้ผู้ใช้เรียกดูเนื้อหาที่มีให้บริการ เลือกแล้วเริ่มเล่นเนื้อหา ประสบการณ์การเรียกดูเนื้อหา ต้องเรียบง่ายและเข้าใจง่าย รวมถึงสวยงามและดึงดูดสายตา

คำแนะนำนี้จะกล่าวถึงวิธีใช้ชั้นเรียนที่ไลบรารี androidx.leanback เพื่อใช้อินเทอร์เฟซผู้ใช้สำหรับการเรียกดูเพลงหรือวิดีโอจากแคตตาล็อกสื่อของแอป

หมายเหตุ: ตัวอย่างการใช้งานที่แสดงที่นี่ใช้ BrowseSupportFragment แทนที่จะเป็น BrowseFragment ที่เลิกใช้งานแล้ว BrowseSupportFragment ขยายเวลาสำหรับ AndroidX Fragment ชั้นเรียน เพื่อช่วยให้เกิดลักษณะการทำงานที่สอดคล้องกันในอุปกรณ์และเวอร์ชัน Android

หน้าจอหลักของแอป

รูปที่ 1 ส่วนการเรียกดูของแอปตัวอย่าง Leanback จะแสดงข้อมูลแคตตาล็อกวิดีโอ

สร้างเลย์เอาต์การเรียกดูสื่อ

BrowseSupportFragment ในชุดเครื่องมือ Leanback UI ช่วยให้คุณสามารถสร้างเค้าโครงหลักสำหรับการเรียกดูหมวดหมู่และแถวของรายการสื่อที่มี ขั้นต่ำของโค้ด ตัวอย่างต่อไปนี้จะแสดงวิธีสร้างเลย์เอาต์ที่มีองค์ประกอบ ออบเจ็กต์ BrowseSupportFragment รายการ:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:name="com.example.android.tvleanback.ui.MainFragment"
        android:id="@+id/main_browse_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

กิจกรรมหลักของแอปพลิเคชันจะกำหนดมุมมองนี้ ดังที่ปรากฏในตัวอย่างต่อไปนี้:

Kotlin

class MainActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
    }
...

Java

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
...

เมธอด BrowseSupportFragment จะป้อนข้อมูลมุมมองด้วย ข้อมูลวิดีโอและองค์ประกอบ UI และตั้งค่าพารามิเตอร์เลย์เอาต์ เช่น ไอคอนและชื่อและ เปิดใช้ส่วนหัวหมวดหมู่หรือไม่

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการตั้งค่าองค์ประกอบ UI โปรดดูตั้งค่า UI องค์ประกอบ ดูข้อมูลเพิ่มเติมเกี่ยวกับการซ่อนส่วนหัวได้ที่ ส่วนซ่อนหรือปิดใช้ส่วนหัว

คลาสย่อยของแอปพลิเคชันที่ใช้ BrowseSupportFragment จะตั้งค่า Listener เหตุการณ์สำหรับการดำเนินการของผู้ใช้ในองค์ประกอบ UI และเตรียมความพร้อม เครื่องมือจัดการพื้นหลัง ดังที่แสดงในตัวอย่างต่อไปนี้

Kotlin

class MainFragment : BrowseSupportFragment(),
        LoaderManager.LoaderCallbacks<HashMap<String, List<Movie>>> {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        loadVideoData()
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        prepareBackgroundManager()
        setupUIElements()
        setupEventListeners()
    }
    ...
    private fun prepareBackgroundManager() {
        backgroundManager = BackgroundManager.getInstance(activity).apply {
            attach(activity?.window)
        }
        defaultBackground = resources.getDrawable(R.drawable.default_background)
        metrics = DisplayMetrics()
        activity?.windowManager?.defaultDisplay?.getMetrics(metrics)
    }

    private fun setupUIElements() {
        badgeDrawable = resources.getDrawable(R.drawable.videos_by_google_banner)
        // Badge, when set, takes precedent over title
        title = getString(R.string.browse_title)
        headersState = BrowseSupportFragment.HEADERS_ENABLED
        isHeadersTransitionOnBackEnabled = true
        // Set header background color
        brandColor = ContextCompat.getColor(requireContext(), R.color.fastlane_background)

        // Set search icon color
        searchAffordanceColor = ContextCompat.getColor(requireContext(), R.color.search_opaque)
    }

    private fun loadVideoData() {
        VideoProvider.setContext(activity)
        videosUrl = getString(R.string.catalog_url)
        loaderManager.initLoader(0, null, this)
    }

    private fun setupEventListeners() {
        setOnSearchClickedListener {
            Intent(activity, SearchActivity::class.java).also { intent ->
                startActivity(intent)
            }
        }

        onItemViewClickedListener = ItemViewClickedListener()
        onItemViewSelectedListener = ItemViewSelectedListener()
    }
    ...

Java

public class MainFragment extends BrowseSupportFragment implements
        LoaderManager.LoaderCallbacks<HashMap<String, List<Movie>>> {
}
...
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        loadVideoData();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        prepareBackgroundManager();
        setupUIElements();
        setupEventListeners();
    }
...
    private void prepareBackgroundManager() {
        backgroundManager = BackgroundManager.getInstance(getActivity());
        backgroundManager.attach(getActivity().getWindow());
        defaultBackground = getResources()
            .getDrawable(R.drawable.default_background);
        metrics = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
    }

    private void setupUIElements() {
        setBadgeDrawable(getActivity().getResources()
            .getDrawable(R.drawable.videos_by_google_banner));
        // Badge, when set, takes precedent over title
        setTitle(getString(R.string.browse_title));
        setHeadersState(HEADERS_ENABLED);
        setHeadersTransitionOnBackEnabled(true);
        // Set header background color
        setBrandColor(ContextCompat.getColor(requireContext(), R.color.fastlane_background));
        // Set search icon color
        setSearchAffordanceColor(ContextCompat.getColor(requireContext(), R.color.search_opaque));
    }

    private void loadVideoData() {
        VideoProvider.setContext(getActivity());
        videosUrl = getString(R.string.catalog_url);
        getLoaderManager().initLoader(0, null, this);
    }

    private void setupEventListeners() {
        setOnSearchClickedListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getActivity(), SearchActivity.class);
                startActivity(intent);
            }
        });

        setOnItemViewClickedListener(new ItemViewClickedListener());
        setOnItemViewSelectedListener(new ItemViewSelectedListener());
    }
...

ตั้งค่าองค์ประกอบ UI

ในตัวอย่างก่อนหน้านี้ วิธีส่วนตัว setupUIElements() เรียกหลายรายการ วันที่ BrowseSupportFragment วิธีจัดรูปแบบเบราว์เซอร์แคตตาล็อกสื่อ

  • setBadgeDrawable() วางทรัพยากรที่ถอนได้ที่ระบุไว้ไว้ที่มุมขวาบนของส่วนการเรียกดู แสดงในรูปที่ 1 และ 2 วิธีนี้จะแทนที่สตริงชื่อด้วยพารามิเตอร์ ทรัพยากรที่ถอนออกได้ หากมีการเรียก setTitle() ด้วย ทรัพยากรที่ถอนออกได้ต้องมีขนาด 52 dp สูง
  • setTitle() ตั้งค่าสตริงชื่อที่มุมขวาบนของส่วนการเรียกดู นอกจาก มีการเรียก setBadgeDrawable()
  • setHeadersState() และ setHeadersTransitionOnBackEnabled() ซ่อนหรือปิดใช้ส่วนหัว ดูส่วนซ่อนหรือปิดใช้ส่วนหัวสำหรับข้อมูลเพิ่มเติม
  • setBrandColor() จะกำหนดสีพื้นหลังสำหรับองค์ประกอบ UI ในส่วนการเรียกดู โดยเฉพาะส่วนหัว สีพื้นหลังของส่วนด้วยค่าสีที่ระบุ
  • setSearchAffordanceColor() กำหนดสีของไอคอนการค้นหาด้วยค่าสีที่ระบุ ไอคอนค้นหา จะปรากฏขึ้นที่มุมซ้ายบนของส่วนการเรียกดูดังที่แสดงในรูปที่ 1 และ 2

ปรับแต่งมุมมองส่วนหัว

ส่วนการเรียกดูที่แสดงในรูปที่ 1 จะแสดงชื่อหมวดหมู่วิดีโอ ซึ่งเป็นส่วนหัวของแถวในฐานข้อมูลวิดีโอในมุมมองข้อความ คุณยังสามารถปรับแต่ง เพื่อรวมมุมมองเพิ่มเติมในเลย์เอาต์ที่ซับซ้อนมากขึ้น ส่วนต่อไปนี้จะแสดงวิธีการ มีมุมมองรูปภาพที่แสดงไอคอนข้างชื่อหมวดหมู่ ดังที่แสดงในรูปที่ 2

หน้าจอหลักของแอป

รูปที่ 2 ส่วนหัวของแถวในส่วนการเรียกดูที่มีทั้งไอคอน และป้ายกำกับข้อความ

เลย์เอาต์สำหรับส่วนหัวของแถวจะได้รับการกำหนดดังต่อไปนี้

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/header_icon"
        android:layout_width="32dp"
        android:layout_height="32dp" />
    <TextView
        android:id="@+id/header_label"
        android:layout_marginTop="6dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

ใช้ Presenter และใช้ วิธีการเชิงนามธรรมในการสร้าง เชื่อมโยง และยกเลิกการเชื่อมโยงผู้ถือมุมมอง ดังต่อไปนี้ ตัวอย่างแสดงวิธีเชื่อมโยงผู้ถือการดูที่มี 2 มุมมอง ImageView และ TextView

Kotlin

class IconHeaderItemPresenter : Presenter() {

    override fun onCreateViewHolder(viewGroup: ViewGroup): Presenter.ViewHolder {
        val view = LayoutInflater.from(viewGroup.context).run {
            inflate(R.layout.icon_header_item, null)
        }

        return Presenter.ViewHolder(view)
    }


    override fun onBindViewHolder(viewHolder: Presenter.ViewHolder, o: Any) {
        val headerItem = (o as ListRow).headerItem
        val rootView = viewHolder.view

        rootView.findViewById<ImageView>(R.id.header_icon).apply {
            rootView.resources.getDrawable(R.drawable.ic_action_video, null).also { icon ->
                setImageDrawable(icon)
            }
        }

        rootView.findViewById<TextView>(R.id.header_label).apply {
            text = headerItem.name
        }
    }

    override fun onUnbindViewHolder(viewHolder: Presenter.ViewHolder) {
        // no-op
    }
}

Java

public class IconHeaderItemPresenter extends Presenter {
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());

        View view = inflater.inflate(R.layout.icon_header_item, null);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, Object o) {
        HeaderItem headerItem = ((ListRow) o).getHeaderItem();
        View rootView = viewHolder.view;

        ImageView iconView = (ImageView) rootView.findViewById(R.id.header_icon);
        Drawable icon = rootView.getResources().getDrawable(R.drawable.ic_action_video, null);
        iconView.setImageDrawable(icon);

        TextView label = (TextView) rootView.findViewById(R.id.header_label);
        label.setText(headerItem.getName());
    }

    @Override
    public void onUnbindViewHolder(ViewHolder viewHolder) {
    // no-op
    }
}

ส่วนหัวจะต้องสามารถโฟกัสได้ จึงจะใช้ D-pad เพื่อ ให้เลื่อนดู การจัดการการดำเนินการนี้ทำได้ 2 วิธี

  • ตั้งค่ามุมมองให้โฟกัสได้ใน onBindViewHolder()

    Kotlin

    override fun onBindViewHolder(viewHolder: Presenter.ViewHolder, o: Any) {
        val headerItem = (o as ListRow).headerItem
        val rootView = viewHolder.view
    
        rootView.focusable = View.FOCUSABLE
        // ...
    }
    

    Java

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, Object o) {
        HeaderItem headerItem = ((ListRow) o).getHeaderItem();
        View rootView = viewHolder.view;
        rootView.setFocusable(View.FOCUSABLE) // Allows the D-Pad to navigate to this header item
        // ...
    }
    
  • ตั้งค่าเลย์เอาต์ให้โฟกัสได้ โดยทำดังนี้
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       ...
       android:focusable="true">

สุดท้าย ในการใช้งาน BrowseSupportFragment ที่แสดง เบราว์เซอร์แคตตาล็อก ให้ใช้ setHeaderPresenterSelector() เพื่อตั้งค่าผู้นำเสนอสำหรับส่วนหัวของแถว ดังที่ปรากฏในตัวอย่างต่อไปนี้

Kotlin

setHeaderPresenterSelector(object : PresenterSelector() {
    override fun getPresenter(o: Any): Presenter {
        return IconHeaderItemPresenter()
    }
})

Java

setHeaderPresenterSelector(new PresenterSelector() {
    @Override
    public Presenter getPresenter(Object o) {
        return new IconHeaderItemPresenter();
    }
});

ดูตัวอย่างที่สมบูรณ์ได้ที่ แอปตัวอย่าง Leanback ที่ใช้เวลาเพียง 2 นาที

ซ่อนหรือปิดใช้ส่วนหัว

บางครั้งคุณไม่ต้องการให้ส่วนหัวของแถวปรากฏ เช่น เมื่อมีจำนวนไม่เพียงพอ หมวดหมู่ที่ต้องการรายการที่เลื่อนได้ โทรหา BrowseSupportFragment.setHeadersState() ในระหว่าง onActivityCreated() ของส่วนย่อย ในการซ่อนหรือปิดใช้ส่วนหัวของแถว setHeadersState() เมธอดจะกำหนดสถานะเริ่มต้นของส่วนหัวในส่วนย่อยการเรียกดู โดยเป็นอย่างใดอย่างหนึ่งต่อไปนี้ ค่าคงที่ที่เป็นพารามิเตอร์

  • HEADERS_ENABLED: เมื่อสร้างกิจกรรมส่วนย่อยของการเรียกดู ส่วนหัวจะถูกเปิดใช้งานและแสดงโดย "ค่าเริ่มต้น" ส่วนหัวจะปรากฏในรูปที่ 1 และ 2 ในหน้านี้
  • HEADERS_HIDDEN: เมื่อมีการสร้างกิจกรรมส่วนย่อยของการเรียกดู ส่วนหัวจะเปิดใช้และซ่อนโดยค่าเริ่มต้น ส่วนหัวของหน้าจอยุบดังที่แสดงใน รูปในส่วนแสดงมุมมองการ์ด ผู้ใช้สามารถเลือกส่วนหัวที่ยุบเพื่อขยายได้
  • HEADERS_DISABLED: เมื่อมีการสร้างกิจกรรมส่วนย่อยของการเรียกดู ส่วนหัวจะถูกปิดใช้งานโดยค่าเริ่มต้นและ ไม่แสดง

หากมีการตั้งค่า HEADERS_ENABLED หรือ HEADERS_HIDDEN ไว้ คุณสามารถโทรหา setHeadersTransitionOnBackEnabled() เพื่อรองรับการย้ายกลับไปที่ส่วนหัวของแถวจากรายการเนื้อหาที่เลือกในแถว เปิดใช้โดย เป็นค่าเริ่มต้นถ้าคุณไม่ได้เรียกใช้เมธอด ในการจับการเคลื่อนไหวด้านหลังด้วยตนเอง ผ่าน false ไปยัง setHeadersTransitionOnBackEnabled() และใช้งานการจัดการ Back Stack ของคุณเอง

แสดงรายการสื่อ

BrowseSupportFragment ให้คุณ กำหนดและแสดงหมวดหมู่เนื้อหาสื่อที่เรียกดูได้และรายการสื่อจาก แคตตาล็อกสื่อโดยใช้อะแดปเตอร์และผู้นำเสนอ อะแดปเตอร์ช่วยให้คุณเชื่อมต่อได้ ลงในแหล่งข้อมูลท้องถิ่นหรือออนไลน์ที่มีข้อมูลแคตตาล็อกสื่อของคุณ อะแดปเตอร์จะใช้ตัวนำเสนอในการสร้างมุมมองและเชื่อมโยงข้อมูลกับมุมมองเหล่านั้น การแสดงรายการบนหน้าจอ

โค้ดตัวอย่างต่อไปนี้แสดงการใช้งาน Presenter สำหรับการแสดงข้อมูลสตริง

Kotlin

private const val TAG = "StringPresenter"

class StringPresenter : Presenter() {

    override fun onCreateViewHolder(parent: ViewGroup): Presenter.ViewHolder {
        val textView = TextView(parent.context).apply {
            isFocusable = true
            isFocusableInTouchMode = true
            background = parent.resources.getDrawable(R.drawable.text_bg)
        }
        return Presenter.ViewHolder(textView)
    }

    override fun onBindViewHolder(viewHolder: Presenter.ViewHolder, item: Any) {
        (viewHolder.view as TextView).text = item.toString()
    }

    override fun onUnbindViewHolder(viewHolder: Presenter.ViewHolder) {
        // no op
    }
}

Java

public class StringPresenter extends Presenter {
    private static final String TAG = "StringPresenter";

    public ViewHolder onCreateViewHolder(ViewGroup parent) {
        TextView textView = new TextView(parent.getContext());
        textView.setFocusable(true);
        textView.setFocusableInTouchMode(true);
        textView.setBackground(
                parent.getResources().getDrawable(R.drawable.text_bg));
        return new ViewHolder(textView);
    }

    public void onBindViewHolder(ViewHolder viewHolder, Object item) {
        ((TextView) viewHolder.view).setText(item.toString());
    }

    public void onUnbindViewHolder(ViewHolder viewHolder) {
        // no op
    }
}

เมื่อคุณสร้างชั้นเรียนผู้นำเสนอสำหรับรายการสื่อแล้ว คุณสามารถสร้าง อะแดปเตอร์และต่อเข้ากับ BrowseSupportFragment เพื่อแสดงรายการเหล่านั้นบนหน้าจอเพื่อให้ผู้ใช้เรียกดู ตัวอย่างต่อไปนี้ สาธิตวิธีสร้างอะแดปเตอร์เพื่อแสดงหมวดหมู่และรายการต่างๆ ในหมวดหมู่เหล่านั้นโดยใช้คลาส StringPresenter ที่แสดงใน ตัวอย่างโค้ดก่อนหน้า

Kotlin

private const val NUM_ROWS = 4
...
private lateinit var rowsAdapter: ArrayObjectAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    buildRowsAdapter()
}

private fun buildRowsAdapter() {
    rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
    for (i in 0 until NUM_ROWS) {
        val listRowAdapter = ArrayObjectAdapter(StringPresenter()).apply {
            add("Media Item 1")
            add("Media Item 2")
            add("Media Item 3")
        }
        HeaderItem(i.toLong(), "Category $i").also { header ->
            rowsAdapter.add(ListRow(header, listRowAdapter))
        }
    }
    browseSupportFragment.adapter = rowsAdapter
}

Java

private ArrayObjectAdapter rowsAdapter;
private static final int NUM_ROWS = 4;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    buildRowsAdapter();
}

private void buildRowsAdapter() {
    rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());

    for (int i = 0; i < NUM_ROWS; ++i) {
        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
                new StringPresenter());
        listRowAdapter.add("Media Item 1");
        listRowAdapter.add("Media Item 2");
        listRowAdapter.add("Media Item 3");
        HeaderItem header = new HeaderItem(i, "Category " + i);
        rowsAdapter.add(new ListRow(header, listRowAdapter));
    }

    browseSupportFragment.setAdapter(rowsAdapter);
}

ตัวอย่างนี้แสดงการใช้งานอะแดปเตอร์แบบคงที่ แอปพลิเคชันเรียกดูสื่อทั่วไป ใช้ข้อมูลจากฐานข้อมูลออนไลน์หรือบริการเว็บ ตัวอย่างเช่น แอปพลิเคชันท่องเว็บที่ ใช้ข้อมูลที่ดึงมาจากอินเทอร์เน็ต โปรดดู แอปตัวอย่าง Leanback ที่ใช้เวลาเพียง 2 นาที

อัปเดตพื้นหลัง

คุณอัปเดตพื้นหลังเพื่อเพิ่มความน่าสนใจของภาพลงในแอปการเรียกดูสื่อบนทีวีได้ ขณะผู้ใช้เรียกดูเนื้อหาต่างๆ เทคนิคนี้สามารถช่วยให้เกิดการโต้ตอบกับแอปมากขึ้น เหมือนในภาพยนตร์และเพลิดเพลิน

ชุดเครื่องมือ Leanback UI มีBackgroundManager สำหรับการเปลี่ยนพื้นหลังของกิจกรรมบนแอปทีวี ตัวอย่างต่อไปนี้จะแสดงวิธีการ สร้างวิธีง่ายๆ ในการอัปเดตพื้นหลังภายในกิจกรรมบนแอป TV ดังนี้

Kotlin

protected fun updateBackground(drawable: Drawable) {
    BackgroundManager.getInstance(this).drawable = drawable
}

Java

protected void updateBackground(Drawable drawable) {
    BackgroundManager.getInstance(this).setDrawable(drawable);
}

แอปการเรียกดูสื่อจำนวนมากจะอัปเดตพื้นหลังโดยอัตโนมัติเมื่อผู้ใช้ไปยังส่วนต่างๆ ผ่านรายการสื่อ คุณสามารถตั้งค่า Listener ที่เลือกโดยอัตโนมัติ อัปเดตพื้นหลังตามการเลือกปัจจุบันของผู้ใช้ ตัวอย่างต่อไปนี้จะแสดงวิธีการ เพื่อตั้งค่าชั้นเรียน OnItemViewSelectedListener ให้ ตรวจจับกิจกรรมการเลือกและอัปเดตพื้นหลัง

Kotlin

protected fun clearBackground() {
    BackgroundManager.getInstance(this).drawable = defaultBackground
}

protected fun getDefaultItemViewSelectedListener(): OnItemViewSelectedListener =
        OnItemViewSelectedListener { _, item, _, _ ->
            if (item is Movie) {
                item.getBackdropDrawable().also { background ->
                    updateBackground(background)
                }
            } else {
                clearBackground()
            }
        }

Java

protected void clearBackground() {
    BackgroundManager.getInstance(this).setDrawable(defaultBackground);
}

protected OnItemViewSelectedListener getDefaultItemViewSelectedListener() {
    return new OnItemViewSelectedListener() {
        @Override
        public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
                RowPresenter.ViewHolder rowViewHolder, Row row) {
            if (item instanceof Movie ) {
                Drawable background = ((Movie)item).getBackdropDrawable();
                updateBackground(background);
            } else {
                clearBackground();
            }
        }
    };
}

หมายเหตุ: ตัวอย่างการติดตั้งใช้งานก่อนหน้านี้คือตัวอย่างง่ายๆ เพื่อวัตถุประสงค์ต่อไปนี้ ภาพ เมื่อสร้างฟังก์ชันนี้ในแอปของคุณเอง ให้เรียกใช้ การดำเนินการอัปเดตในเบื้องหลังในชุดข้อความแยกต่างหากเพื่อประสิทธิภาพที่ดีขึ้น นอกจากนี้ หากคุณ วางแผนอัปเดตพื้นหลังเพื่อตอบสนองต่อผู้ใช้ที่เลื่อนดูรายการต่างๆ เพิ่ม ระยะเวลาเลื่อนการอัปเดตภาพพื้นหลังจนกว่าผู้ใช้จะตัดสินใจดำเนินการใดๆ เทคนิคนี้ช่วยเลี่ยง การอัปเดตภาพพื้นหลังมากเกินไป