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