18

I'm using the Google Leanback widgets in an Android TV application. It utilizes a RowsFragment with ListRows in it.

What I'm trying to determine is if there is any way to programmatically scroll to a particular object within one of the rows. I've dug into the docs for the Leanback widgets but cannot find what I'm looking for.

Alex Styl
  • 3,982
  • 2
  • 28
  • 47
ebr
  • 323
  • 3
  • 10

5 Answers5

17

I had a similar necessity: I needed to set the initial selected item in a ListRow. I ended up subclassing the ListRowPresenter like this:

import android.support.v17.leanback.widget.ListRowPresenter;
import android.support.v17.leanback.widget.RowPresenter;

public class CustomPresenter extends ListRowPresenter {

    private int mInitialSelectedPosition;

    public CustomPresenter(int position) {
        this.mInitialSelectedPosition = position;
    }

    @Override
    protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
        super.onBindRowViewHolder(holder, item);

        ViewHolder vh = (ListRowPresenter.ViewHolder) holder;
        vh.getGridView().setSelectedPosition(mInitialSelectedPosition);
    }

}

Hopefully this will help you.

GerryP
  • 241
  • 2
  • 5
  • 1
    Thanks, I think that gives me the information I'll need to do what I wanted. – ebr Jun 13 '15 at 18:07
  • 1
    The example is really good, it is also possible to modify the logic behind the first item to select. Thanks – Massimo Sep 26 '16 at 10:05
11

In the latest version of Leanback (think v23.3.0+), you can now specify not only the row position but also perform optional tasks on the row. In your case, the task would be programmatic selection like so:

BrowseFragment.setSelectedPosition(0, true, new ListRowPresenter.SelectItemViewHolderTask(2));

No need to implement custom list row presenters or anything

kip2
  • 6,473
  • 4
  • 55
  • 72
  • 3
    Same line of code in my onActivityResult gives: IllegalStateException: Cannot start headers transition; any help? – Uniruddh Dec 22 '16 at 12:20
6

I've done it when I needed to implement "Return to the first item in a Row by pressing Back".

I was calling this method from Activity's onBackPressed().

If this method returns false we call Activity.super.onBackPressed(). If true - we don't.

    public boolean onBackPressed(){
        boolean consumeBack;

        int selectedRowPosition = getRowsFragment().getSelectedPosition();

        ListRowPresenter.ViewHolder selectedRow = (ListRowPresenter.ViewHolder) getRowsFragment().getRowViewHolder(selectedRowPosition);
        int selectedItemPosition = selectedRow.getSelectedPosition();

        if(selectedItemPosition == 0){
            consumeBack = false;
        } else {
            consumeBack = true;
            getRowsFragment().setSelectedPosition(selectedRowPosition, true, new ListRowPresenter.SelectItemViewHolderTask(0));
        }
        return consumeBack;
}

Instead of "0" you can set any position you need.

Danylo Volokh
  • 4,149
  • 2
  • 33
  • 40
0

This answer is suggesting the usage of the latest androidx.leanback library.

In your BrowseSupportFragment create a class variable of type HeadersSupportFragment. After creating your ArrayObjectAdapter and using it by setAdapter(), call the getHeadersSupportFragment(). Then call getSelectedPosition() to get the current selected position and store it in Preferences. Later, use setSelectedPosition() to set the previous position.

Here is an example:


private HeadersSupportFragment hsp;  
private ArrayObjectAdapter mRowsAdapter;

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

        mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
        setAdapter(mRowsAdapter);

        hsp = getHeadersSupportFragment();

        int lastPosition = getSharedPreferences(CONTEXT).getInt(LAST_NUMBER, 0);
        hsp.setSelectedPosition(lastPosition);

}

  @Override
    public void onPause() {
        super.onPause();

        if(hsp != null){
            getSharedPreferences(CONTEXT).edit().putInt(LAST_NUMBER, hsp.getSelectedPosition()).commit();
         
        }

    }

taxo
  • 539
  • 1
  • 3
  • 21
0

If your headersState is enabled, use

SelectItemViewHolderTask task = new SelectItemViewHolderTask(positionX)
boolean isSmoothScroll = false // If you need to ignore the animation
task.setSmoothScroll(isSmothScroll)  
setSelectedPosition(positionY, isSmothScroll, task)

However, if your headersState is disabled, then using this code will cause an exception: IllegalStateException: Cannot start headers transition.
In this case you need to use this instead:

getRowsSupportFragment().setSelectedPosition(positionY, isSmothScroll, task)

The difference between them is whether the HeadersSupportFragment is updated or not.