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 umfangreichen Inhaltskatalog enthält, ist das Suchen nach einem bestimmten Titel für Nutzer möglicherweise nicht die effizienteste Methode, das Gesuchte zu finden. Mit einer Suchoberfläche können deine Nutzer schneller zu den gewünschten Inhalten gelangen als mit dem Surfen.

Die Androidx-Bibliothek für Leanback bietet eine Reihe von Klassen, mit denen Sie in Ihrer App eine Standardsuchoberfläche in Ihrer App aktivieren können, die mit anderen Suchfunktionen auf dem Fernseher übereinstimmt und Funktionen wie Spracheingabe bietet.

In diesem Leitfaden wird erläutert, wie Sie in Ihrer App mithilfe der Klassen der Leanback-Supportbibliothek eine Suchoberfläche 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:Du kannst die Farbe des Suchsymbols mithilfe der Methode setSearchAffordanceColor(int) festlegen.

Sucheingabe und Ergebnisse hinzufügen

Wenn ein Nutzer das Suchsymbol auswählt, ruft das System eine Suchaktivität mit dem definierten Intent auf. Verwenden Sie für Suchaktivitäten ein lineares Layout mit SearchFragment. Mit diesem Fragment muss auch die Schnittstelle SearchFragment.SearchResultProvider implementiert werden, damit die Ergebnisse einer Suche angezeigt werden können.

Das folgende Codebeispiel zeigt, wie die Klasse SearchFragment erweitert wird, 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 sollte mit einer SearchRunnable-Klasse verwendet werden, die die Suchanfrage in einem separaten Thread ausführt. Mit dieser Technik wird verhindert, dass Abfragen mit potenziell langsamen Ausführungen den Hauptthread der Benutzeroberfläche blockieren.