I'm hoping the wisdom of the crowd can help me solve a strange problem. I have a very basic ATV Leanback App using androidx.leanback.app.BrowseSupportFragment.
I have subclassed the BrowseSupportFragment and everything works fine. That is until I set up either a setOnHeaderViewSelectedListener or a setOnHeaderClickedListener. Setting either one Breaks the normal "out of the box" navigation.
What I would like to accomplish is setting up either a setOnHeaderViewSelectedListener or a setOnHeaderClickedListener so I can monitor these events without breaking the normal "out of the box" navigation.
There is no super class to call so I can't do it that way. I'm posting the relevant code below and the full source code is readily available online. What am I missing?
Note I have checked many other issues on Stackoverflow but I have not found any that address this issue with an actual working fix. e.g. Adding a listener and still have the normal "out of the box" navigation work exactly the same as in did before the listener was added.
I'm wondering if I'm going to be forced to just copy the entire androidx.leanback.app.BrowseSupportFragment and /or androidx.leanback.app.HeadersSupportFragment source as a way forward but that just does not seem right.
Thank you for your help.
My code
public class WatchTVFragment extends BrowseSupportFragment {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (getHeadersSupportFragment() != null){
getHeadersSupportFragment().setOnHeaderClickedListener(new HeadersSupportFragment.OnHeaderClickedListener() {
@Override
public void onHeaderClicked(RowHeaderPresenter.ViewHolder viewHolder, Row row) {
Log.d("WatchTVFragment", "=============> onHeaderClicked");
}
});
getHeadersSupportFragment().setOnHeaderViewSelectedListener(new HeadersSupportFragment.OnHeaderViewSelectedListener() {
@Override
public void onHeaderSelected(RowHeaderPresenter.ViewHolder viewHolder, Row row) {
// catch your item by row.getId();
Log.d("WatchTVFragment", "=============> onHeaderSelected");
//return;
}
});
}
Snippets from androidx/leanback/app/HeadersSupportFragment.java
public void setOnHeaderViewSelectedListener(OnHeaderViewSelectedListener listener) {
mOnHeaderViewSelectedListener = listener;
}
/**
* Interface definition for a callback to be invoked when a header item is selected.
*/
public interface OnHeaderViewSelectedListener {
/**
* Called when a header item has been selected.
*
* @param viewHolder Row ViewHolder object corresponding to the selected Header.
* @param row Row object corresponding to the selected Header.
*/
void onHeaderSelected(RowHeaderPresenter.ViewHolder viewHolder, Row row);
}
private OnHeaderViewSelectedListener mOnHeaderViewSelectedListener;
@Override
void onRowSelected(RecyclerView parent, RecyclerView.ViewHolder viewHolder,
int position, int subposition) {
if (mOnHeaderViewSelectedListener != null) {
if (viewHolder != null && position >= 0) {
ItemBridgeAdapter.ViewHolder vh = (ItemBridgeAdapter.ViewHolder) viewHolder;
mOnHeaderViewSelectedListener.onHeaderSelected(
(RowHeaderPresenter.ViewHolder) vh.getViewHolder(), (Row) vh.getItem());
} else {
mOnHeaderViewSelectedListener.onHeaderSelected(null, null);
}
}
}
Snippets from androidx/leanback/app/BrowseSupportFragment.java
HeadersSupportFragment mHeadersSupportFragment;
/**
* Get currently bound HeadersSupportFragment or null if HeadersSupportFragment has not been created yet.
* @return Currently bound HeadersSupportFragment or null if HeadersSupportFragment has not been created yet.
*/
public HeadersSupportFragment getHeadersSupportFragment() {
return mHeadersSupportFragment;
}
private HeadersSupportFragment.OnHeaderViewSelectedListener mHeaderViewSelectedListener =
new HeadersSupportFragment.OnHeaderViewSelectedListener() {
@Override
public void onHeaderSelected(RowHeaderPresenter.ViewHolder viewHolder, Row row) {
int position = mHeadersSupportFragment.getSelectedPosition();
if (DEBUG) Log.v(TAG, "header selected position " + position);
// Layout of Headers Fragment in hidden state may triggers the onRowSelected and
// reset to 0. Skip in that case.
if (mShowingHeaders) {
onRowSelected(position);
}
}
};
Just Following up...
I have not found a solution yet but I came across this post Building for Android TV — Episode 4 that referenced this same issue and had a solution. The only problem is this only works for leanback-v17:22.1.1
Will follow up if I can get a work around.