Rechercher dans les applis TV

Les utilisateurs ont souvent des contenus spécifiques en tête lorsqu'ils utilisent une application multimédia sur leur téléviseur. Si votre application contient un vaste catalogue de contenus, la recherche d'un titre spécifique n'est pas forcément le moyen le plus efficace aux utilisateurs de trouver ce qu'ils cherchent. Une interface de recherche peut aider vos utilisateurs à accéder plus rapidement que la navigation.

La bibliothèque androidx.leanback fournit un ensemble de classes pour permettre une interface de recherche standard dans votre application, qui est cohérente avec les autres fonctions de recherche sur téléviseur et offre des fonctionnalités telles que saisie vocale.

Ce guide explique comment fournir une interface de recherche dans votre application à l'aide de la compatibilité avec Leanback. les classes de bibliothèque.

Ajouter une action de recherche

Lorsque vous utilisez la classe BrowseFragment pour un contenu multimédia de navigation, vous pouvez activer une interface de recherche de commande. L'interface de recherche est une icône qui apparaît dans la mise en page lorsque vous définissez View.OnClickListener sur BrowseFragment. . L'exemple de code suivant illustre cette technique.

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());
}

Remarque:Vous pouvez définir la couleur de l'icône de recherche à l'aide des boutons setSearchAffordanceColor(int) .

Ajouter un champ de recherche et des résultats

Lorsqu'un utilisateur sélectionne l'icône de recherche, le système appelle une activité de recherche à l'aide de la méthode un intent défini. Pour votre activité de recherche, utilisez une mise en page linéaire contenant SearchFragment Ce fragment doit également implémenter le SearchFragment.SearchResultProvider. pour afficher les résultats d'une recherche.

L'exemple de code suivant montre comment étendre la classe SearchFragment. pour fournir une interface et des résultats de recherche:

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;
    }
}

L'exemple de code précédent est destiné à être utilisé avec une classe SearchRunnable. qui exécute la requête de recherche sur un thread distinct. Cette technique ralentit potentiellement les requêtes de bloquer le thread principal de l'interface utilisateur.