In TV-Apps suchen

Nutzer haben häufig bestimmte Inhalte im Kopf, wenn sie eine Medien-App auf dem Fernseher verwenden. Wenn deine App einen großen Inhaltskatalog enthält, ist die Suche nach einem bestimmten Titel für Nutzer möglicherweise nicht die effizienteste Möglichkeit, um das Gesuchte zu finden. Mit einer Suchoberfläche können Nutzer schneller die gewünschten Inhalte finden als durchstöbern.

Die androidx.leanback-Bibliothek bietet eine Reihe von Klassen, die eine Standardsuchoberfläche in deiner App ermöglichen, die mit anderen Suchfunktionen auf Fernsehern in Einklang steht und Funktionen wie die Spracheingabe bietet.

In diesem Leitfaden wird erläutert, wie Sie mithilfe von Klassen der Leanback-Supportbibliothek eine Suchoberfläche in Ihrer App bereitstellen.

Suchaktion hinzufügen

Wenn Sie die Klasse BrowseFragment für eine Oberfläche zum Durchsuchen von Medien verwenden, können Sie eine Suchoberfläche als Standardteil der Benutzeroberfläche aktivieren. Die Suchoberfläche ist ein Symbol, das im Layout angezeigt wird, wenn du View.OnClickListener für das BrowseFragment-Objekt festlegst. Der folgende Beispielcode veranschaulicht diese Technik.

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.browse_activity)
    browseFragment = fragmentManager.findFragmentById(R.id.browse_fragment) as BrowseFragment
    browseFragment.setOnSearchClickedListener { view ->
        val intent = Intent(this@BrowseActivity, SearchActivity::class.java)
        startActivity(intent)
    }

    browseFragment.setAdapter(buildAdapter())
}

Java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.browse_activity);

    browseFragment = (BrowseFragment)
            getFragmentManager().findFragmentById(R.id.browse_fragment);

    ...

    browseFragment.setOnSearchClickedListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(BrowseActivity.this, SearchActivity.class);
            startActivity(intent);
        }
    });

    browseFragment.setAdapter(buildAdapter());
}

Hinweis:Sie können die Farbe des Suchsymbols mit der Methode setSearchAffordanceColor(int) festlegen.

Sucheingaben und -ergebnisse hinzufügen

Wenn ein Nutzer das Suchsymbol auswählt, ruft das System mit dem definierten Intent eine Suchaktivität auf. Verwende für deine Suchaktivitäten ein lineares Layout mit einem SearchFragment. Dieses Fragment muss auch die Schnittstelle SearchFragment.SearchResultProvider implementieren, damit die Ergebnisse einer Suche angezeigt werden.

Das folgende Codebeispiel zeigt, wie die Klasse SearchFragment erweitert werden kann, um eine Suchoberfläche und Ergebnisse bereitzustellen:

Kotlin

class MySearchFragment : SearchFragment(), SearchFragment.SearchResultProvider {
    private val rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
    private val handler = Handler()
    private val delayedLoad = SearchRunnable()

    val resultsAdapter: ObjectAdapter
    get() {
        return rowsAdapter
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setSearchResultProvider(this)
        setOnItemClickedListener(getDefaultItemClickedListener())
    }

    fun onQueryTextChange(newQuery: String): Boolean {
        rowsAdapter.clear()
        if (!TextUtils.isEmpty(newQuery)) {
            delayedLoad.setSearchQuery(newQuery)
            handler.removeCallbacks(delayedLoad)
            handler.postDelayed(delayedLoad, SEARCH_DELAY_MS)
        }
        return true
    }

    fun onQueryTextSubmit(query: String): Boolean {
        rowsAdapter.clear()
        if (!TextUtils.isEmpty(query)) {
            delayedLoad.setSearchQuery(query)
            handler.removeCallbacks(delayedLoad)
            handler.postDelayed(delayedLoad, SEARCH_DELAY_MS)
        }
        return true
    }

    companion object {
        private val SEARCH_DELAY_MS = 300
    }
}

Java

public class MySearchFragment extends SearchFragment
        implements SearchFragment.SearchResultProvider {

    private static final int SEARCH_DELAY_MS = 300;
    private ArrayObjectAdapter rowsAdapter;
    private Handler handler = new Handler();
    private SearchRunnable delayedLoad;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
        setSearchResultProvider(this);
        setOnItemClickedListener(getDefaultItemClickedListener());
        delayedLoad = new SearchRunnable();
    }

    @Override
    public ObjectAdapter getResultsAdapter() {
        return rowsAdapter;
    }

    @Override
    public boolean onQueryTextChange(String newQuery) {
        rowsAdapter.clear();
        if (!TextUtils.isEmpty(newQuery)) {
            delayedLoad.setSearchQuery(newQuery);
            handler.removeCallbacks(delayedLoad);
            handler.postDelayed(delayedLoad, SEARCH_DELAY_MS);
        }
        return true;
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        rowsAdapter.clear();
        if (!TextUtils.isEmpty(query)) {
            delayedLoad.setSearchQuery(query);
            handler.removeCallbacks(delayedLoad);
            handler.postDelayed(delayedLoad, SEARCH_DELAY_MS);
        }
        return true;
    }
}

Der vorherige Beispielcode soll mit einer SearchRunnable-Klasse verwendet werden, die die Suchanfrage in einem separaten Thread ausführt. Diese Technik verhindert, dass potenziell langsam ausgeführte Abfragen den Hauptthread der Benutzeroberfläche blockieren.