3

N.B. It seems this functionality is now available in version 22.1.1 of the leanback support library making this question slightly out of date. However, the question still remains why is the public standard documentation ahead of publicly available library versions?

I'm browsing the API docs and I see there's this interface: OnChildLaidOutListener and then there's also this method HorizontalGridView#setOnChildLaidOutListener. I try to use them, but Android Studio says no such things exists. I look at the source code (in Studio) for the HorizontalGridView and there's nothing like this in there. I tried searching for different versions of the compatibility library, but to none of them have this functionality. From here I can see that this functionality was added on this commit Reduce memory consumption of DPAD scroll multiple column grid.

What's up with all this? They document all the yet unavailable some day to come APIs at the official Android API docs or why is this documented there? Or is there something wrong with my installation/configuration of Android Studio and it's just that I somehow have an old version of the support libraries there or what's going on?

I would really love to use this stuff... it's exactly what I need.

EDIT: Sample code to elaborate what I'm doing (though I still do not understand how that relates to the question of why according to the API docs these methods should be there, but at least I can't use them). So, the thing that I'm trying to solve is to programmatically initialise the GridView to a selected item and then call requestLayout on it, because otherwise the zoomed in view will be cut off from bottom.

public class MinimalisticLeanbackFragment extends Fragment {

    private HorizontalGridView gridView;
    private boolean positionInitied = false;

    public SimplifiedEpgFragment() {
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(android.support.v17.leanback.R.layout.lb_list_row, container, false);
    }

    public ItemBridgeAdapter initItemBridgeAdapter(ObjectAdapter objectAdapter) {
        ItemBridgeAdapter iba = new ItemBridgeAdapter(objectAdapter);

        ItemBridgeAdapter.Wrapper mWrapper = new ItemBridgeAdapter.Wrapper() {
            @Override
            public View createWrapper(View root) {
                ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext());
                wrapper.setLayoutParams(
                        new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                wrapper.initialize(needsDefaultShadow(), true, false);
                return wrapper;
            }
            @Override
            public void wrap(View wrapper, View wrapped) {
                ((ShadowOverlayContainer) wrapper).wrap(wrapped);
            }
        };

        iba.setWrapper(mWrapper);

        FocusHighlightHelper.setupBrowseItemFocusHighlight(iba, FocusHighlight.ZOOM_FACTOR_LARGE, false);

        return iba;
    }

    private boolean needsDefaultShadow() {
        return true;
    }

    private ObjectAdapter initObjectAdapter() {
        ContentsPresenter contentsPresenter = new ContentsPresenter();
        ArrayObjectAdapter contentsAdapter = new ArrayObjectAdapter(contentsPresenter);
        contentsAdapter.addAll(0, ProgramList.collectionList());
        return contentsAdapter;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        gridView = initGridView((HorizontalGridView) view.findViewById(R.id.row_content));

        ItemBridgeAdapter mBridgeAdapter = initItemBridgeAdapter(initObjectAdapter());

        gridView.setAdapter(mBridgeAdapter);
    }

    private HorizontalGridView initGridView(final HorizontalGridView gridView) {
        gridView.isLaidOut();
        ShadowOverlayContainer.prepareParentForShadow(gridView);
        gridView.setClipChildren(false);
        gridView.setFocusDrawingOrderEnabled(false); //Or?
        gridView.setOnChildSelectedListener(new OnChildSelectedListener() {
            @Override
            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
                Log.d(Configs.TAG, "Child selected");
            }
        });

        gridView.setFadingLeftEdge(false);
        gridView.setFadingRightEdge(false);

        //TODO: wtf? It seems the only way to do this would be to rewrite the entire HorizontalGridView and all of its dependencies injecting these newer
        //features this updated version.
        /*
        gridView.setOnChildLaidOutListener(new android.support.v17.leanback.widget.OnChildLaidOutListener() {
            @Override
            public void onChildLaidOut(ViewGroup parent, View view, int position, long id) {
                initGridState();
            }
        });
        */

        //Maybe this could work then...
        final ViewTreeObserver viewTreeObserver = gridView.getViewTreeObserver();
        viewTreeObserver.addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
            @Override
            public void onDraw() {
                if (initGridState()) {
                    Log.d(Configs.TAG, "state init succeeded!");
                    viewTreeObserver.removeOnDrawListener(this);
                } else {
                    Log.d(Configs.TAG, "onDraw of the gridview, children not ready yet..");
                }
            }
        });

        return gridView;
    }

    private boolean initGridState() {
        int position = gridView.getSelectedPosition();
        if (position == RecyclerView.NO_POSITION) {
            position = 0;
            gridView.setSelectedPosition(0);
        }
        if (!this.positionInitied) {
            View child = gridView.getChildAt(position);
            if (child != null) {
                Log.d(Configs.TAG, "Child available, requesting focus the the selected position...");
                child.requestFocus();
                gridView.requestLayout();
            } else {
                Log.e(Configs.TAG, "Could not focus to child... grid has: " + gridView.getChildCount()+" children, is " + (gridView.isActivated() ? "" : " not ") + "activated");
                return false;
            }
        } else {
            Log.d(Configs.TAG, "Child focus already inited... doing nothing..");
        }
        return true;
    }
}
Timo
  • 3,335
  • 30
  • 25
  • 1
    Could you be more specific (e.g., with some code snippets)? How are you trying to access the `HorizontalGridView`? – Sebastiano May 06 '15 at 12:19
  • Not really sure how does that matter, but I guess I can elaborate this a bit.. – Timo May 06 '15 at 12:23
  • Because, as far as I know, you do not have access to `HorizontalGridView` or `VerticalGridView` instances from the Leanback widgets (e.g., you cannot retrieve the `VerticalGridView` instance from a `VerticalGridFragment`). – Sebastiano May 06 '15 at 12:24
  • I'm not using the VerticalGridFragment. I have my own fragment. And in fact there is actually a way to get it even with the VerticalGridFragment (though using it is probably not wise and may cause some unpredictable side effects), though it's a bit tricky, you can extend the ListRowPresenter override the createRowViewHolder method and call super impl, cast the result to ListRowPresenter.ViewHolder and call getGridView(). :) I used that method to experiment with rows that have internally two rows. – Timo May 06 '15 at 12:31
  • 1
    Either that, or retrieve the GridView via Reflection. Anyway, if you could elaborate a little bit more with some code, that would be great. – Sebastiano May 06 '15 at 12:32

0 Answers0