BaseRowSupportFragment.java revision 0d841b3454f896da58deb506ca22730bfd04f34f
1/* This file is auto-generated from BaseRowFragment.java.  DO NOT MODIFY. */
2
3/*
4 * Copyright (C) 2014 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7 * in compliance with the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software distributed under the License
12 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13 * or implied. See the License for the specific language governing permissions and limitations under
14 * the License.
15 */
16package android.support.v17.leanback.app;
17
18import android.support.v4.app.Fragment;
19import android.os.Bundle;
20import android.support.v17.leanback.widget.ItemBridgeAdapter;
21import android.support.v17.leanback.widget.ListRow;
22import android.support.v17.leanback.widget.ObjectAdapter;
23import android.support.v17.leanback.widget.OnChildViewHolderSelectedListener;
24import android.support.v17.leanback.widget.PresenterSelector;
25import android.support.v17.leanback.widget.Row;
26import android.support.v17.leanback.widget.VerticalGridView;
27import android.support.v7.widget.RecyclerView;
28import android.view.LayoutInflater;
29import android.view.View;
30import android.view.ViewGroup;
31
32/**
33 * An internal base class for a fragment containing a list of rows.
34 */
35abstract class BaseRowSupportFragment extends Fragment {
36    private static final String CURRENT_SELECTED_POSITION = "currentSelectedPosition";
37    private ObjectAdapter mAdapter;
38    private VerticalGridView mVerticalGridView;
39    private PresenterSelector mPresenterSelector;
40    private ItemBridgeAdapter mBridgeAdapter;
41    private int mSelectedPosition = -1;
42    private boolean mPendingTransitionPrepare;
43    private LateSelectionObserver mLateSelectionObserver = new LateSelectionObserver();
44
45    abstract int getLayoutResourceId();
46
47    private final OnChildViewHolderSelectedListener mRowSelectedListener =
48            new OnChildViewHolderSelectedListener() {
49                @Override
50                public void onChildViewHolderSelected(RecyclerView parent,
51                        RecyclerView.ViewHolder view, int position, int subposition) {
52                    mSelectedPosition = position;
53                    onRowSelected(parent, view, position, subposition);
54                }
55            };
56
57    void onRowSelected(RecyclerView parent, RecyclerView.ViewHolder view,
58            int position, int subposition) {
59    }
60
61    @Override
62    public View onCreateView(LayoutInflater inflater, ViewGroup container,
63            Bundle savedInstanceState) {
64        View view = inflater.inflate(getLayoutResourceId(), container, false);
65        mVerticalGridView = findGridViewFromRoot(view);
66        if (mPendingTransitionPrepare) {
67            mPendingTransitionPrepare = false;
68            onTransitionPrepare();
69        }
70        return view;
71    }
72
73    VerticalGridView findGridViewFromRoot(View view) {
74        return (VerticalGridView) view;
75    }
76
77    @Override
78    public void onViewCreated(View view, Bundle savedInstanceState) {
79        if (savedInstanceState != null) {
80            mSelectedPosition = savedInstanceState.getInt(CURRENT_SELECTED_POSITION, -1);
81        }
82        if (mBridgeAdapter != null) {
83            setAdapterAndSelection();
84        }
85        mVerticalGridView.setOnChildViewHolderSelectedListener(mRowSelectedListener);
86    }
87
88    /**
89     * This class waits for the adapter to be updated before setting the selected
90     * row.
91     */
92    private class LateSelectionObserver extends RecyclerView.AdapterDataObserver {
93        boolean mIsLateSelection = false;
94
95        public void onChanged() {
96            performLateSelection();
97        }
98
99        public void onItemRangeInserted(int positionStart, int itemCount) {
100            performLateSelection();
101        }
102
103        void startLateSelection() {
104            mIsLateSelection = true;
105            mBridgeAdapter.registerAdapterDataObserver(this);
106        }
107
108        void performLateSelection() {
109            clear();
110            if (mVerticalGridView != null) {
111                mVerticalGridView.setSelectedPosition(mSelectedPosition);
112            }
113        }
114
115        void clear() {
116            if (mIsLateSelection) {
117                mIsLateSelection = false;
118                mBridgeAdapter.unregisterAdapterDataObserver(this);
119            }
120        }
121    }
122
123    void setAdapterAndSelection() {
124        mVerticalGridView.setAdapter(mBridgeAdapter);
125        // We don't set the selected position unless we've data in the adapter.
126        boolean lateSelection = mBridgeAdapter.getItemCount() == 0 && mSelectedPosition >= 0;
127        if (lateSelection) {
128            mLateSelectionObserver.startLateSelection();
129        } else if (mSelectedPosition >= 0) {
130            mVerticalGridView.setSelectedPosition(mSelectedPosition);
131        }
132    }
133
134    @Override
135    public void onDestroyView() {
136        super.onDestroyView();
137        mLateSelectionObserver.clear();
138        mVerticalGridView = null;
139    }
140
141    @Override
142    public void onSaveInstanceState(Bundle outState) {
143        super.onSaveInstanceState(outState);
144        outState.putInt(CURRENT_SELECTED_POSITION, mSelectedPosition);
145    }
146
147    /**
148     * Set the presenter selector used to create and bind views.
149     */
150    public final void setPresenterSelector(PresenterSelector presenterSelector) {
151        mPresenterSelector = presenterSelector;
152        updateAdapter();
153    }
154
155    /**
156     * Get the presenter selector used to create and bind views.
157     */
158    public final PresenterSelector getPresenterSelector() {
159        return mPresenterSelector;
160    }
161
162    /**
163     * Sets the adapter for the fragment.
164     */
165    public final void setAdapter(ObjectAdapter rowsAdapter) {
166        mAdapter = rowsAdapter;
167        updateAdapter();
168    }
169
170    /**
171     * Returns the list of rows.
172     */
173    public final ObjectAdapter getAdapter() {
174        return mAdapter;
175    }
176
177    /**
178     * Returns the bridge adapter.
179     */
180    final ItemBridgeAdapter getBridgeAdapter() {
181        return mBridgeAdapter;
182    }
183
184    /**
185     * Sets the selected row position with smooth animation.
186     */
187    public void setSelectedPosition(int position) {
188        setSelectedPosition(position, true);
189    }
190
191    /**
192     * Gets position of currently selected row.
193     * @return Position of currently selected row.
194     */
195    public int getSelectedPosition() {
196        return mSelectedPosition;
197    }
198
199    /**
200     * Sets the selected row position.
201     */
202    public void setSelectedPosition(int position, boolean smooth) {
203        if (mSelectedPosition == position) {
204            return;
205        }
206        mSelectedPosition = position;
207        if(mVerticalGridView != null && mVerticalGridView.getAdapter() != null) {
208            if (mLateSelectionObserver.mIsLateSelection) {
209                return;
210            }
211            if (smooth) {
212                mVerticalGridView.setSelectedPositionSmooth(position);
213            } else {
214                mVerticalGridView.setSelectedPosition(position);
215            }
216        }
217    }
218
219    final VerticalGridView getVerticalGridView() {
220        return mVerticalGridView;
221    }
222
223    void updateAdapter() {
224        if (mBridgeAdapter != null) {
225            // detach observer from ObjectAdapter
226            mLateSelectionObserver.clear();
227            mBridgeAdapter.clear();
228            mBridgeAdapter = null;
229        }
230
231        if (mAdapter != null) {
232            // If presenter selector is null, adapter ps will be used
233            mBridgeAdapter = new ItemBridgeAdapter(mAdapter, mPresenterSelector);
234        }
235        if (mVerticalGridView != null) {
236            setAdapterAndSelection();
237        }
238    }
239
240    Object getItem(Row row, int position) {
241        if (row instanceof ListRow) {
242            return ((ListRow) row).getAdapter().get(position);
243        } else {
244            return null;
245        }
246    }
247
248    public boolean onTransitionPrepare() {
249        if (mVerticalGridView != null) {
250            mVerticalGridView.setAnimateChildLayout(false);
251            mVerticalGridView.setScrollEnabled(false);
252            return true;
253        }
254        mPendingTransitionPrepare = true;
255        return false;
256    }
257
258    public void onTransitionStart() {
259        if (mVerticalGridView != null) {
260            mVerticalGridView.setPruneChild(false);
261            mVerticalGridView.setLayoutFrozen(true);
262            mVerticalGridView.setFocusSearchDisabled(true);
263        }
264    }
265
266    public void onTransitionEnd() {
267        // be careful that fragment might be destroyed before header transition ends.
268        if (mVerticalGridView != null) {
269            mVerticalGridView.setLayoutFrozen(false);
270            mVerticalGridView.setAnimateChildLayout(true);
271            mVerticalGridView.setPruneChild(true);
272            mVerticalGridView.setFocusSearchDisabled(false);
273            mVerticalGridView.setScrollEnabled(true);
274        }
275    }
276
277    public void setAlignment(int windowAlignOffsetTop) {
278        if (mVerticalGridView != null) {
279            // align the top edge of item
280            mVerticalGridView.setItemAlignmentOffset(0);
281            mVerticalGridView.setItemAlignmentOffsetPercent(
282                    VerticalGridView.ITEM_ALIGN_OFFSET_PERCENT_DISABLED);
283
284            // align to a fixed position from top
285            mVerticalGridView.setWindowAlignmentOffset(windowAlignOffsetTop);
286            mVerticalGridView.setWindowAlignmentOffsetPercent(
287                    VerticalGridView.WINDOW_ALIGN_OFFSET_PERCENT_DISABLED);
288            mVerticalGridView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE);
289        }
290    }
291}
292