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  */
14 package android.support.v17.leanback.app;
15 
16 import android.support.v17.leanback.R;
17 import android.support.v17.leanback.widget.ObjectAdapter;
18 import android.support.v17.leanback.widget.OnItemClickedListener;
19 import android.support.v17.leanback.widget.OnItemSelectedListener;
20 import android.support.v17.leanback.widget.OnItemViewClickedListener;
21 import android.support.v17.leanback.widget.OnItemViewSelectedListener;
22 import android.support.v17.leanback.widget.Presenter;
23 import android.support.v17.leanback.widget.Row;
24 import android.support.v17.leanback.widget.RowPresenter;
25 import android.support.v17.leanback.widget.VerticalGridView;
26 import android.app.Fragment;
27 import android.os.Bundle;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 
32 /**
33  * Wrapper fragment for leanback details screens.
34  */
35 public class DetailsFragment extends BaseFragment {
36     private static final String TAG = "DetailsFragment";
37     private static boolean DEBUG = false;
38 
39     private class SetSelectionRunnable implements Runnable {
40         int mPosition;
41         boolean mSmooth = true;
42         @Override
run()43         public void run() {
44             mRowsFragment.setSelectedPosition(mPosition, mSmooth);
45         }
46     }
47 
48     private RowsFragment mRowsFragment;
49 
50     private ObjectAdapter mAdapter;
51     private int mContainerListAlignTop;
52     private OnItemSelectedListener mExternalOnItemSelectedListener;
53     private OnItemClickedListener mOnItemClickedListener;
54     private OnItemViewSelectedListener mExternalOnItemViewSelectedListener;
55     private OnItemViewClickedListener mOnItemViewClickedListener;
56     private int mSelectedPosition = -1;
57 
58     private Object mSceneAfterEntranceTransition;
59 
60     private final SetSelectionRunnable mSetSelectionRunnable = new SetSelectionRunnable();
61 
62     /**
63      * Sets the list of rows for the fragment.
64      */
setAdapter(ObjectAdapter adapter)65     public void setAdapter(ObjectAdapter adapter) {
66         mAdapter = adapter;
67         if (mRowsFragment != null) {
68             mRowsFragment.setAdapter(adapter);
69         }
70     }
71 
72     /**
73      * Returns the list of rows.
74      */
getAdapter()75     public ObjectAdapter getAdapter() {
76         return mAdapter;
77     }
78 
79     /**
80      * Sets an item selection listener.
81      * @deprecated Use {@link #setOnItemViewSelectedListener(OnItemViewSelectedListener)}
82      */
setOnItemSelectedListener(OnItemSelectedListener listener)83     public void setOnItemSelectedListener(OnItemSelectedListener listener) {
84         mExternalOnItemSelectedListener = listener;
85     }
86 
87     /**
88      * Sets an item Clicked listener.
89      * @deprecated Use {@link #setOnItemViewClickedListener(OnItemViewClickedListener)}
90      */
setOnItemClickedListener(OnItemClickedListener listener)91     public void setOnItemClickedListener(OnItemClickedListener listener) {
92         mOnItemClickedListener = listener;
93         if (mRowsFragment != null) {
94             mRowsFragment.setOnItemClickedListener(listener);
95         }
96     }
97 
98     /**
99      * Sets an item selection listener.
100      */
setOnItemViewSelectedListener(OnItemViewSelectedListener listener)101     public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
102         mExternalOnItemViewSelectedListener = listener;
103     }
104 
105     /**
106      * Sets an item Clicked listener.
107      */
setOnItemViewClickedListener(OnItemViewClickedListener listener)108     public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
109         mOnItemViewClickedListener = listener;
110         if (mRowsFragment != null) {
111             mRowsFragment.setOnItemViewClickedListener(listener);
112         }
113     }
114 
115     /**
116      * Returns the item Clicked listener.
117      * @deprecated Use {@link #getOnItemViewClickedListener()}
118      */
getOnItemClickedListener()119     public OnItemClickedListener getOnItemClickedListener() {
120         return mOnItemClickedListener;
121     }
122 
123     /**
124      * Returns the item Clicked listener.
125      */
getOnItemViewClickedListener()126     public OnItemViewClickedListener getOnItemViewClickedListener() {
127         return mOnItemViewClickedListener;
128     }
129 
130     @Override
onCreate(Bundle savedInstanceState)131     public void onCreate(Bundle savedInstanceState) {
132         super.onCreate(savedInstanceState);
133 
134         mContainerListAlignTop =
135             getResources().getDimensionPixelSize(R.dimen.lb_details_rows_align_top);
136     }
137 
138     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)139     public View onCreateView(LayoutInflater inflater, ViewGroup container,
140             Bundle savedInstanceState) {
141         View view = inflater.inflate(R.layout.lb_details_fragment, container, false);
142         mRowsFragment = (RowsFragment) getChildFragmentManager().findFragmentById(
143                 R.id.fragment_dock);
144         if (mRowsFragment == null) {
145             mRowsFragment = new RowsFragment();
146             getChildFragmentManager().beginTransaction()
147                     .replace(R.id.fragment_dock, mRowsFragment).commit();
148         }
149         mRowsFragment.setAdapter(mAdapter);
150         mRowsFragment.setOnItemSelectedListener(mExternalOnItemSelectedListener);
151         mRowsFragment.setOnItemViewSelectedListener(mExternalOnItemViewSelectedListener);
152         mRowsFragment.setOnItemClickedListener(mOnItemClickedListener);
153         mRowsFragment.setOnItemViewClickedListener(mOnItemViewClickedListener);
154         mSceneAfterEntranceTransition = sTransitionHelper.createScene((ViewGroup) view,
155                 new Runnable() {
156             @Override
157             public void run() {
158                 mRowsFragment.setEntranceTransitionState(true);
159             }
160         });
161         return view;
162     }
163 
setVerticalGridViewLayout(VerticalGridView listview)164     void setVerticalGridViewLayout(VerticalGridView listview) {
165         // align the top edge of item to a fixed position
166         listview.setItemAlignmentOffset(0);
167         listview.setItemAlignmentOffsetPercent(VerticalGridView.ITEM_ALIGN_OFFSET_PERCENT_DISABLED);
168         listview.setWindowAlignmentOffset(mContainerListAlignTop);
169         listview.setWindowAlignmentOffsetPercent(VerticalGridView.WINDOW_ALIGN_OFFSET_PERCENT_DISABLED);
170         listview.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE);
171     }
172 
getVerticalGridView()173     VerticalGridView getVerticalGridView() {
174         return mRowsFragment == null ? null : mRowsFragment.getVerticalGridView();
175     }
176 
getRowsFragment()177     RowsFragment getRowsFragment() {
178         return mRowsFragment;
179     }
180 
181     /**
182      * Setup dimensions that are only meaningful when the child Fragments are inside
183      * DetailsFragment.
184      */
setupChildFragmentLayout()185     private void setupChildFragmentLayout() {
186         setVerticalGridViewLayout(mRowsFragment.getVerticalGridView());
187     }
188 
189     /**
190      * Sets the selected row position with smooth animation.
191      */
setSelectedPosition(int position)192     public void setSelectedPosition(int position) {
193         setSelectedPosition(position, true);
194     }
195 
196     /**
197      * Sets the selected row position.
198      */
setSelectedPosition(int position, boolean smooth)199     public void setSelectedPosition(int position, boolean smooth) {
200         mSetSelectionRunnable.mPosition = position;
201         mSetSelectionRunnable.mSmooth = smooth;
202         if (getView() != null && getView().getHandler() != null) {
203             getView().getHandler().post(mSetSelectionRunnable);
204         }
205     }
206 
207     @Override
onStart()208     public void onStart() {
209         super.onStart();
210         setupChildFragmentLayout();
211         mRowsFragment.getView().requestFocus();
212         if (isEntranceTransitionEnabled()) {
213             // make sure recycler view animation is disabled
214             mRowsFragment.onTransitionStart();
215             mRowsFragment.setEntranceTransitionState(false);
216         }
217     }
218 
219     @Override
createEntranceTransition()220     protected Object createEntranceTransition() {
221         return sTransitionHelper.loadTransition(getActivity(),
222                 R.transition.lb_details_enter_transition);
223     }
224 
225     @Override
runEntranceTransition(Object entranceTransition)226     protected void runEntranceTransition(Object entranceTransition) {
227         sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
228                 entranceTransition);
229     }
230 
231     @Override
onEntranceTransitionEnd()232     protected void onEntranceTransitionEnd() {
233         mRowsFragment.onTransitionEnd();
234     }
235 
236 }
237